mirror of
https://github.com/XRPLF/xrpl-dev-portal.git
synced 2025-11-19 03:05:49 +00:00
Compare commits
172 Commits
clio-full-
...
payment-ch
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
36083f247a | ||
|
|
71fe97fa3d | ||
|
|
928881f03d | ||
|
|
f97f378642 | ||
|
|
03dfb1f60e | ||
|
|
9aec5a9ae8 | ||
|
|
0401a21fc6 | ||
|
|
bccad295ad | ||
|
|
a8e9273acc | ||
|
|
b2c4aa0dd2 | ||
|
|
a253e654db | ||
|
|
f3f783b07e | ||
|
|
f9fd30ef3a | ||
|
|
9a1051f3cb | ||
|
|
339b70e93c | ||
|
|
db303831af | ||
|
|
8daf8f862f | ||
|
|
6001a566c7 | ||
|
|
acc36d2081 | ||
|
|
ea0bad889a | ||
|
|
55934e03b8 | ||
|
|
1e38da684c | ||
|
|
0a90236de7 | ||
|
|
7f8e251cb2 | ||
|
|
a67dc50ef6 | ||
|
|
03370445c5 | ||
|
|
8604e68670 | ||
|
|
2fd7b5ee75 | ||
|
|
af9c7cd4a5 | ||
|
|
f76b364b2a | ||
|
|
d296f07e6a | ||
|
|
72c0384b72 | ||
|
|
d5d8df66fa | ||
|
|
e0e2b63d50 | ||
|
|
21bf3be3af | ||
|
|
451fc83deb | ||
|
|
d3e8c8f4a0 | ||
|
|
88d9fce053 | ||
|
|
da60932700 | ||
|
|
8bab684cb5 | ||
|
|
c1acd9e417 | ||
|
|
3ef97a1785 | ||
|
|
97a79550b2 | ||
|
|
7d84421565 | ||
|
|
fc337738e6 | ||
|
|
fc4c5262fb | ||
|
|
df89b5bd6e | ||
|
|
532e635573 | ||
|
|
2691f7fdf9 | ||
|
|
649e707c42 | ||
|
|
79b874cacf | ||
|
|
59371e02e0 | ||
|
|
fe9a9b41b1 | ||
|
|
228ff1a63e | ||
|
|
5c88b2a168 | ||
|
|
36d785c355 | ||
|
|
8d72c91e4f | ||
|
|
a7fd85618b | ||
|
|
8036e2628a | ||
|
|
9cd10b4c44 | ||
|
|
974441ff90 | ||
|
|
d327c69864 | ||
|
|
f161bd0331 | ||
|
|
603bcd9106 | ||
|
|
a6b4fd1ee3 | ||
|
|
1c3bcdd9b6 | ||
|
|
37e7f6e08e | ||
|
|
b6473eabb9 | ||
|
|
a603fd6b85 | ||
|
|
a2ae8909ea | ||
|
|
1f2d6af975 | ||
|
|
cf44f76240 | ||
|
|
b214189e46 | ||
|
|
bb6aab25b1 | ||
|
|
ddf36ff2dd | ||
|
|
3ac296c066 | ||
|
|
1bac248b31 | ||
|
|
ec4543c890 | ||
|
|
b82d397a66 | ||
|
|
b663d36191 | ||
|
|
7eae9064f3 | ||
|
|
623a5d30a3 | ||
|
|
0dc41bd569 | ||
|
|
4236a9fa45 | ||
|
|
2e3e8ec794 | ||
|
|
3697c919cd | ||
|
|
8b4809e619 | ||
|
|
1fa846e647 | ||
|
|
a6743f325e | ||
|
|
8076410c29 | ||
|
|
97d621f06e | ||
|
|
7ac30a63ba | ||
|
|
f92da3a9bd | ||
|
|
8ca49fce23 | ||
|
|
841327bca5 | ||
|
|
27a85302b1 | ||
|
|
5a9da8a1ae | ||
|
|
d413cc1bf7 | ||
|
|
ef40552be6 | ||
|
|
86ca76aa6b | ||
|
|
ba47d9531e | ||
|
|
e606c76d06 | ||
|
|
479d8b1e9a | ||
|
|
308779807a | ||
|
|
bf85e727b5 | ||
|
|
5842c0176e | ||
|
|
1a2d544891 | ||
|
|
ddd20605da | ||
|
|
bcf7332ae0 | ||
|
|
5078334f95 | ||
|
|
f6da72a5e4 | ||
|
|
5dcb5cb42e | ||
|
|
2fb65794c0 | ||
|
|
e3c6c8dda4 | ||
|
|
b9232fc245 | ||
|
|
5d30328345 | ||
|
|
11ad13f860 | ||
|
|
a6573b8e29 | ||
|
|
b23aa3a55e | ||
|
|
98f8cbb9d5 | ||
|
|
5c97efbdac | ||
|
|
45eb02437b | ||
|
|
7f80874c8e | ||
|
|
6d90eb4974 | ||
|
|
9dce798703 | ||
|
|
d043759f72 | ||
|
|
cd539662c4 | ||
|
|
9befa993bf | ||
|
|
16c8fdd871 | ||
|
|
d1648846d0 | ||
|
|
9ce8f3faae | ||
|
|
a27dad4cbd | ||
|
|
471c2e48df | ||
|
|
cc10aa0f94 | ||
|
|
08f2fde9e4 | ||
|
|
306e169cb5 | ||
|
|
a74231ab0d | ||
|
|
3afd06b23d | ||
|
|
0eb60e6571 | ||
|
|
72b1cdd150 | ||
|
|
a0015990e9 | ||
|
|
0bef4e48c9 | ||
|
|
f88f9d1cf0 | ||
|
|
ec84bead02 | ||
|
|
fbcccafb45 | ||
|
|
f109dc8f45 | ||
|
|
44e111acec | ||
|
|
bdcc397433 | ||
|
|
1523837d9f | ||
|
|
84e8c3e241 | ||
|
|
f1f4004bf6 | ||
|
|
29bdf2210f | ||
|
|
d1b72a5b39 | ||
|
|
ee81ed9544 | ||
|
|
f00d710f32 | ||
|
|
79e1612b72 | ||
|
|
ec1f33d4e3 | ||
|
|
e6add92430 | ||
|
|
5efad8cba7 | ||
|
|
8fe9041a96 | ||
|
|
49300a328f | ||
|
|
4ba07466e1 | ||
|
|
447b8640c8 | ||
|
|
559da0932c | ||
|
|
c7a11da4fd | ||
|
|
e57011070b | ||
|
|
5f877ebd93 | ||
|
|
a4ab945215 | ||
|
|
dba9871513 | ||
|
|
1ae3992c3a | ||
|
|
b598a607a6 | ||
|
|
5bb552db12 |
@@ -9,7 +9,7 @@ parent: contribute.html
|
||||
## 報告する
|
||||
詐欺に遭ったと思ったら、詐欺の手口や詐欺業者について、できるだけ早く、できるだけ多くの情報を集めるようにしてください。どのように行動すべきかは以下の方法を確認してください。
|
||||
|
||||
{% admonition type="warning" name="注意" %}誰もXRP Ledgerのアカウントを凍結したり、トランザクションを元に戻したりすることはできません。これはXRP Ledgerブロックチェーンの分散型設計によるものです。{% /admonition %}
|
||||
{% admonition type="warning" name="注意" %}誰もXRP Ledgerのアカウントをフリーズしたり、トランザクションを元に戻したりすることはできません。これはXRP Ledgerブロックチェーンの分散型設計によるものです。{% /admonition %}
|
||||
|
||||
1. [Xrplorerの調査チーム](https://xrplorer.com/forensics/submit)に詐欺業者のウォレットアドレスを提出してください。
|
||||
|
||||
@@ -17,14 +17,14 @@ parent: contribute.html
|
||||
|
||||
2. 最寄りの警察署に通報してください。詐欺業者が捕まれば、お金を取り戻せる場合があります。
|
||||
|
||||
3. 詐欺業者が取引所にXRPを送金した場合は、必ず取引所のサポートチームに連絡してください。取引所は詐欺業者の口座を凍結することができます。以下は、いくつかの有名な取引所のサポートリンクです。
|
||||
3. 詐欺業者が取引所にXRPを送金した場合は、必ず取引所のサポートチームに連絡してください。取引所は詐欺業者の口座をフリーズすることができます。以下は、いくつかの有名な取引所のサポートリンクです。
|
||||
|
||||
- [Binance](https://www.binance.com/en/support)
|
||||
- [Coinbase](https://help.coinbase.com/)
|
||||
- [Uphold](https://support.uphold.com/hc/en-us/requests/new)
|
||||
- [Bitrue](https://www.bitrue.com/exchange-web/footer/contactus.html)
|
||||
|
||||
4. 詐欺業者がXRP Ledger上でXRPを他のトークンと交換した場合、そのトークンの発行者に連絡してください。発行者は[詐欺業者のトラストラインを凍結する](../docs/tutorials/how-tos/use-tokens/freeze-a-trust-line.md)ことができるかもしれません。
|
||||
4. 詐欺業者がXRP Ledger上でXRPを他のトークンと交換した場合、そのトークンの発行者に連絡してください。発行者は[詐欺業者のトラストラインをフリーズする](../docs/tutorials/how-tos/use-tokens/freeze-a-trust-line.md)ことができるかもしれません。
|
||||
|
||||
詐欺業者の報告に関する詳細は、[Xrplorer Forensicsのヘルプ](https://xrplorer.com/forensics/help)をご覧ください。
|
||||
|
||||
|
||||
@@ -104,7 +104,7 @@ XRP Ledgerは、複数の[暗号署名アルゴリズム](#署名アルゴリズ
|
||||
|
||||
- マスターキーペアを無効化する。
|
||||
|
||||
- [凍結](../tokens/fungible-tokens/freezes.md#no-freeze)の機能を永久に放棄する。
|
||||
- [フリーズ](../tokens/fungible-tokens/freezes.md#no-freeze)の機能を永久に放棄する。
|
||||
|
||||
- トランザクションコスト0XRPの特別な[キーリセットトランザクション](../transactions/transaction-cost.md#key-resetトランザクション)を送信する。
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@ Checksは[Escrow](escrow.md)と[Payment Channel](../../tutorials/how-tos/use-spe
|
||||
|
||||
* Checksではトークンを送金できます。Payment ChannelとEscrowで送金できるのはXRPのみです。
|
||||
|
||||
* Checksは資金を凍結しません。Payment ChannelとEscrowでは、送金元が発行したクレームでXRPが清算されるか(Payment Channel)、または有効期限切れまたはCrypto-conditionsによってXRPがリリースされる(Escrow)までは、そのXRPを使用できません。
|
||||
* Checksは資金をフリーズしません。Payment ChannelとEscrowでは、送金元が発行したクレームでXRPが清算されるか(Payment Channel)、または有効期限切れまたはCrypto-conditionsによってXRPがリリースされる(Escrow)までは、そのXRPを使用できません。
|
||||
|
||||
* EscrowではXRPを自分自身に送金できます。ChecksではXRPを自身に送金することはできません。
|
||||
|
||||
|
||||
@@ -51,7 +51,7 @@ XRP Ledgerのすべての変更がそうであるように、取引を行うに
|
||||
|
||||
XRP Ledgerは、成行注文、指値注文、レバレッジ取引などの概念をネイティブに表現するものではありません。カスタムトークンやOfferのプロパティをクリエイティブに利用することで、いくつかは実現できるかもしれません。
|
||||
|
||||
分散型システムであるXRP Ledgerは、取引に関わる[アカウント](../../accounts/index.md)の背後にいる実際の人々や組織に関する情報を一切持っていません。また、ユーザや発行者は、様々な種類の裏付け資産を表すトークンの取引を規制するために、関連する法律に従う必要があります。[凍結](../fungible-tokens/freezes.md)や[認可トラストライン](../fungible-tokens/authorized-trust-lines.md)などの機能は、発行者が関連法規を順守できるよう意図しています。
|
||||
分散型システムであるXRP Ledgerは、取引に関わる[アカウント](../../accounts/index.md)の背後にいる実際の人々や組織に関する情報を一切持っていません。また、ユーザや発行者は、様々な種類の裏付け資産を表すトークンの取引を規制するために、関連する法律に従う必要があります。[フリーズ](../fungible-tokens/freezes.md)や[認可トラストライン](../fungible-tokens/authorized-trust-lines.md)などの機能は、発行者が関連法規を順守できるよう意図しています。
|
||||
|
||||
## 関連項目
|
||||
|
||||
|
||||
@@ -46,8 +46,8 @@ Offerオブジェクトは、他のオファーやクロスカレンシー決済
|
||||
|
||||
- 所有者が売却する資産を一切保有しなくなった場合。
|
||||
- オーナーがその資産を再度取得すると、オファーに資金が供給されるようになります。
|
||||
- 売却する資産が[凍結されたトラストライン](../fungible-tokens/freezes.md)に含まれるトークンである場合。
|
||||
- トラストラインが凍結解除されると、オファーは再び資金が供給されるようになります。
|
||||
- 売却する資産が[フリーズされたトラストライン](../fungible-tokens/freezes.md)に含まれるトークンである場合。
|
||||
- トラストラインがフリーズ解除されると、オファーは再び資金が供給されるようになります。
|
||||
- オファーが新しいトラストラインを作成する必要があるが、オーナーがその[準備金](../../accounts/reserves.md)の増加に伴う十分なXRPを持っていない場合。
|
||||
- オーナーが追加のXRPを調達するか、準備金の必要量が減少すると、オファーは自動的に使用可能になります。
|
||||
- オファーが失効した場合。([オファーの有効期限](#オファーの有効期限)を参照)
|
||||
|
||||
@@ -13,7 +13,7 @@ XRP Ledgerの認可トラストライン機能により、発行者は、発行
|
||||
|
||||
認可トラストライン機能を使用するには、発行アドレスで**RequireAuth**フラグを有効にします。その後、他のアカウントは、あなたがそのアカウントのトラストラインをあなたの発行アカウントに承認した場合にのみ、あなたが発行したトークンを保持することができます。
|
||||
|
||||
発行アドレスから[TrustSetトランザクション][]を送信し、自分のアカウントと認可するアカウントとの間のトラストラインを設定することで、トラストラインを認可することができます。トラストラインを認可した後、その認可を取り消すことはできません。(ただし、必要に応じてトラストラインを[凍結](freezes.md)することは可能です)。
|
||||
発行アドレスから[TrustSetトランザクション][]を送信し、自分のアカウントと認可するアカウントとの間のトラストラインを設定することで、トラストラインを認可することができます。トラストラインを認可した後、その認可を取り消すことはできません。(ただし、必要に応じてトラストラインを[フリーズ](freezes.md)することは可能です)。
|
||||
|
||||
トラストラインを認可するためのトランザクションは、発行アドレスの署名が必要であり、残念ながらそのアドレスのリスクエクスポージャーが増加することを意味します。
|
||||
|
||||
@@ -116,7 +116,7 @@ POST http://localhost:8088/
|
||||
|
||||
- **コンセプト:**
|
||||
- [Deposit Authorization](../../accounts/depositauth.md)
|
||||
- [トークンの凍結](freezes.md)
|
||||
- [トークンのフリーズ](freezes.md)
|
||||
- **リファレンス:**
|
||||
- [account_linesメソッド][]
|
||||
- [account_infoメソッド][]
|
||||
|
||||
@@ -6,29 +6,29 @@ seo:
|
||||
labels:
|
||||
- トークン
|
||||
---
|
||||
# トークンの凍結に関するよくある誤解
|
||||
# トークンのフリーズに関するよくある誤解
|
||||
|
||||
PayPalのような中央集権的なサービスがアカウントを停止して資金にアクセスできないようにするのと同様に、Ripple社などがXRPを凍結することができるというのはよくある誤解です。XRP Ledgerには[凍結機能](freezes.md)がありますが、これは発行トークンにのみ使用可能で、XRPには使用できません。 **XRPを凍結することは誰にもできません**。
|
||||
PayPalのような中央集権的なサービスがアカウントを停止して資金にアクセスできないようにするのと同様に、Ripple社などがXRPをフリーズすることができるというのはよくある誤解です。XRP Ledgerには[フリーズ機能](freezes.md)がありますが、これは発行トークンにのみ使用可能で、XRPには使用できません。 **XRPをフリーズすることは誰にもできません**。
|
||||
|
||||
XRP Ledgerのトークンは、[XRPとは根本的に異なる](../../../references/protocol/data-types/currency-formats.md#comparison)ものです。トークンは常にトラストライン上に存在し、それは凍結される可能性があります。XRPはアカウントに含まれており、凍結されることはありません。
|
||||
XRP Ledgerのトークンは、[XRPとは根本的に異なる](../../../references/protocol/data-types/currency-formats.md#comparison)ものです。トークンは常にトラストライン上に存在し、それはフリーズされる可能性があります。XRPはアカウントに含まれており、フリーズされることはありません。
|
||||
|
||||
## XRPは単なるRipple社のトークンではないのか?
|
||||
|
||||
いいえ、XRPはトークンとは異なります。XRPはXRP Ledger上の唯一のネイティブアセットであり、XRP Ledger上で取引を行うために必要なものです。XRPにはカウンタパーティが存在しません。つまり、誰かがXRPを保有するとき、その人は負債を保有しているのではなく、実際の通貨であるXRPを保有しているのです。この事実により、 _**<u>XRPはいかなる団体や個人によっても凍結することができません</u>**_ 。
|
||||
いいえ、XRPはトークンとは異なります。XRPはXRP Ledger上の唯一のネイティブアセットであり、XRP Ledger上で取引を行うために必要なものです。XRPにはカウンタパーティが存在しません。つまり、誰かがXRPを保有するとき、その人は負債を保有しているのではなく、実際の通貨であるXRPを保有しているのです。この事実により、 _**<u>XRPはいかなる団体や個人によってもフリーズすることができません</u>**_ 。
|
||||
|
||||
## Ripple社またはXRP Ledger財団は私のトークンを凍結することができますか?
|
||||
## Ripple社またはXRP Ledger財団は私のトークンをフリーズすることができますか?
|
||||
|
||||
XRP Ledgerは分散型であり、Ripple社やXRP Ledger財団、そして他のいかなる存在もそれをコントロールすることはできません。
|
||||
|
||||
あるトークンの発行者は、 _そのトークンに限定して_ あなたのトラストラインを凍結することができます。あなたのアカウントの他の部分や、異なる発行者のトークンを凍結することはできませんし、あなたがXRP Ledgerを使うのを止めることもできないのです。
|
||||
あるトークンの発行者は、 _そのトークンに限定して_ あなたのトラストラインをフリーズすることができます。あなたのアカウントの他の部分や、異なる発行者のトークンをフリーズすることはできませんし、あなたがXRP Ledgerを使うのを止めることもできないのです。
|
||||
|
||||
さらに、トークン発行者は、トークンを凍結する能力を自主的かつ永久的に放棄することができます。この["No Freeze"](freezes.md#no-freeze)設定は、他者がトークンの使用を止めることができないという意味で、トークンがより実際の現金のように振る舞うことを想定しています。
|
||||
さらに、トークン発行者は、トークンをフリーズする能力を自主的かつ永久的に放棄することができます。この["No Freeze"](freezes.md#no-freeze)設定は、他者がトークンの使用を止めることができないという意味で、トークンがより実際の現金のように振る舞うことを想定しています。
|
||||
|
||||
|
||||
## しかし、Ripple社がJed McCaleb氏のXRPを凍結したと聞きましたが?
|
||||
## しかし、Ripple社がJed McCaleb氏のXRPをフリーズしたと聞きましたが?
|
||||
|
||||
これは、2015年から2016年にかけて実際に起こった事件の誤報です。2013年にRipple社の創業者で同社を退社したJed McCaleb氏は、100万USドル以上のXRPをカストディ取引所であるBitstampで売却しようと試みました。Ripple社の代理人は、この売却はJed氏とRipple社が2014年に締結した契約に違反すると主張しました。Ripple社の要求により、[BitstampはJedのBitstampアカウントを凍結](https://www.coindesk.com/markets/2015/04/02/1-million-legal-fight-ensnares-ripple-bitstamp-and-jed-mccaleb/)し、裁判に持ち込まれました。この裁判は[最終的に和解](https://www.coindesk.com/markets/2016/02/12/ripple-settles-1-million-lawsuit-with-former-executive-and-founder/)となり、双方がその結果に納得したと表明しています。
|
||||
これは、2015年から2016年にかけて実際に起こった事件の誤報です。2013年にRipple社の創業者で同社を退社したJed McCaleb氏は、100万USドル以上のXRPをカストディ取引所であるBitstampで売却しようと試みました。Ripple社の代理人は、この売却はJed氏とRipple社が2014年に締結した契約に違反すると主張しました。Ripple社の要求により、[BitstampはJedのBitstampアカウントをフリーズ](https://www.coindesk.com/markets/2015/04/02/1-million-legal-fight-ensnares-ripple-bitstamp-and-jed-mccaleb/)し、裁判に持ち込まれました。この裁判は[最終的に和解](https://www.coindesk.com/markets/2016/02/12/ripple-settles-1-million-lawsuit-with-former-executive-and-founder/)となり、双方がその結果に納得したと表明しています。
|
||||
|
||||
注目すべきは、この「凍結」はXRP Ledger上で起こったものではなく、XRP Ledgerの凍結機能を使ったものでもないことです。他のカストディアン取引所と同様に、Bitstampはユーザのアカウントを凍結し、特にそれらの資金が法的紛争に巻き込まれている場合、取引や資金の引き出しを停止する権限を持っています。
|
||||
注目すべきは、この「フリーズ」はXRP Ledger上で起こったものではなく、XRP Ledgerのフリーズ機能を使ったものでもないことです。他のカストディアン取引所と同様に、Bitstampはユーザのアカウントをフリーズし、特にそれらの資金が法的紛争に巻き込まれている場合、取引や資金の引き出しを停止する権限を持っています。
|
||||
|
||||
一方、XRP Ledgerの[分散型取引所](../decentralized-exchange/index.md)で取引する場合は、自分で資産を管理するので、XRPの取引を止めることは誰にもできないのです。
|
||||
|
||||
@@ -6,39 +6,39 @@ seo:
|
||||
labels:
|
||||
- トークン
|
||||
---
|
||||
# トークンの凍結
|
||||
# トークンのフリーズ
|
||||
|
||||
発行者は発行したトークンをXRP Ledgerで凍結することができます。**これはXRP LedgerのネイティブアセットであるXRPには適用されません。**
|
||||
発行者は発行したトークンをXRP Ledgerでフリーズすることができます。**これはXRP LedgerのネイティブアセットであるXRPには適用されません。**
|
||||
|
||||
特定のケースでは、法的要件への準拠や、疑わしい活動の調査のために、取引所またはゲートウェイが、XRP以外のトークンの残高を急きょ凍結することがあります。
|
||||
特定のケースでは、法的要件への準拠や、疑わしい活動の調査のために、取引所またはゲートウェイが、XRP以外のトークンの残高を急きょフリーズすることがあります。
|
||||
|
||||
{% admonition type="success" name="ヒント" %}誰もXRP LedgerのXRPを凍結することはできません。しかし、カストディアル取引所は、自らの裁量で常に保管資金を凍結することができます。詳しくは、[凍結に関するよくある誤解](common-misconceptions-about-freezes.md)をご覧ください。{% /admonition %}
|
||||
{% admonition type="success" name="ヒント" %}誰もXRP LedgerのXRPをフリーズすることはできません。しかし、カストディアル取引所は、自らの裁量で常に保管資金をフリーズすることができます。詳しくは、[フリーズに関するよくある誤解](common-misconceptions-about-freezes.md)をご覧ください。{% /admonition %}
|
||||
|
||||
凍結については、3種類の設定があります。
|
||||
フリーズについては、3種類の設定があります。
|
||||
|
||||
* [**Individual Freeze(個別の凍結)**](#individual-freeze) - 1件の取引相手を凍結します。
|
||||
* [**Global Freeze(全体の凍結)**](#global-freeze) - 取引相手全員を凍結します。
|
||||
* [**No Freeze(凍結機能の放棄)**](#no-freeze) - 個々の取引相手の凍結機能と、Global Freeze機能を永久に放棄します。
|
||||
* [**Individual Freeze(個別のフリーズ)**](#individual-freeze) - 1件の取引相手をフリーズします。
|
||||
* [**Global Freeze(全体のフリーズ)**](#global-freeze) - 取引相手全員をフリーズします。
|
||||
* [**No Freeze(フリーズ機能の放棄)**](#no-freeze) - 個々の取引相手のフリーズ機能と、Global Freeze機能を永久に放棄します。
|
||||
|
||||
凍結対象の残高がプラス、マイナスにかかわらず、すべての凍結設定を行うことができます。通貨イシュアーまたは通貨保持者のいずれかがトラストラインを凍結できますが、通貨保持者がイシュアーを凍結しても、その影響はわずかです。
|
||||
フリーズ対象の残高がプラス、マイナスにかかわらず、すべてのフリーズ設定を行うことができます。通貨イシュアーまたは通貨保持者のいずれかがトラストラインをフリーズできますが、通貨保持者がイシュアーをフリーズしても、その影響はわずかです。
|
||||
|
||||
|
||||
## Individual Freeze
|
||||
|
||||
**Individual Freeze**機能は、[トラストライン](index.md)に関する設定です。発行アドレスがIndividual Freeze設定を有効にすると、そのトラストラインの通貨に対して以下のルールが適用されます。
|
||||
|
||||
* 凍結されたトラストラインの両当事者間の直接決済は、凍結後も可能です。
|
||||
* そのトラストラインの取引相手は、イシュアーへ直接支払う場合を除き、凍結されたトラストラインの残高を減らすことはできません。取引相手は、凍結されたイシュアンスを直接イシュアーに送信することだけが可能です。
|
||||
* 取引相手は、凍結されたトラストライン上で引き続きその他の当事者からの支払を受け取ることができます。
|
||||
* 取引相手が凍結されたトラストライン上のトークンの売りオファーを出した場合、[資金不足とみなされます](../decentralized-exchange/offers.md#オファーのライフサイクル)。
|
||||
* フリーズされたトラストラインの両当事者間の直接決済は、フリーズ後も可能です。
|
||||
* そのトラストラインの取引相手は、イシュアーへ直接支払う場合を除き、フリーズされたトラストラインの残高を減らすことはできません。取引相手は、フリーズされたイシュアンスを直接イシュアーに送信することだけが可能です。
|
||||
* 取引相手は、フリーズされたトラストライン上で引き続きその他の当事者からの支払を受け取ることができます。
|
||||
* 取引相手がフリーズされたトラストライン上のトークンの売りオファーを出した場合、[資金不足とみなされます](../decentralized-exchange/offers.md#オファーのライフサイクル)。
|
||||
|
||||
再確認: トラストラインではXRPは保持されません。XRPは凍結できません。
|
||||
再確認: トラストラインではXRPは保持されません。XRPはフリーズできません。
|
||||
|
||||
金融機関は、疑わしい活動を行う取引相手や、金融機関の利用規約に違反する取引相手にリンクしているトラストラインを凍結できます。金融機関は、同機関が運用する、XRP Ledgerに接続されているその他のシステムにおいても、その取引相手を凍結する必要があります。(凍結しないと、アドレスから金融機関経由で支払を送金することで、望ましくない活動を行うことが依然として可能となります。)
|
||||
金融機関は、疑わしい活動を行う取引相手や、金融機関の利用規約に違反する取引相手にリンクしているトラストラインをフリーズできます。金融機関は、同機関が運用する、XRP Ledgerに接続されているその他のシステムにおいても、その取引相手をフリーズする必要があります。(フリーズしないと、アドレスから金融機関経由で支払を送金することで、望ましくない活動を行うことが依然として可能となります。)
|
||||
|
||||
各個別アドレスは金融機関とのトラストラインを凍結できます。これは金融機関とその他のユーザの間の取引には影響しません。ただし、他のアドレス([運用アドレス](../../accounts/account-types.md)を含む)からその個別アドレスに対しては、その金融機関のイシュアンスを送信できなくなります。このようなIndividual Freezeは、オファーには影響しません。
|
||||
各個別アドレスは金融機関とのトラストラインをフリーズできます。これは金融機関とその他のユーザの間の取引には影響しません。ただし、他のアドレス([運用アドレス](../../accounts/account-types.md)を含む)からその個別アドレスに対しては、その金融機関のイシュアンスを送信できなくなります。このようなIndividual Freezeは、オファーには影響しません。
|
||||
|
||||
Individual Freezeは1つの通貨にのみ適用されます。特定の取引相手の複数通貨を凍結するには、アドレスが各通貨のトラストラインで、個別にIndividual Freezeを有効にする必要があります。
|
||||
Individual Freezeは1つの通貨にのみ適用されます。特定の取引相手の複数通貨をフリーズするには、アドレスが各通貨のトラストラインで、個別にIndividual Freezeを有効にする必要があります。
|
||||
|
||||
[No Freeze](#no-freeze)設定を有効にしている場合、アドレスはIndividual Freeze設定を有効にできません。
|
||||
|
||||
@@ -47,9 +47,9 @@ Individual Freezeは1つの通貨にのみ適用されます。特定の取引
|
||||
|
||||
**Global Freeze**機能は、アドレスに設定できます。発行アドレスがGlobal Freeze機能を有効にすると、その発行アドレスのすべてのトークンに対して以下のルールが適用されます:
|
||||
|
||||
* 凍結された発行アドレスのすべての取引相手は、イシュアーに直接支払う場合を除き、凍結されたアドレスへのトラストラインの残高を減らすことができません。(これはすべての[運用アドレス](../../accounts/account-types.md)にも影響します。)
|
||||
* 凍結された発行アドレスの取引相手は、発行アドレスとの直接的な支払の送受信を引き続き行うことができます。
|
||||
* 凍結アドレスによるトークンの売りオファーはすべて、[資金不足とみなされます](../decentralized-exchange/offers.md#オファーのライフサイクル)。
|
||||
* フリーズされた発行アドレスのすべての取引相手は、イシュアーに直接支払う場合を除き、フリーズされたアドレスへのトラストラインの残高を減らすことができません。(これはすべての[運用アドレス](../../accounts/account-types.md)にも影響します。)
|
||||
* フリーズされた発行アドレスの取引相手は、発行アドレスとの直接的な支払の送受信を引き続き行うことができます。
|
||||
* フリーズアドレスによるトークンの売りオファーはすべて、[資金不足とみなされます](../decentralized-exchange/offers.md#オファーのライフサイクル)。
|
||||
|
||||
再確認: アドレスはXRPを発行できません。Global FreezeはXRPには適用されません。
|
||||
|
||||
@@ -57,25 +57,25 @@ Individual Freezeは1つの通貨にのみ適用されます。特定の取引
|
||||
|
||||
また、金融機関が新しい[発行アドレス](../../accounts/account-types.md)への移行や、営業の停止を予定している場合にも、Global Freezeを有効にすることが有用です。これにより、特定の時点で資金がロックされるため、ユーザは他の通貨で取引することができなくなります。
|
||||
|
||||
Global Freezeは、当該アドレスによって発行および保有されている _すべての_ 通貨に適用されます。1つの通貨のみに対してGlobal Freezeを有効にすることはできません。一部の通貨のみを凍結できるようにしたい場合は、通貨ごとに異なるアドレスを使用してください。
|
||||
Global Freezeは、当該アドレスによって発行および保有されている _すべての_ 通貨に適用されます。1つの通貨のみに対してGlobal Freezeを有効にすることはできません。一部の通貨のみをフリーズできるようにしたい場合は、通貨ごとに異なるアドレスを使用してください。
|
||||
|
||||
アドレスのGlobal Freeze設定はいつでも有効にできます。ただし、アドレスの[No Freeze](#no-freeze)設定を有効にすると、Global Freezeを _無効にする_ ことはできません。
|
||||
|
||||
|
||||
## No Freeze
|
||||
|
||||
**No Freeze**機能をアドレスに設定すると、取引相手が発行した通貨を凍結する機能を永久に放棄します。この機能を使用すれば、企業は自社が発行した資金を「物理的なお金のように」扱うことができます。これにより、企業は顧客どうしがその資金を取引することに介入できなくなります。
|
||||
**No Freeze**機能をアドレスに設定すると、取引相手が発行した通貨をフリーズする機能を永久に放棄します。この機能を使用すれば、企業は自社が発行した資金を「物理的なお金のように」扱うことができます。これにより、企業は顧客どうしがその資金を取引することに介入できなくなります。
|
||||
|
||||
確認事項: XRPはすでに凍結できません。No Freeze機能は、XRP Ledgerで発行された他の通貨にのみ適用されます。
|
||||
確認事項: XRPはすでにフリーズできません。No Freeze機能は、XRP Ledgerで発行された他の通貨にのみ適用されます。
|
||||
|
||||
No Freeze設定には次の2つの効果があります。
|
||||
|
||||
* 発行アドレスは、すべての取引相手とのトラストラインに対してIndividual Freezeを有効にできなくなります。
|
||||
* 発行アドレスは、Global Freezeを有効にしてグローバル凍結を施行できますが、Global Freezeを _無効にする_ ことはできません。
|
||||
* 発行アドレスは、Global Freezeを有効にしてグローバルフリーズを施行できますが、Global Freezeを _無効にする_ ことはできません。
|
||||
|
||||
XRP Ledgerは金融機関に対し、その発行資金が表す債務を履行することを強制できません。このため、Global Freezeを有効にする機能を放棄しても顧客を保護できません。ただし、Global Freezeを _無効にする_ 機能を放棄することで、Global Freeze機能が一部の顧客に対して不当に適用されないようにすることができます。
|
||||
|
||||
No Freeze設定は、アドレスに対して発行される通貨と、アドレスから発行される通貨のすべてに適用されます。一部の通貨のみを凍結できるようにしたい場合は、通貨ごとに異なるアドレスを使用してください。
|
||||
No Freeze設定は、アドレスに対して発行される通貨と、アドレスから発行される通貨のすべてに適用されます。一部の通貨のみをフリーズできるようにしたい場合は、通貨ごとに異なるアドレスを使用してください。
|
||||
|
||||
No Freeze設定は、アドレスのマスターキーのシークレットキーにより署名されたトランザクションでのみ有効にできます。[レギュラーキー](../../../references/protocol/transactions/types/setregularkey.md)または[マルチシグトランザクション](../../accounts/multi-signing.md)を使用してNo Freezeを有効にすることはできません。
|
||||
|
||||
@@ -83,13 +83,13 @@ No Freeze設定は、アドレスのマスターキーのシークレットキ
|
||||
|
||||
# 関連項目
|
||||
|
||||
- [凍結コードの例](https://github.com/XRPLF/xrpl-dev-portal/tree/master/_code-samples/freeze)
|
||||
- [フリーズコードの例](https://github.com/XRPLF/xrpl-dev-portal/tree/master/_code-samples/freeze)
|
||||
- **コンセプト:**
|
||||
- [トラストラインとトークンの発行](index.md)
|
||||
- **Tutorials:**
|
||||
- [No Freezeを有効化](../../../tutorials/how-tos/use-tokens/enable-no-freeze.md)
|
||||
- [Global Freezeの実行](../../../tutorials/how-tos/use-tokens/enact-global-freeze.md)
|
||||
- [トラストラインの凍結](../../../tutorials/how-tos/use-tokens/freeze-a-trust-line.md)
|
||||
- [トラストラインのフリーズ](../../../tutorials/how-tos/use-tokens/freeze-a-trust-line.md)
|
||||
- **References:**
|
||||
- [account_linesメソッド][]
|
||||
- [account_infoメソッド][]
|
||||
|
||||
@@ -51,7 +51,7 @@ labels:
|
||||
- **Limit**: 0から[トークンの上限量](../../../references/protocol/data-types/currency-formats.md)の範囲内の数字です。支払いや他のアカウントの操作によって、(このアカウントから見た)トラストラインの残高が限度額を超えることはできません。デフォルトは`0`です。
|
||||
- **Authorized**: [Authorized Trust Lines](authorized-trust-lines.md)と併用し、このアカウントが発行するトークンを相手側に保持させることを許可するための値(true/false)です。デフォルトは`false`です。一度`true`に設定すると、元に戻すことはできません。
|
||||
- **No Ripple**: トークンがこのトラストラインを通過して[ripple](rippling.md)するかどうかを設定するための値(true/false)です。デフォルトはアカウントの"Default Ripple"設定に依存します。新しいアカウントでは"Default Ripple"はoffで、つまり`true`がNo Rippleのデフォルト値となります。通常、発行者はrippleを許可し、非発行者はコミュニティクレジットのためにトラストラインを使用していない限り、rippleを無効にするべきです。
|
||||
- **Freeze**: このトラストラインに[個別の凍結](freezes.md#individual-freeze)が適用されているかどうかを示す値(true/false)です。デフォルトは`false です。
|
||||
- **Freeze**: このトラストラインに[個別のフリーズ](freezes.md#individual-freeze)が適用されているかどうかを示す値(true/false)です。デフォルトは`false です。
|
||||
- **Quality In** および **Quality Out**: この設定により、このトラストライン上の他のアカウントで発行されたトークンを額面より少なく(または多く)評価することができます。たとえば、ステーブルコインの発行者が、オフレッジャーにある同等の資産に対してトークンの引き出しに3%の手数料を課している場合、この設定を使用して、それらのトークンを額面の97%で評価することが可能です。デフォルトは`0`で、額面価格を表しています。
|
||||
|
||||
|
||||
|
||||
@@ -73,11 +73,11 @@ KYC(Know Your Customer)やAML(Anti-Money Laundering)などのコンプライア
|
||||
|
||||
### Freezeフラグ
|
||||
|
||||
保有者アカウント内のステーブルコインを凍結することができます。これは、詐欺行為が疑われる場合、または保有を強制する場合に行うことができます。個々のトラストラインを凍結することも、グローバルに凍結することもできます。
|
||||
保有者アカウント内のステーブルコインをフリーズすることができます。これは、詐欺行為が疑われる場合、または保有を強制する場合に行うことができます。個々のトラストラインをフリーズすることも、グローバルにフリーズすることもできます。
|
||||
|
||||
逆に、トークンを凍結する能力を永久に放棄する「No Freeze」を設定することもできます。これにより、発行者がトークン同士の取引を妨害でき無くなるという意味で、そのステーブルコインはより現実の通貨に近くなります。
|
||||
逆に、トークンをフリーズする能力を永久に放棄する「No Freeze」を設定することもできます。これにより、発行者がトークン同士の取引を妨害でき無くなるという意味で、そのステーブルコインはより現実の通貨に近くなります。
|
||||
|
||||
[トークンの凍結](../freezes.md)をご覧ください。
|
||||
[トークンのフリーズ](../freezes.md)をご覧ください。
|
||||
|
||||
|
||||
### Clawbackフラグ
|
||||
|
||||
@@ -52,7 +52,7 @@ XRP Ledgerにおけるトークンは、[XRPと異なる性質](../../references
|
||||
|
||||
必要なトラストラインが設定されていれば、誰でも[Paymentトランザクション][]を送信することでトークンを発行することができます。トークンを発行者に送り返せば、トークンを「burn」することができます。また、発行者の設定により、[クロスカレンシー支払い](../payment-types/cross-currency-payments.md)やトレードでトークンをさらに生み出せるケースもあります。
|
||||
|
||||
発行者は、ユーザがトークンを送金する際に自動で差し引かれる「送金手数料」(transfer-fees.html)を設定することができます。発行者は、自分のトークンを含む取引レートの[ティックサイズ](decentralized-exchange/ticksize.md)を定義することもできます。発行者と一般アカウントのどちらも、トラストラインを[凍結](fungible-tokens/freezes.md)することができ、トラストライン内のトークンの使用方法を制限することができます。( XRPにはこのいずれも適用されません。)
|
||||
発行者は、ユーザがトークンを送金する際に自動で差し引かれる「送金手数料」(transfer-fees.html)を設定することができます。発行者は、自分のトークンを含む取引レートの[ティックサイズ](decentralized-exchange/ticksize.md)を定義することもできます。発行者と一般アカウントのどちらも、トラストラインを[フリーズ](fungible-tokens/freezes.md)することができ、トラストライン内のトークンの使用方法を制限することができます。( XRPにはこのいずれも適用されません。)
|
||||
|
||||
トークン発行の技術的な手順については、[代替可能トークンの発行](../../tutorials/how-tos/use-tokens/issue-a-fungible-token.md) をご覧ください。
|
||||
|
||||
|
||||
32
@l10n/ja/docs/concepts/tokens/nfts/dynamic-nfts.md
Normal file
32
@l10n/ja/docs/concepts/tokens/nfts/dynamic-nfts.md
Normal file
@@ -0,0 +1,32 @@
|
||||
---
|
||||
seo:
|
||||
description: ダイナミックNFTを作成し、URIを変更して参照されるデータオブジェクトを更新するオプションを提供します。
|
||||
labels:
|
||||
- 非代替性トークン, NFT
|
||||
---
|
||||
|
||||
# ダイナミックNFT (dNFT)
|
||||
|
||||
標準的なNFTは変更不可能です。一部のユースケースでは、NFTの初回Mint後に参照されるデータオブジェクトを更新する機能が便利です。例えば、延期されたイベントのコンサートチケットを代替日に更新したり、スポーツ選手のバーチャルトレーディングカードを定期的に現在の統計情報に更新したりすることができます。ダイナミックNFT(dNFT)は、このようなユースケースに柔軟性を提供します。
|
||||
|
||||
## dNFTの作成
|
||||
|
||||
新しいNFTをミントする際に、`tfMutable`フラグ(`0x00000010`)を設定して、NFTの`URI`フィールドを更新する機能を有効にします。
|
||||
|
||||
## dNFTの変更
|
||||
|
||||
`NFTokenModify`トランザクションを使用して、dNFTの`URI`フィールドを更新します。発行者または許可された発行者の`Account`、dNFTの`Owner`(`Account`アドレスと異なる場合)、dNFTの`NFTokenID`、および新しいオブジェクトデータの`URI`を指定します。
|
||||
|
||||
### NFTokenModifyトランザクションの例
|
||||
|
||||
```json
|
||||
{
|
||||
"TransactionType": "NFTokenModify",
|
||||
"Account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
|
||||
"Owner": "rogue5HnPRSszD9CWGSUz8UGHMVwSSKF6",
|
||||
"Fee": "10",
|
||||
"Sequence": 33,
|
||||
"NFTokenID": "0008C350C182B4F213B82CCFA4C6F59AD76F0AFCFBDF04D5A048C0A300000007",
|
||||
"URI": "697066733A2F2F62616679626569636D6E73347A736F6C686C6976346C746D6E356B697062776373637134616C70736D6C6179696970666B73746B736D3472746B652F5665742E706E67",
|
||||
}
|
||||
```
|
||||
@@ -46,7 +46,7 @@ _トランザクション(取引)_ は、XRP Ledgerを変更する唯一の
|
||||
署名の種類に関係なく、あらゆるタイプのトランザクションを承認できます。ただし、次の例外があります。
|
||||
|
||||
* マスター秘密鍵だけが[マスター公開鍵](../../references/protocol/transactions/types/accountset.md)を無効にできます。
|
||||
* マスター秘密鍵だけが[凍結機能を永続的に放棄](../tokens/fungible-tokens/freezes.md#no-freeze)できます。
|
||||
* マスター秘密鍵だけが[フリーズ機能を永続的に放棄](../tokens/fungible-tokens/freezes.md#no-freeze)できます。
|
||||
* アドレスからトランザクションに署名する最後の方法を削除することはできません。
|
||||
|
||||
マスターキーとレギュラーキーペアについて詳しくは、[暗号鍵](../accounts/cryptographic-keys.md)をご覧ください。
|
||||
|
||||
@@ -30,7 +30,7 @@ XRPはXRP Ledgerにて使用可能な暗号通貨です。
|
||||
|
||||
暗号通貨は _代替可能トークン_ です。 _代替可能_ とは、あるトークンを同じ価値の他のトークンに置き換えることができるという意味です。郵便切手は代替可能(相対的な価値が一致し、交換可能)であるため、手紙を出すのに50セントかかる場合、25セント切手を2枚使うか、10セント切手を5枚使って郵便料金を支払うことが出来ます。
|
||||
|
||||
暗号通貨は分散型でもあります。通貨を管理する中央機関がないのです。一度でもトランザクションがブロックチェーンに登録されると、それを変更することはできません。暗号通貨を検閲することは困難です。システムが十分に分散化されている限り、誰もトランザクションをロールバックしたり、残高を凍結したり、誰かが分散化されたデジタル資産を使うことをブロックしたりすることはできません。あらゆる参加者の間で大きな合意がなければルールが変更されることはありません。
|
||||
暗号通貨は分散型でもあります。通貨を管理する中央機関がないのです。一度でもトランザクションがブロックチェーンに登録されると、それを変更することはできません。暗号通貨を検閲することは困難です。システムが十分に分散化されている限り、誰もトランザクションをロールバックしたり、残高をフリーズしたり、誰かが分散化されたデジタル資産を使うことをブロックしたりすることはできません。あらゆる参加者の間で大きな合意がなければルールが変更されることはありません。
|
||||
|
||||
暗号通貨が投資家や開発者にとって魅力的なのは、単一の事業者が「電源を切って」暗号通貨を消滅させることができないからです。
|
||||
|
||||
|
||||
@@ -146,7 +146,7 @@ labels:
|
||||
| `send_currencies` | 文字列の配列 | このアカウントが送金できる通貨の[通貨コード][]の配列。 |
|
||||
| `validated` | ブール値 | `true`の場合、このデータは検証済みレジャーから取得されます。 |
|
||||
|
||||
{% admonition type="info" name="注記" %}アカウントが送金または受領できる通貨は、アカウントのトラストラインのチェックに基づいて定義されます。アカウントに通貨のトラストラインがあり、残高を増額できる余裕がある場合、その通貨を受領できます。トラストラインの残高を減らせる場合、アカウントはその通貨を送金できます。このメソッドでは、トラストラインが[凍結](../../../../concepts/tokens/fungible-tokens/freezes.md)または承認されているかどうかは確認 _されません_ 。{% /admonition %}
|
||||
{% admonition type="info" name="注記" %}アカウントが送金または受領できる通貨は、アカウントのトラストラインのチェックに基づいて定義されます。アカウントに通貨のトラストラインがあり、残高を増額できる余裕がある場合、その通貨を受領できます。トラストラインの残高を減らせる場合、アカウントはその通貨を送金できます。このメソッドでは、トラストラインが[フリーズ](../../../../concepts/tokens/fungible-tokens/freezes.md)または承認されているかどうかは確認 _されません_ 。{% /admonition %}
|
||||
|
||||
## 考えられるエラー
|
||||
|
||||
|
||||
@@ -223,8 +223,8 @@ rippled account_info rG1QQv2nh2gr7RCZ1P8YYcBUKCCN633jCn validated
|
||||
| `disallowIncomingPayChan` | 真偽値 | `true`の場合、このアカウントは第三者からの[ペイメントチャンネル](../../../../concepts/payment-types/payment-channels.md)の作成を許可していません。 _([DisallowIncoming amendment][]が必要です)_ |
|
||||
| `disallowIncomingTrustline` | 真偽値 | `true`の場合、このアカウントは第三者が[トラストライン](../../../../concepts/tokens/fungible-tokens/index.md)を作ることを許可していません。 _([DisallowIncoming amendment][]が必要です)_ |
|
||||
| `disallowIncomingXRP` | 真偽値 | `true`の場合、このアカウントは他者からXRPを受け取りたくありません。(これは参考情報であり、プロトコルレベルでは強制されません) |
|
||||
| `globalFreeze` | 真偽値 | `true`の場合、このアカウントによって発行されたすべてのトークンは現在凍結されています。 |
|
||||
| `noFreeze` | 真偽値 | `true`の場合、このアカウントは個々のトラストラインを凍結したり、グローバル凍結を行う機能を永久に放棄しています。詳細は[No Freeze](../../../../concepts/tokens/fungible-tokens/freezes.md#no-freeze)をご覧ください。 |
|
||||
| `globalFreeze` | 真偽値 | `true`の場合、このアカウントによって発行されたすべてのトークンは現在フリーズされています。 |
|
||||
| `noFreeze` | 真偽値 | `true`の場合、このアカウントは個々のトラストラインをフリーズしたり、グローバルフリーズを行う機能を永久に放棄しています。詳細は[No Freeze](../../../../concepts/tokens/fungible-tokens/freezes.md#no-freeze)をご覧ください。 |
|
||||
| `passwordSpent` | 真偽値 | `false`の場合、このアカウントはトランザクションコスト0の特別な[キーリセットトランザクション](../../../../concepts/transactions/transaction-cost.md#key-resetトランザクション)を送信できます。プロトコルはこのフラグを自動的にオン/オフします。 |
|
||||
| `requireAuthorization` | 真偽値 | `true`の場合、このアカウントは[認可トラストライン](../../../../concepts/tokens/fungible-tokens/authorized-trust-lines.md)を使って、発行するトークンを保持できる人を制限しています。 |
|
||||
| `requireDestinationTag` | 真偽値 | `true`の場合、このアカウントは受け取るすべての支払いに[宛先タグ](../../../../tutorials/how-tos/manage-account-settings/require-destination-tags.md)をリクエストしています。 |
|
||||
|
||||
@@ -435,8 +435,8 @@ rippled account_lines r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59
|
||||
| `no_ripple_peer` | 真偽値 | (省略される場合があります)`true`の場合、ピアアカウントはこのトラストラインで[No Rippleフラグ](../../../../concepts/tokens/fungible-tokens/rippling.md)を有効にしています。もし`false`なら、このアカウントはNo Rippleフラグを無効にしていますが、このアカウントはDefault Rippleフラグも無効にしているため、[デフォルト値](../../../protocol/ledger-data/ledger-entry-types/ripplestate.md#所有者の準備金への資金供給)とはみなされません。省略された場合、そのアカウントはこのトラストラインのNo Rippleフラグが無効で、Default Rippleが有効です。{% badge href="https://github.com/XRPLF/rippled/releases/tag/1.7.0" %}更新: rippled 1.7.0{% /badge %} |
|
||||
| `authorized` | 真偽値 | (省略される場合があります)このアカウントが[このトラストラインを承認した](../../../../concepts/tokens/fungible-tokens/authorized-trust-lines.md)場合は、`true`。省略されている場合は、`false`と同じです。 |
|
||||
| `peer_authorized` | 真偽値 | (省略される場合があります)ピアアカウントが[このトラストラインを承認した](../../../../concepts/tokens/fungible-tokens/authorized-trust-lines.md)場合は`true`。省略されている場合は、`false`と同じです。 |
|
||||
| `freeze` | 真偽値 | (省略される場合があります)このアカウントがこのトラストラインを[凍結](../../../../concepts/tokens/fungible-tokens/freezes.md)した場合は`true`。省略されている場合は、`false`と同じです。 |
|
||||
| `freeze_peer` | 真偽値 | (省略される場合があります)ピアアカウントがこのトラストラインを[凍結](../../../../concepts/tokens/fungible-tokens/freezes.md)した場合は、`true`。省略されている場合は、`false`と同じです。 |
|
||||
| `freeze` | 真偽値 | (省略される場合があります)このアカウントがこのトラストラインを[フリーズ](../../../../concepts/tokens/fungible-tokens/freezes.md)した場合は`true`。省略されている場合は、`false`と同じです。 |
|
||||
| `freeze_peer` | 真偽値 | (省略される場合があります)ピアアカウントがこのトラストラインを[フリーズ](../../../../concepts/tokens/fungible-tokens/freezes.md)した場合は、`true`。省略されている場合は、`false`と同じです。 |
|
||||
|
||||
## 考えられるエラー
|
||||
|
||||
|
||||
@@ -98,7 +98,7 @@ Clioの`ledger`コマンドは、[rippledのledgerコマンド](../ledger-method
|
||||
|
||||
| `Field` | 値 | 説明 |
|
||||
|:--------------|:------|:----------------------------------------------------|
|
||||
| `owner_funds` | 文字列 | このレジャーのすべてのトランザクションの実行後に、このOfferCreateトランザクションを送信する`Account`が保有する`TakerGets`通貨の額。この通貨額が[凍結](../../../../concepts/tokens/fungible-tokens/freezes.md)されているかどうかはチェックされません。 |
|
||||
| `owner_funds` | 文字列 | このレジャーのすべてのトランザクションの実行後に、このOfferCreateトランザクションを送信する`Account`が保有する`TakerGets`通貨の額。この通貨額が[フリーズ](../../../../concepts/tokens/fungible-tokens/freezes.md)されているかどうかはチェックされません。 |
|
||||
|
||||
リクエストで`”diff": true`を指定した場合、レスポンスにはオブジェクト`diff`が含まれます。このオブジェクトのフィールドは以下の通りです。
|
||||
|
||||
|
||||
@@ -138,7 +138,7 @@ rippled ledger current
|
||||
|
||||
| `Field` | 値 | 説明 |
|
||||
|:--------------|:-------|:----------------------------------------------------|
|
||||
| `owner_funds` | 文字列 | このレジャーのすべてのトランザクションの実行後に、このOfferCreateトランザクションを送信する`Account`が保有する`TakerGets`通貨の額。この通貨額が[凍結](../../../../concepts/tokens/fungible-tokens/freezes.md)されているかどうかはチェックされません。 |
|
||||
| `owner_funds` | 文字列 | このレジャーのすべてのトランザクションの実行後に、このOfferCreateトランザクションを送信する`Account`が保有する`TakerGets`通貨の額。この通貨額が[フリーズ](../../../../concepts/tokens/fungible-tokens/freezes.md)されているかどうかはチェックされません。 |
|
||||
|
||||
## 考えられるエラー
|
||||
|
||||
|
||||
@@ -211,8 +211,8 @@ _([AMM amendment][]により追加されました。)_
|
||||
| `amm_account` | 文字列 | AMMアカウントの[アドレス][]です。 |
|
||||
| `amount` | [通貨額][] | AMMのプールにある1つの資産の合計額。(注記:リクエストに指定した`asset` _または_ `asset2`になります。) |
|
||||
| `amount2` | [通貨額][] | AMMのプール内の他の資産の合計額。(注意:リクエストに指定した`asset` _または_ `asset2`になります。) |
|
||||
| `asset_frozen` | 真偽値 | _(XRPの場合、省略)_ `true`の場合、`amount`の通貨は現在[凍結](../../../../concepts/tokens/fungible-tokens/freezes.md)されています。 |
|
||||
| `asset2_frozen` | 真偽値 | _(XRPの場合、省略)_ `true`の場合、`amount2`の通貨は現在[凍結](../../../../concepts/tokens/fungible-tokens/freezes.md)されています。 |
|
||||
| `asset_frozen` | 真偽値 | _(XRPの場合、省略)_ `true`の場合、`amount`の通貨は現在[フリーズ](../../../../concepts/tokens/fungible-tokens/freezes.md)されています。 |
|
||||
| `asset2_frozen` | 真偽値 | _(XRPの場合、省略)_ `true`の場合、`amount2`の通貨は現在[フリーズ](../../../../concepts/tokens/fungible-tokens/freezes.md)されています。 |
|
||||
| `auction_slot` | オブジェクト | _(省略される場合があります)_ 存在する場合、現在のオークションスロットの所有者を記述した[オークションスロットオブジェクト](#オークションスロットオブジェクト)です。 |
|
||||
| `lp_token` | [通貨額][] | このAMMのLPトークンの発行残高の合計。リクエスト時に`account`フィールドで流動性プロバイダを指定した場合、その流動性プロバイダが保有するこのAMMのLPトークンの量です。 |
|
||||
| `trading_fee` | 数値 | AMMの現在の取引手数料。単位は1/100,000で、1は0.001%の手数料に相当します。 |
|
||||
|
||||
@@ -563,7 +563,7 @@ labels:
|
||||
|
||||
| `Field` | 値 | 説明 |
|
||||
| :------------------------ | :----- | ---- |
|
||||
| `transaction.owner_funds` | 文字列 | このOfferCreateトランザクションを送信する`Account`が、このトランザクション実行後に有する`TakerGets`通貨の金額。この通貨額が[凍結](../../../../concepts/tokens/fungible-tokens/freezes.md)されているかどうかはチェックされません。<br>[API v2][]では`tx_json.owner_funds`に変更されました。 |
|
||||
| `transaction.owner_funds` | 文字列 | このOfferCreateトランザクションを送信する`Account`が、このトランザクション実行後に有する`TakerGets`通貨の金額。この通貨額が[フリーズ](../../../../concepts/tokens/fungible-tokens/freezes.md)されているかどうかはチェックされません。<br>[API v2][]では`tx_json.owner_funds`に変更されました。 |
|
||||
|
||||
|
||||
## Book Changesストリーム
|
||||
|
||||
@@ -0,0 +1,192 @@
|
||||
---
|
||||
seo:
|
||||
description: あらゆる種類のトランザクションを仮実行して、結果とメタデータをプレビューします。
|
||||
labels:
|
||||
- トランザクション送信
|
||||
---
|
||||
# simulate
|
||||
[[ソース]](https://github.com/XRPLF/rippled/blob/master/src/xrpld/rpc/handlers/Simulate.cpp "ソース")
|
||||
|
||||
`simulate` メソッドは、あらゆる トランザクションを仮実行し、XRP Ledger に反映することなく、その結果やメタデータを事前に確認できます。このコマンドはネットワークにトランザクションを送信しないため、手数料は発生しません。
|
||||
|
||||
{% admonition type="warning" name="Caution" %}
|
||||
`simulate` メソッドの結果は、実際にトランザクションを送信したときと同じになるとは限りません。これは、トランザクションの処理に影響する台帳の状態が、シミュレーションと送信の間に変化する可能性があるためです。
|
||||
{% /admonition %}
|
||||
|
||||
|
||||
## リクエストのフォーマット
|
||||
|
||||
リクエストのフォーマットの例:
|
||||
|
||||
{% tabs %}
|
||||
|
||||
{% tab label="WebSocket" %}
|
||||
```json
|
||||
{
|
||||
"id": 2,
|
||||
"command": "simulate",
|
||||
"tx_json" : {
|
||||
"TransactionType" : "Payment",
|
||||
"Account" : "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn",
|
||||
"Destination" : "ra5nK24KXen9AHvsdFTKHSANinZseWnPcX",
|
||||
"Amount" : {
|
||||
"currency" : "USD",
|
||||
"value" : "1",
|
||||
"issuer" : "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
{% /tab %}
|
||||
|
||||
{% tab label="JSON-RPC" %}
|
||||
```json
|
||||
{
|
||||
"method": "simulate",
|
||||
"params": {
|
||||
"tx_json" : {
|
||||
"TransactionType" : "Payment",
|
||||
"Account" : "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn",
|
||||
"Destination" : "ra5nK24KXen9AHvsdFTKHSANinZseWnPcX",
|
||||
"Amount" : {
|
||||
"currency" : "USD",
|
||||
"value" : "1",
|
||||
"issuer" : "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
{% /tab %}
|
||||
|
||||
{% /tabs %}
|
||||
|
||||
{% try-it method="simulate" /%}
|
||||
|
||||
リクエストには以下のパラメーターが含まれます。
|
||||
|
||||
| フィールド | 型 | 必須? | 説明 |
|
||||
| --------- | ------- | --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
||||
| `tx_blob` | 文字列 | はい | シミュレーション対象のトランザクションを[バイナリフォーマット](https://xrpl.org/ja/docs/references/protocol/binary-format)で指定します。このフィールドを使用する場合、`tx_json`は同時に指定しないでください。 |
|
||||
| `tx_json` | オブジェクト | はい | シミュレーション対象のトランザクションをJSON形式で指定します。このフィールドを使用する場合は、`tx_blob`を同時に指定しないでください。 |
|
||||
| `binary` | ブール値 | いいえ | デフォルト値は`false`であり、この場合はデータとメタデータがJSON形式で返されます。`true`を指定すると、データとメタデータはバイナリフォーマットで返され、16進文字列としてシリアライズされます。 |
|
||||
|
||||
- シミュレーションで使用するトランザクションは、未署名でなければなりません。
|
||||
- `Fee`、`Sequence`、`SigningPubKey`、または`NetworkID`フィールドが指定されている場合、それらはトランザクションに使用されます。指定されていない場合は、サーバーが自動的に補完します。
|
||||
|
||||
## レスポンスのフォーマット
|
||||
|
||||
処理が成功したレスポンスの例:
|
||||
|
||||
```json
|
||||
{
|
||||
"id": 2,
|
||||
"result": {
|
||||
"applied": false,
|
||||
"engine_result": "tesSUCCESS",
|
||||
"engine_result_code": 0,
|
||||
"engine_result_message": "The simulated transaction would have been applied.",
|
||||
"ledger_index": 3,
|
||||
"meta": {
|
||||
"AffectedNodes": [
|
||||
{
|
||||
"ModifiedNode": {
|
||||
"FinalFields": {
|
||||
"Account": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn",
|
||||
"AccountTxnID": "4D5D90890F8D49519E4151938601EF3D0B30B16CD6A519D9C99102C9FA77F7E0",
|
||||
"Balance": "75159663",
|
||||
"Flags": 9043968,
|
||||
"OwnerCount": 5,
|
||||
"Sequence": 361,
|
||||
"TransferRate": 1004999999
|
||||
},
|
||||
"LedgerEntryType": "AccountRoot",
|
||||
"LedgerIndex": "13F1A95D7AAB7108D5CE7EEAF504B2894B8C674E6D68499076441C4837282BF8",
|
||||
"PreviousFields": {
|
||||
"AccountTxnID": "2B44EBE00728D04658E597A85EC4F71D20503B31ABBF556764AD8F7A80BA72F6",
|
||||
"Balance": "75169663",
|
||||
"Sequence": 360
|
||||
},
|
||||
"PreviousTxnID": "2B44EBE00728D04658E597A85EC4F71D20503B31ABBF556764AD8F7A80BA72F6",
|
||||
"PreviousTxnLgrSeq": 18555460
|
||||
}
|
||||
},
|
||||
{
|
||||
"ModifiedNode": {
|
||||
"FinalFields": {
|
||||
"Balance": {
|
||||
"currency": "USD",
|
||||
"issuer": "rrrrrrrrrrrrrrrrrrrrBZbvji",
|
||||
"value": "12.0301"
|
||||
},
|
||||
"Flags": 65536,
|
||||
"HighLimit": {
|
||||
"currency": "USD",
|
||||
"issuer": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn",
|
||||
"value": "0"
|
||||
},
|
||||
"HighNode": "0",
|
||||
"LowLimit": {
|
||||
"currency": "USD",
|
||||
"issuer": "ra5nK24KXen9AHvsdFTKHSANinZseWnPcX",
|
||||
"value": "100"
|
||||
},
|
||||
"LowNode": "0"
|
||||
},
|
||||
"LedgerEntryType": "RippleState",
|
||||
"LedgerIndex": "96D2F43BA7AE7193EC59E5E7DDB26A9D786AB1F7C580E030E7D2FF5233DA01E9",
|
||||
"PreviousFields": {
|
||||
"Balance": {
|
||||
"currency": "USD",
|
||||
"issuer": "rrrrrrrrrrrrrrrrrrrrBZbvji",
|
||||
"value": "11.0301"
|
||||
}
|
||||
},
|
||||
"PreviousTxnID": "7FFE02667225DFE39594663DEDC823FAF188AC5F036A9C2CA3259FB5379C82B4",
|
||||
"PreviousTxnLgrSeq": 9787698
|
||||
}
|
||||
}
|
||||
],
|
||||
"TransactionIndex": 0,
|
||||
"TransactionResult": "tesSUCCESS",
|
||||
"delivered_amount": {
|
||||
"currency": "USD",
|
||||
"issuer": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn",
|
||||
"value": "1"
|
||||
}
|
||||
},
|
||||
"tx_json": {
|
||||
"Account": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn",
|
||||
"DeliverMax": {
|
||||
"currency": "USD",
|
||||
"issuer": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn",
|
||||
"value": "1"
|
||||
},
|
||||
"Destination": "ra5nK24KXen9AHvsdFTKHSANinZseWnPcX",
|
||||
"Fee": "10",
|
||||
"Sequence": 360,
|
||||
"TransactionType": "Payment"
|
||||
}
|
||||
},
|
||||
"status": "success",
|
||||
"type": "response"
|
||||
}
|
||||
```
|
||||
|
||||
レスポンスは[標準フォーマット][]に従っており、正常に完了した場合は結果に次のフィールドが含まれています。
|
||||
|
||||
| フィールド | 型 | 説明 |
|
||||
| -------------- | ------ | ----------- |
|
||||
| `tx_json` | オブジェクト | 自動補完された値を含む、シミュレーションされたトランザクション。`binary`が`false`の場合に含まれます。 |
|
||||
| `tx_blob` | 文字列 | 自動補完された値を含む、シリアライズされたシミュレーションされたトランザクション。`binary`が`true`の場合に含まれます。 |
|
||||
| `ledger_index` | [レジャーインデックス](https://xrpl.org/ja/docs/references/protocol/data-types/basic-data-types#レジャーインデックス) | このトランザクションが含まれていたであろうレジャーインデックス。 |
|
||||
| `meta` | オブジェクト | トランザクションの結果を示すメタデータ。台帳に含まれないことを意味するコード(たとえば TEC 以外のコード)でトランザクションが失敗した場合は含まれません。`binary`が`false`の場合に含まれます。 |
|
||||
| `meta_blob` | 文字列 | トランザクションの結果を示すメタデータ。台帳に含まれないことを意味するコード(たとえば TEC 以外のコード)でトランザクションが失敗した場合は含まれません。`binary`が`true`の場合に含まれます。 |
|
||||
|
||||
|
||||
## 考えられるエラー
|
||||
|
||||
* `invalidParams` - 1つ以上のフィールドの指定が正しくないか、1つ以上の必須フィールドが指定されていません。
|
||||
* `transactionSigned` - トランザクションが署名済みです。シミュレーションで使用するトランザクションは、未署名でなければなりません。
|
||||
|
||||
{% raw-partial file="/docs/_snippets/common-links.md" /%}
|
||||
@@ -24,7 +24,7 @@ XRP Ledgerには2種類の通貨、XRPと[トークン](../../../concepts/tokens
|
||||
| 最小値: `0` (負の値はありません) | 最小値: `-9999999999999999e80` ゼロでない絶対値の最小値: `1000000000000000e-96`
|
||||
| 最大値 `100000000000` (10<sup>11</sup>) XRP (`100000000000000000` (10<sup>17</sup>) "drops") | 最大値 `9999999999999999e80` |
|
||||
| 最小の精度: "drop" (0.000001 XRP) | 小数点以下15桁の精度 |
|
||||
| [凍結](../../../concepts/tokens/fungible-tokens/freezes.md)できません | 発行者は残高を[凍結](../../../concepts/tokens/fungible-tokens/freezes.md)することができます |
|
||||
| [フリーズ](../../../concepts/tokens/fungible-tokens/freezes.md)できません | 発行者は残高を[フリーズ](../../../concepts/tokens/fungible-tokens/freezes.md)することができます |
|
||||
| 送金手数料はかかりません。XRP同士の支払いは常に直接行われます | 間接的な[パス](../../../concepts/tokens/fungible-tokens/paths.md)を取ることができ、各発行者は一定の[送金手数料](../../../concepts/tokens/transfer-fees.md)を請求できます |
|
||||
| [ペイメントチャンネル](../../../concepts/payment-types/payment-channels.md)と[エスクロー](../../../concepts/payment-types/escrow.md)で使用できます | ペイメントチャネルやエスクローには対応していません |
|
||||
|
||||
|
||||
@@ -98,8 +98,8 @@ AccountRootオブジェクトは`Flags`フィールドに以下のフラグを
|
||||
| `lsfDisallowIncomingPayChan` | `0x10000000` | 268435456 | `asfDisallowIncomingPayChan` | このアカウントを宛先とするペイメントチャネルの作成をブロックします。 _([DisallowIncoming Amendment][]により追加されました。)_ |
|
||||
| `lsfDisallowIncomingTrustline` | `0x20000000` | 536870912 | `asfDisallowIncomingTrustline` | このアカウントに対するトラストラインの作成をブロックします。 _([DisallowIncoming Amendment][]により追加されました。)_ |
|
||||
| `lsfDisallowXRP` | `0x00080000` | 524288 | `asfDisallowXRP` | クライアントアプリケーションはこのアカウントにXRPを送金しないでください。`rippled`により強制されるものではありません。 |
|
||||
| `lsfGlobalFreeze` | `0x00400000` | 4194304 | `asfGlobalFreeze` | このアドレスが発行するすべての資産が凍結されます。 |
|
||||
| `lsfNoFreeze` | `0x00200000` | 2097152 | `asfNoFreeze` | このアドレスは、このアドレスに接続しているトラストラインを凍結できません。一度有効にすると、無効にできません。 |
|
||||
| `lsfGlobalFreeze` | `0x00400000` | 4194304 | `asfGlobalFreeze` | このアドレスが発行するすべての資産がフリーズされます。 |
|
||||
| `lsfNoFreeze` | `0x00200000` | 2097152 | `asfNoFreeze` | このアドレスは、このアドレスに接続しているトラストラインをフリーズできません。一度有効にすると、無効にできません。 |
|
||||
| `lsfPasswordSpent` | `0x00010000` | 65536 | (なし) | このアカウントは無料のSetRegularKeyトランザクションを使用しています。 |
|
||||
| `lsfRequireAuth` | `0x00040000` | 262144 | `asfRequireAuth` | このアカウントは、他のユーザがこのアカウントのトークンを保有することを個別に承認する必要があります。 |
|
||||
| `lsfRequireDestTag` | `0x00020000` | 131072 | `asfRequireDest` | 受信ペイメントには宛先タグの指定が必要です。 |
|
||||
|
||||
@@ -80,8 +80,8 @@ labels:
|
||||
| `lsfHighAuth` | `0x00080000` | 524288 | `tfSetAuth` | 高位アカウントにより、低位アカウントが高位アカウントのイシュアンスを保有することが承認されています。 |
|
||||
| `lsfLowNoRipple` | `0x00100000` | 1048576 | `tfSetNoRipple` | 低位アカウントで、このトラストラインから、同じアカウントのNoRippleフラグが設定されている他のトラストラインへの[Ripplingが無効化されています](../../../../concepts/tokens/fungible-tokens/rippling.md)。 |
|
||||
| `lsfHighNoRipple` | `0x00200000` | 2097152 | `tfSetNoRipple` | 高位アカウントで、このトラストラインから、同じアカウントのNoRippleフラグが設定されている他のトラストラインへの[Ripplingが無効化されています](../../../../concepts/tokens/fungible-tokens/rippling.md)。 |
|
||||
| `lsfLowFreeze` | `0x00400000` | 4194304 | `tfSetFreeze` | 低位アカウントがトラストラインを凍結しており、高位アカウントから資産を移動できません。 |
|
||||
| `lsfHighFreeze` | `0x00800000` | 8388608 | `tfSetFreeze` | 高位アカウントがトラストラインを凍結しており、低位アカウントから資産を移動できません。 |
|
||||
| `lsfLowFreeze` | `0x00400000` | 4194304 | `tfSetFreeze` | 低位アカウントがトラストラインをフリーズしており、高位アカウントから資産を移動できません。 |
|
||||
| `lsfHighFreeze` | `0x00800000` | 8388608 | `tfSetFreeze` | 高位アカウントがトラストラインをフリーズしており、低位アカウントから資産を移動できません。 |
|
||||
|
||||
トラストラインによって接続された2つのアカウントは、[TrustSetトランザクション][]を使用して、それぞれの設定を変更することができます。
|
||||
|
||||
|
||||
@@ -45,7 +45,7 @@ labels:
|
||||
| `tecINVARIANT_FAILED` | 147 | このトランザクションを実行しようとしたところ、不変性チェックが失敗しました。[EnforceInvariants Amendment][]により追加されました。このエラーを再現できる場合は、[問題を報告](https://github.com/XRPLF/rippled/issues)してください。 |
|
||||
| `tecKILLED` | 150 | [OfferCreateトランザクション][]がtfFillOrKillフラグを指定しましたが、トランザクションを確定できなかったため、このトランザクションは取り消されました。_([fix1578 Amendment][]により追加されました。)_ |
|
||||
| `tecMAX_SEQUENCE_REACHED` | 153 | シーケンス番号フィールドはすでに最大値に達しています。これには`MintedNFTokens`フィールドも含まれます。 _([NonFungibleTokensV1_1 amendment][]により追加されました。)_ |
|
||||
| `tecNEED_MASTER_KEY` | 142 | このトランザクションはマスターキーを必要とする変更([マスターキーの無効化または残高凍結能力の放棄](../types/accountset.md#accountsetのフラグ)など)を試みました。|
|
||||
| `tecNEED_MASTER_KEY` | 142 | このトランザクションはマスターキーを必要とする変更([マスターキーの無効化または残高フリーズ能力の放棄](../types/accountset.md#accountsetのフラグ)など)を試みました。|
|
||||
| `tecNFTOKEN_BUY_SELL_MISMATCH` | 155 | [NFTokenAcceptOfferトランザクション][]は、非代替性トークンの購入と売却に関する対応しないオファーをマッチングさせようとしました。 _([NonFungibleTokensV1_1 amendment][]により追加されました。)_ |
|
||||
| `tecNFTOKEN_OFFER_TYPE_MISMATCH` | 156 | トランザクションで指定されたオファーのうち、1つまたは複数について、オファーの種類が適切ではありませんでした。(例えば、`NFTokenSellOffer`フィールドに購入オファーが指定されていました。) _([NonFungibleTokensV1_1 amendment][]により追加されました。)_ |
|
||||
| `tecNO_ALTERNATIVE_KEY` | 130 | トランザクションが唯一の[トランザクション承認](../../../../concepts/transactions/index.md#トランザクションの承認)メソッドを削除しようとしました。これは、レギュラーキーを削除する[SetRegularKeyトランザクション][]、SignerListを削除する[SignerListSetトランザクション][]、またはマスターキーを無効にする[AccountSetトランザクション][]である可能性があります。(`rippled` 0.30.0より前のバージョンでは、このトランザクションは`tecMASTER_DISABLED`と呼ばれていました。) |
|
||||
|
||||
@@ -82,8 +82,8 @@ AccountSetトランザクションは、[XRP Ledgerのアカウント](../../led
|
||||
| `asfDisallowIncomingPayChan` | 14 | `lsfDisallowIncomingPayChan` | ペイメントチャネルの着信をブロックします。_([DisallowIncoming amendment][] が必要です)_。 |
|
||||
| `asfDisallowIncomingTrustline` | 15 | `lsfDisallowIncomingTrustline` | トラストラインの着信をブロックします。_([DisallowIncoming amendment][] が必要です)_。 |
|
||||
| `asfDisallowXRP` | 3 | `lsfDisallowXRP` | XRPがこのアカウントに送信されないようにします(勧告的なもので、XRP Ledgerのプロトコルでは強制されません)。 |
|
||||
| `asfGlobalFreeze` | 7 | `lsfGlobalFreeze` | このアカウントによって発行されたすべての資産を[凍結](../../../../concepts/tokens/fungible-tokens/freezes.md)します。 |
|
||||
| `asfNoFreeze` | 6 | `lsfNoFreeze` | [個々のトラストラインの凍結またはGlobal Freezeの無効化](../../../../concepts/tokens/fungible-tokens/freezes.md)の機能を永続的に放棄します。このフラグは、有効にした後は無効にできません。 |
|
||||
| `asfGlobalFreeze` | 7 | `lsfGlobalFreeze` | このアカウントによって発行されたすべての資産を[フリーズ](../../../../concepts/tokens/fungible-tokens/freezes.md)します。 |
|
||||
| `asfNoFreeze` | 6 | `lsfNoFreeze` | [個々のトラストラインのフリーズまたはGlobal Freezeの無効化](../../../../concepts/tokens/fungible-tokens/freezes.md)の機能を永続的に放棄します。このフラグは、有効にした後は無効にできません。 |
|
||||
| `asfRequireAuth` | 2 | `lsfRequireAuth` | このアドレスによって発行された残高をユーザが保持することについて、承認を要求します。アドレスにトラストラインが接続されていない場合のみ有効にできます。 |
|
||||
| `asfRequireDest` | 1 | `lsfRequireDestTag` | トランザクションをこのアカウントに送信するための宛先タグを要求します。 |
|
||||
|
||||
|
||||
@@ -63,7 +63,7 @@ AMMを表す[AMMエントリ][]と[特殊なAccountRootエントリ](../../ledge
|
||||
| `terNO_ACCOUNT` | リクエストで参照されたいずれかのアカウントが存在しません。|
|
||||
| `tecNO_AUTH` | 送信者は資産(`Amount`または`Amount2`)のいずれかを保有する権限がありません。 |
|
||||
| `tecNO_LINE` | 送信者は資産(`Amount`または`Amount2`)のうちいずれか1つに対するトラストラインを保有していません。 |
|
||||
| `tecFROZEN` | 資産(`Amount`または`Amount2`)の少なくとも1つが現在[凍結](../../../../concepts/tokens/fungible-tokens/freezes.md)されています。 |
|
||||
| `tecFROZEN` | 資産(`Amount`または`Amount2`)の少なくとも1つが現在[フリーズ](../../../../concepts/tokens/fungible-tokens/freezes.md)されています。 |
|
||||
| `tecUNFUNDED_AMM` | 送信者は`Amount`と`Amount2`で指定された金額をAMMに入金するための十分な資金を保有していません。 |
|
||||
| `tecAMM_EXISTS` | この通貨ペアを扱っているAMMが既に存在しています。 |
|
||||
|
||||
|
||||
@@ -128,7 +128,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)されているトークンを預けようとしました。 |
|
||||
| `tecINSUF_RESERVE_LINE` | このトランザクションの送信者は、この処理による[準備金要件](../../../../concepts/accounts/reserves.md)の増加の対象であり、LPトークンを保持するための新しいトラストラインが必要で、そのための追加の所有者準備金分のXRPを保有していないためと思われます。 |
|
||||
| `tecUNFUNDED_AMM` | 送信者の残高が、指定された預け入れを行うのに十分な量ではありません。 |
|
||||
| `temBAD_AMOUNT` | トランザクションで指定された金額が無効です。例えば、金額がマイナスなど。 |
|
||||
|
||||
@@ -114,7 +114,7 @@ AMMWithdrawトランザクションは、以下のように[`Flags`フィール
|
||||
| `tecAMM_BALANCE` | トランザクションによって、プールから1つの資産をすべて引き出そうとしている、もしくは`tfWithdrawAll`の場合に端数処理によって0以外の金額が残ってしまっています。 |
|
||||
| `tecAMM_FAILED` | 例えば、`EPrice`フィールドに指定された有効価格が低過ぎる場合など、出金に関する条件が成立しませんでした。 |
|
||||
| `tecAMM_INVALID_TOKENS` | トークンペアのAMMが存在しないか、計算の結果、引き出し額がゼロに丸められました。 |
|
||||
| `tecFROZEN` | トランザクションは[凍結](../../../../concepts/tokens/fungible-tokens/freezes.md)されたトークンを引き出そうとしました。 |
|
||||
| `tecFROZEN` | トランザクションは[フリーズ](../../../../concepts/tokens/fungible-tokens/freezes.md)されたトークンを引き出そうとしました。 |
|
||||
| `tecINSUF_RESERVE_LINE` | トランザクションの送信者は、このトランザクションを処理するための[準備金要件](../../../../concepts/accounts/reserves.md)の増加に対応できません。おそらく、引き出される資産の1つを保持するために少なくとも1つの新しいトラストラインが必要ですが、新しいトラストラインのための追加の所有者準備金分のXRPを持っていないためでしょう。 |
|
||||
| `tecNO_AUTH` | 送信者は、引き出し資産のいずれかを保有する権限を有していません。 |
|
||||
| `temMALFORMED` | トランザクションで無効なフィールドの組み合わせが指定されました。[AMMWithdrawモード](#ammwithdrawモード)をご覧ください。 |
|
||||
|
||||
@@ -45,7 +45,7 @@ _([Checks Amendment][]が必要です)_
|
||||
- `Destination`がトランザクションの送信者である場合、トランザクションは結果コード`temREDUNDANT`で失敗します。
|
||||
- `Destination`[アカウント](../../../../concepts/accounts/index.md)がレジャーに存在していない場合、トランザクションは結果コード`tecNO_DST`で失敗します。
|
||||
- `Destination`アカウントでRequireDestフラグが有効であるが、トランザクションに`DestinationTag`フィールドが含まれていない場合、トランザクションは結果コード`tecDST_TAG_NEEDED`で失敗します。
|
||||
- `SendMax`に[凍結](../../../../concepts/tokens/fungible-tokens/freezes.md)されているトークンが指定されている場合、トランザクションは結果コード`tecFROZEN`で失敗します。
|
||||
- `SendMax`に[フリーズ](../../../../concepts/tokens/fungible-tokens/freezes.md)されているトークンが指定されている場合、トランザクションは結果コード`tecFROZEN`で失敗します。
|
||||
- トランザクションの`Expiration`が過去の日時である場合、トランザクションは結果コード`tecEXPIRED`で失敗します。
|
||||
- Checkの追加後に送金元が[所有者準備金](../../../../concepts/accounts/reserves.md#所有者準備金)条件を満たすのに十分なXRPを保有していない場合、トランザクションは結果コード`tecINSUFFICIENT_RESERVE`で失敗します。
|
||||
- Checkの送金元または送金先のいずれかがレジャーでこれ以上のオブジェクトを所有できない場合、トランザクションは結果コード`tecDIR_FULL`で失敗します。
|
||||
|
||||
@@ -98,7 +98,7 @@ _([NonFungibleTokensV1_1 amendment][]により追加されました)_
|
||||
| `temMALFORMED` | トランザクションのフォーマットが正しくありません。たとえば、`NFTokenSellOffer`と`NFTokenBuyOffer`のどちらも指定されていないか、`NFTokenBrokerFee`に負の値が指定されています。|
|
||||
| `tecCANT_ACCEPT_OWN_NFTOKEN_OFFER` | 購入者と販売者が同じアカウントになっています。 |
|
||||
| `tecEXPIRED` | トランザクションで指定されたオファーの有効期限が既に切れています。 |
|
||||
| `tecINSUFFICIENT_FUNDS` | 購入者が申し出た金額を全額持っていない。購入額がXRPで指定されている場合、[所有者準備金](../../../../concepts/accounts/reserves.md)が原因である可能性があります。購入額がトークンである場合、トークンが[凍結](../../../../concepts/tokens/fungible-tokens/freezes.md) されていることが原因と考えられます。 |
|
||||
| `tecINSUFFICIENT_FUNDS` | 購入者が申し出た金額を全額持っていない。購入額がXRPで指定されている場合、[所有者準備金](../../../../concepts/accounts/reserves.md)が原因である可能性があります。購入額がトークンである場合、トークンが[フリーズ](../../../../concepts/tokens/fungible-tokens/freezes.md) されていることが原因と考えられます。 |
|
||||
| `tecINSUFFICIENT_PAYMENT` | ブローカーモードにおいて、提示された購入額は、`BrokerFee` _および_ `NFToken`の売却コストを支払うには十分な額ではありません。 |
|
||||
| `tecOBJECT_NOT_FOUND` | トランザクションで指定されたオファーがレジャーに存在しません。 |
|
||||
| `tecNFTOKEN_BUY_SELL_MISMATCH` | ブローカーモードにおいて、2つのオファーが有効なマッチングではありません。例えば、販売者が購入者の提示額よりも高い金額を提示している、購入と売却のオファーが異なる通貨で提示されている、販売者が購入者や ブローカーとは異なる販売先を指定している、などです。 |
|
||||
|
||||
@@ -59,14 +59,14 @@ NFTokenCreateOfferタイプのトランザクションは、以下のように[`
|
||||
| `temBAD_EXPIRATION` | 指定された`Expiration`は無効です(例:`0`)。 |
|
||||
| `tecDIR_FULL` | 送信者がレジャーにすでにあまりにも多くのオブジェクトを所有しているか、またはこのトークンの売買のオファーがあまりにも多く存在しています。 |
|
||||
| `tecEXPIRED` | 指定された`Expiration`の時間は既に経過しています。 |
|
||||
| `tecFROZEN` | `Amount`はトークンで、このオファーからトークンを受け取るトラストラインは[凍結](../../../../concepts/tokens/fungible-tokens/freezes.md)されています。これは売却者のトラストラインか、`NFToken`の発行者のトラストライン(`NFToken`に送金手数料がある場合)である可能性があります。 |
|
||||
| `tecFROZEN` | `Amount`はトークンで、このオファーからトークンを受け取るトラストラインは[フリーズ](../../../../concepts/tokens/fungible-tokens/freezes.md)されています。これは売却者のトラストラインか、`NFToken`の発行者のトラストライン(`NFToken`に送金手数料がある場合)である可能性があります。 |
|
||||
| `tecINSUFFICIENT_RESERVE` | 送信者はこのオファーを提示した後、[所有者準備金](../../../../concepts/accounts/reserves.md)を満たすのに十分なXRPを持っていません。 |
|
||||
| `tecNO_DST` | `Destination`に指定されたアカウントがレジャーに存在しません。 |
|
||||
| `tecNO_ENTRY` | `NFToken`フィールドで指定したアカウントは所有していません。 |
|
||||
| `tecNO_ISSUER` | `Amount`フィールドで指定した発行者が存在しません。 |
|
||||
| `tecNO_LINE` | `Amount`フィールドはトークンですが、`NFToken`の発行者はそのトークンのトラストラインを持っておらず、`NFToken`は[`lsfTrustLine`フラグ](../../data-types/nftoken.md#nftoken-フラグ)が有効ではありません。 |
|
||||
| `tecNO_PERMISSION` | `Destination`アカウントが着信する NFTokenOffer をブロックします。 _([DisallowIncoming amendment][] が必要です。)_
|
||||
| `tecUNFUNDED_OFFER` | 購入オファーの場合、送信者は`Amount`フィールドで指定された通貨を利用可能です。もし`Amount`がXRPである場合、これは準備不足によるものかもしれません。もし`Amount`がトークンである場合、これは[凍結](../../../../concepts/tokens/fungible-tokens/freezes.md)されている可能性があります。 |
|
||||
| `tecUNFUNDED_OFFER` | 購入オファーの場合、送信者は`Amount`フィールドで指定された通貨を利用可能です。もし`Amount`がXRPである場合、これは準備不足によるものかもしれません。もし`Amount`がトークンである場合、これは[フリーズ](../../../../concepts/tokens/fungible-tokens/freezes.md)されている可能性があります。 |
|
||||
| `tefNFTOKEN_IS_NOT_TRANSFERABLE` | `NFToken`は[`lsfTransferable`フラグ](../../data-types/nftoken.md#nftoken-flags)が無効になっており、このトランザクションでは`NFToken`を発行者に転送したり発行者から転送したりすることはできません。 |
|
||||
|
||||
{% raw-partial file="/docs/_snippets/common-links.md" /%}
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
---
|
||||
html: nftokenmint.html
|
||||
parent: transaction-types.html
|
||||
seo:
|
||||
description: NFTokenMintを使用して新規NFTを発行する。
|
||||
labels:
|
||||
@@ -62,6 +60,7 @@ NFTokenMint型のトランザクションでは、以下のように[`Flags`フ
|
||||
| `tfOnlyXRP` | `0x00000002` | 2 | 発行された`NFToken`はXRPでのみ売買が可能です。これは、トークンに送金手数料がかかり、発行者がXRP以外のトークンで手数料を受け取りたくない場合に望ましいでしょう。 |
|
||||
| `tfTrustLine` | `0x00000004` | 4 | **非推奨** 発行者が、発行した`NFToken`を転送する際に受け取る手数料を保有するために、自動的に[トラストライン](../../../../concepts/tokens/fungible-tokens/index.md) を作成します。[fixRemoveNFTokenAutoTrustLine Amendment][]により、このフラグの設定は無効となります。 |
|
||||
| `tfTransferable` | `0x00000008` | 8 | 発行された`NFToken`は他の人に譲渡することができます。このフラグが _有効でない_ 場合、トークンは _発行者から_ 、または _発行者へ_ のみ転送することができます。 |
|
||||
| `tfMutable` | `0x00000010` | 16 | 発行された`NFToken`の`URI`フィールドは、`NFTokenModify`トランザクションを使用して更新することができます。 |
|
||||
|
||||
|
||||
## 追加情報の埋め込み
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
---
|
||||
seo:
|
||||
description: ダイナミックNFTを変更します。
|
||||
labels:
|
||||
- 非代替性トークン, トークン, NFT
|
||||
title:
|
||||
- NFTokenModify
|
||||
---
|
||||
# NFTokenModify
|
||||
[[ソース]](https://github.com/XRPLF/rippled/blob/master/src/xrpld/app/tx/detail/NFTokenModify.cpp "ソース")
|
||||
|
||||
`NFTokenModify`は、NFTの`URI`フィールドを別のURIに変更し、NFTのサポートデータを更新するために使用されます。NFTは、`tfMutable`フラグが設定された状態でミントされている必要があります。[ダイナミックNFT](../../../../concepts/tokens/nfts/dynamic-nfts.md)をご覧ください。
|
||||
|
||||
## {% $frontmatter.seo.title %} JSONの例
|
||||
|
||||
|
||||
```json
|
||||
{
|
||||
"TransactionType": "NFTokenModify",
|
||||
"Account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
|
||||
"Owner": "rogue5HnPRSszD9CWGSUz8UGHMVwSSKF6",
|
||||
"Fee": "10",
|
||||
"Sequence": 33,
|
||||
"NFTokenID": "0008C350C182B4F213B82CCFA4C6F59AD76F0AFCFBDF04D5A048C0A300000007",
|
||||
"URI": "697066733A2F2F62616679626569636D6E73347A736F6C686C6976346C746D6E356B697062776373637134616C70736D6C6179696970666B73746B736D3472746B652F5665742E706E67"
|
||||
}
|
||||
```
|
||||
|
||||
{% raw-partial file="/@l10n/ja/docs/_snippets/tx-fields-intro.md" /%}
|
||||
|
||||
| フィールド | JSONの型 | [内部の型][] | 説明 |
|
||||
|:------------------|:---------|:-------------|:-------------------|
|
||||
| `TransactionType` | 文字列 | UINT16 | `NFTokenModify` |
|
||||
| `Account` | 文字列 | AccountID | NFTの発行者または許可されたアカウントの一意のアドレス。 |
|
||||
| `Owner` | 文字列 | AccountID | _(任意)_ NFTの所有者のアドレス。`Account`と`Owner`が同じアドレスの場合、このフィールドは省略します。 |
|
||||
| `NFTokenID` | 文字列 | Hash256 | NFTを識別する一意のID。 |
|
||||
| `URI` | 文字列 | Blob | _(任意)_ 最大256バイトの任意のデータ。JSONでは、16進数の文字列としてエンコードされます。[`xrpl.convertStringToHex`](https://js.xrpl.org/modules.html#convertStringToHex)ユーティリティメソッドを使用してURIを16進数に変換できます。これは、NFTに関連するデータまたはメタデータを指すURIです。URIはHTTPまたはHTTPS URL、IPFS URI、マグネットリンク、[RFC 2379 "data" URL](https://datatracker.ietf.org/doc/html/rfc2397)としてエンコードされた即値データ、または発行者固有のエンコードをデコードできます。URIは検証されません。URIを指定しない場合、既存のURIは削除されます。 |
|
||||
|
||||
## エラーケース
|
||||
|
||||
すべてのトランザクションで発生する可能性のあるエラーに加えて、{% $frontmatter.seo.title %}トランザクションでは、次の[トランザクション結果コード](../transaction-results/index.md)が発生する可能性があります。
|
||||
|
||||
| エラーコード | 説明 |
|
||||
|:-------------------|:-----------|
|
||||
| `tecNO_PERMISSION` | `tfMutable`フラグが有効になっていないため、`URI`フィールドを更新できません。また、`Account`フィールドがNFTの発行者または許可された発行者でない場合、このエラーを受け取ることがあります。 |
|
||||
|
||||
{% raw-partial file="/docs/_snippets/common-links.md" /%}
|
||||
@@ -67,7 +67,7 @@ OfferCreate型のトランザクションについては、[`Flags`フィール
|
||||
| `temBAD_CURRENCY` | トランザクションで通貨コードが"XRP"のトークンが指定された場合に発生します。 |
|
||||
| `temBAD_ISSUER` | トランザクションが無効な`issuer`値を持つトークンを指定した場合に発生します。 |
|
||||
| `tecNO_ISSUER` | トランザクションで、`issuer`の値が台帳の有効化されたアカウントでないトークンを指定した場合に発生します。|
|
||||
| `tecFROZEN` | [凍結](../../../../concepts/tokens/fungible-tokens/freezes.md)されたトラストライン(ローカルおよびグローバルの凍結を含む)上のトークンを含むトランザクションの場合に発生します。 |
|
||||
| `tecFROZEN` | [フリーズ](../../../../concepts/tokens/fungible-tokens/freezes.md)されたトラストライン(ローカルおよびグローバルのフリーズを含む)上のトークンを含むトランザクションの場合に発生します。 |
|
||||
| `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)を使用しているトークンを含むトランザクションで、トークンを受け取るトラストラインが存在するが認証されていない場合に発生します。 |
|
||||
|
||||
@@ -59,7 +59,7 @@ Paymentトランザクションタイプは、いくつかの異なるタイプ
|
||||
| Paymentの種類 | `Amount` | `SendMax` | `Paths` | `Address` = `Destination`? | 説明 |
|
||||
| :--------------------------------- | :---------------------------------- | :---------------------------------- | :--------- | :------------------------- | ---- |
|
||||
| [XRP同士の直接支払い][] | 文字列 (XRP) | 省略 | 省略 | いいえ | アカウント間でへ直接XRPを送金します。常に正確な金額を送信します。基本的な[取引コスト](../../../../concepts/transactions/transaction-cost.md)以外の手数料は適用されません。 |
|
||||
| [発行通貨の作成・償還][] | オブジェクト | オブジェクト (任意) | 任意 | いいえ | XRP Ledgerに追跡されているXRP以外の通貨や資産の量を増減させます。[送金手数料](../../../../concepts/tokens/transfer-fees.md)と[凍結](../../../../concepts/tokens/fungible-tokens/freezes.md)は、直接送金・換金する際には適用されません。 |
|
||||
| [発行通貨の作成・償還][] | オブジェクト | オブジェクト (任意) | 任意 | いいえ | XRP Ledgerに追跡されているXRP以外の通貨や資産の量を増減させます。[送金手数料](../../../../concepts/tokens/transfer-fees.md)と[フリーズ](../../../../concepts/tokens/fungible-tokens/freezes.md)は、直接送金・換金する際には適用されません。 |
|
||||
| [クロスカレンシー(通貨間)決済][] | オブジェクト (非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" として追跡しています。 |
|
||||
|
||||
@@ -53,8 +53,8 @@ TrustSetタイプのトランザクションについては、[`Flags`フィー
|
||||
| `tfSetfAuth` | `0x00010000` | 65536 | [このアカウントから発行された通貨](../../../../concepts/tokens/index.md)を相手方に保有させることを許可します。([*asfRequireAuth* AccountSet フラグ](accountset.md#accountsetのフラグ)を使用しない場合は効果がありません。)設定を解除できません。 |
|
||||
| `tfSetNoRipple` | `0x00020000` | 131072 | 2つのトラストラインの両方でこのフラグが有効になっている場合、同じ通貨のトラストライン間の[リップリング](../../../../concepts/tokens/fungible-tokens/rippling.md)をブロックする No Ripple フラグを有効にします。 |
|
||||
| `tfClearNoRipple` | `0x00040000` | 262144 | No Rippleフラグを無効にし、このトラストラインで[リップリング](../../../../concepts/tokens/fungible-tokens/rippling.md)を許可します。 |
|
||||
| `tfSetFreeze` | `0x00100000` | 1048576 | トラストラインを[凍結](../../../../concepts/tokens/fungible-tokens/freezes.md)します。 |
|
||||
| `tfClearFreeze` | `0x00200000` | 2097152 | トラストラインを[凍結解除](../../../../concepts/tokens/fungible-tokens/freezes.md)します。 |
|
||||
| `tfSetFreeze` | `0x00100000` | 1048576 | トラストラインを[フリーズ](../../../../concepts/tokens/fungible-tokens/freezes.md)します。 |
|
||||
| `tfClearFreeze` | `0x00200000` | 2097152 | トラストラインを[フリーズ解除](../../../../concepts/tokens/fungible-tokens/freezes.md)します。 |
|
||||
|
||||
トランザクションがNo Rippleを有効にしようとしたができない場合、結果コード `tecNO_PERMISSION` で失敗します。[fix1578 amendment][]が有効になる前は、このようなトランザクションは代わりに`tesSUCCESS`(可能な限りの他の変更を行う)という結果になりました。
|
||||
|
||||
|
||||
@@ -66,7 +66,7 @@ XRPは、XRP Ledgerの _アカウント_ ( _ウォレット_ や _アドレス
|
||||
|
||||
<!-- STYLE_OVERRIDE: hot wallet, warm wallet, cold wallet, wallet -->
|
||||
|
||||
Rippleが推奨するベストプラクティスに従い、Alpha Exchangeは、XRP Ledgerに最低2つのアカウントを作成する必要があります。シークレットキーが悪用された場合の危険を最小限にとどめるため、Rippleでは、[ _コールドアカウント_ 、 _ホットアカウント_ 、 _ウォームアカウント_ ](https://ripple.com/build/issuing-operational-addresses/)(それぞれコールドウォレット、ホットウォレット、ウォームウォレットとも呼ばれる)の作成をお勧めしています。コールド/ホット/ウォームのモデルは、セキュリティと利便性のバランスをとるためのものです。XRPを上場する取引所は、以下のアカウントを作成する必要があります。
|
||||
Rippleが推奨するベストプラクティスに従い、Alpha Exchangeは、XRP Ledgerに最低2つのアカウントを作成する必要があります。シークレットキーが悪用された場合の危険を最小限にとどめるため、Rippleでは、[ _コールドアカウント_ 、 _ホットアカウント_ 、 _ウォームアカウント_ ](../../concepts/accounts/account-types.md)(それぞれコールドウォレット、ホットウォレット、ウォームウォレットとも呼ばれる)の作成をお勧めしています。コールド/ホット/ウォームのモデルは、セキュリティと利便性のバランスをとるためのものです。XRPを上場する取引所は、以下のアカウントを作成する必要があります。
|
||||
|
||||
* 大部分のXRPと顧客の資金を維持する[ _コールドウォレット_ ](../../concepts/accounts/account-types.md#発行アドレス)。取引所にとって、これはユーザが[預入れ](#取引所へのxrpの入金)をするアドレスです。 セキュリティを最適化するため、このアカウントのシークレットキーはオフラインにする必要があります。
|
||||
|
||||
|
||||
@@ -141,16 +141,16 @@ How to transparently report the current number of stablecoins held in reserve.
|
||||
|
||||
### トラストラインのFreeze
|
||||
|
||||
XRP Ledgerでトークンを発行する場合、_No Freeze_ 設定を有効にすることで、XRP Ledgerのトークン凍結機能を利用することを永久に停止することができます。(注意点として、これは発行されたトークンにのみ適用され、XRPには適用されません)。
|
||||
XRP Ledgerでトークンを発行する場合、_No Freeze_ 設定を有効にすることで、XRP Ledgerのトークンフリーズ機能を利用することを永久に停止することができます。(注意点として、これは発行されたトークンにのみ適用され、XRPには適用されません)。
|
||||
|
||||
_No Freeze_ 設定を有効にしない場合、アカウントが疑わしい動きを示したり、金融機関の利用規約に違反したりした場合、問題を解決する間、トラストラインを凍結する選択肢があります。
|
||||
_No Freeze_ 設定を有効にしない場合、アカウントが疑わしい動きを示したり、金融機関の利用規約に違反したりした場合、問題を解決する間、トラストラインをフリーズする選択肢があります。
|
||||
|
||||
[トラストラインの凍結](../../concepts/tokens/fungible-tokens/freezes.md)をご覧ください。
|
||||
[トラストラインのフリーズ](../../concepts/tokens/fungible-tokens/freezes.md)をご覧ください。
|
||||
|
||||
|
||||
### Global Freeze
|
||||
|
||||
不審な活動の兆候が見られた場合、アカウントをグローバルに凍結し、ユーザがトークンを相互に送信したり、分散型取引所でトークンを取引したりできないようにすることができます。
|
||||
不審な活動の兆候が見られた場合、アカウントをグローバルにフリーズし、ユーザがトークンを相互に送信したり、分散型取引所でトークンを取引したりできないようにすることができます。
|
||||
|
||||

|
||||
|
||||
|
||||
81
@l10n/ja/resources/contribute-blog/_blog-template.md
Normal file
81
@l10n/ja/resources/contribute-blog/_blog-template.md
Normal file
@@ -0,0 +1,81 @@
|
||||
---
|
||||
category: 2025
|
||||
date: 2025-mm-dd
|
||||
seo:
|
||||
title: SEO最適化済みのタイトル
|
||||
description: ページ内容を正確に反映した、SEO最適化された説明文(155文字以内を推奨)。
|
||||
|
||||
labels:
|
||||
- 一般
|
||||
markdown:
|
||||
editPage:
|
||||
hide: true
|
||||
---
|
||||
# SEO最適化済みのタイトル
|
||||
|
||||
|
||||
ブログ記事の下書きに向けて、最初の一歩を踏み出しましたね! この記事の構成を整理するための出発点として、このテンプレートを活用してください。
|
||||
|
||||
<!-- BREAK -->
|
||||
|
||||
|
||||
詳しいガイドラインや例については、[ブログ記事を投稿する](https://xrpl.org/resources/contribute-blog/)をご覧ください。
|
||||
|
||||
NOTE: 現在、ブログ記事は英語のみで提供されており、翻訳はまだ行われていません。
|
||||
|
||||
## セクション: 便利なリファレンス
|
||||
|
||||
すぐに執筆を始められるように、ブログ記事でよく使われる構文のガイドをご用意しました。執筆プロセスを効率化するのに最適です。
|
||||
|
||||
**タイトル**
|
||||
|
||||
ブログ記事のタイトルや見出しにはタイトルケース(英語の各単語の頭文字を大文字)を使用してください。
|
||||
|
||||
SEOに最適化されたタイトルを選びましょう。
|
||||
|
||||
タイトルは50文字以内に収め、メタ情報の `seo -> title` フィールドと一致させることを推奨します。
|
||||
|
||||
**リンク**
|
||||
|
||||
内部リンクを含めるには、相対パスを使用します。 例えば、ドキュメントへの貢献 トピックへのリンクを作成するには以下の構文を使用します。
|
||||
|
||||
```
|
||||
[ドキュメントへの貢献](../resources/contribute-documentation/index.md).
|
||||
```
|
||||
|
||||
外部リンクを含めるには、相対パスではなく絶対URLを使用してください。以下の例をご覧ください。
|
||||
|
||||
```
|
||||
[ドキュメントへの貢献](https://xrpl.org/resources/contribute-documentation).
|
||||
```
|
||||
|
||||
**リスト**
|
||||
|
||||
順不同リストを含めるには、以下の構文を使用してください。
|
||||
|
||||
- 項目 1
|
||||
- 項目 2
|
||||
|
||||
順序付きリストを含めるには、以下の構文を使用してください。
|
||||
|
||||
1. リスト項目 1
|
||||
2. リスト項目 2
|
||||
|
||||
|
||||
### サブセクション: ブログ記事へ画像を埋め込む方法
|
||||
|
||||
画像を含めるには、以下の構文を使用してください。
|
||||
|
||||
```
|
||||

|
||||
```
|
||||
|
||||
画像ファイルは `/blog/img` ディレクトリに保存することを推奨します。
|
||||
|
||||
例えば、 `` と記述すると、以下のように表示されます。
|
||||
|
||||

|
||||
|
||||
### サブセクション: ブログ記事へ動画を埋め込む方法
|
||||
|
||||
動画の埋め込み方法については、[ドキュメントへの貢献](https://xrpl.org/resources/contribute-documentation#videos) の該当セクションをご覧ください。
|
||||
42
@l10n/ja/resources/contribute-blog/index.md
Normal file
42
@l10n/ja/resources/contribute-blog/index.md
Normal file
@@ -0,0 +1,42 @@
|
||||
---
|
||||
html: contribute-blog.html
|
||||
parent: resources.html
|
||||
seo:
|
||||
description: XRPLブログへの投稿手順
|
||||
labels:
|
||||
- ブロックチェーン
|
||||
---
|
||||
# ブログ記事を投稿する
|
||||
|
||||
XRP Ledger開発者ブログへの投稿をご検討いただきありがとうございます!
|
||||
|
||||
このページでは、新しいブログ記事を作成するための概要手順を紹介しています。XRP Ledger開発者ポータルへの投稿に関する詳細な手順やガイドラインについては、[ドキュメントへの貢献](../contribute-documentation/index.md)をご覧ください。
|
||||
|
||||
{% admonition type="info" name="Note" %}現在、ブログ記事は英語のみで提供されており、まだ翻訳は行われていません。{% /admonition %}
|
||||
|
||||
|
||||
## ブログ投稿用のディレクトリ構成
|
||||
|
||||
ソースファイルは、公開されている `xrpl-dev-portal` リポジトリの `blog` ディレクトリにあります。
|
||||
|
||||
ブログ記事で使用される画像ファイルは、`blog/img` ディレクトリにあります。
|
||||
|
||||
ブログ記事は年ごとに分類されており、2025年に公開されたすべてのブログ記事は `blog/2025` ディレクトリにあります。
|
||||
|
||||
## ブログ記事の新規作成手順
|
||||
|
||||
新しい記事を作成するには、以下の手順に従ってください。
|
||||
|
||||
1. 作業を始める前に、`xrpl-dev-portal` リポジトリの上流(upstream)`master` ブランチから最新の更新をプルしておいてください。
|
||||
|
||||
2. `blog-{記事の概要}` の形式で、新しいブログ記事用のブランチを作成してください。
|
||||
|
||||
3. `blog/{年}` フォルダ内に、新しいMarkdownファイルを作成してください。たとえば、以下のようになります:https://github.com/XRPLF/xrpl-dev-portal/tree/master/blog/2025
|
||||
|
||||
4. 下書きのブログ記事は、テンプレートファイル [`_blog_template.md`](https://github.com/XRPLF/xrpl-dev-portal/tree/master/%40l10n/ja/resources/contribute-blog/_blog-template.md) を参考にして作成してください。
|
||||
|
||||
5. 新しく作成したファイルを `blog/sidebars.yaml` に追加してください。
|
||||
|
||||
6. 下書きがレビュー可能な状態になったら、内容を保存し、コミットを実行してください。
|
||||
|
||||
7. master ブランチへのマージ用に、新しいプルリクエストを作成してください。
|
||||
@@ -17,13 +17,18 @@ labels:
|
||||
|
||||
| 名前 | 登場 | ステータス |
|
||||
|:----------------------------------|:-----------|:------------------------------------|
|
||||
| [AMMClawback][] | v2.3.0 | {% badge href="https://xrpl.org/blog/2024/rippled-2.3.0" %}投票中: 2024-11-26{% /badge %} |
|
||||
| [DynamicNFT][] | v2.4.0 | {% badge href="https://xrpl.org/blog/2025/rippled-2.4.0" %}投票中: 2025-03-06{% /badge %} |
|
||||
| [DeepFreeze][] | v2.4.0 | {% badge href="https://livenet.xrpl.org/transactions/976281D793337FF5377A36409F2A1432DADAB64DB5064E12E71B1AC491EA3021" %}有効: 2025-05-04{% /badge %} |
|
||||
| [PermissionedDomains][] | v2.4.0 | {% badge href="https://xrpl.org/blog/2025/rippled-2.4.0" %}投票中: 2025-03-06{% /badge %} |
|
||||
| [fixFrozenLPTokenTransfer][] | v2.4.0 | {% badge href="https://xrpl.org/blog/2025/rippled-2.4.0" %}投票中: 2025-03-06{% /badge %} |
|
||||
| [fixInvalidTxFlags][] | v2.4.0 | {% badge href="https://xrpl.org/blog/2025/rippled-2.4.0" %}投票中: 2025-03-06{% /badge %} |
|
||||
| [AMMClawback][] | v2.3.0 | {% badge href="https://livenet.xrpl.org/transactions/8672DFD11FCF79F8E8F92E300187E8E533899ED8C8CF5AFB1A9C518195C16261" %}有効: 2025-01-30{% /badge %} |
|
||||
| [Credentials][] | v2.3.0 | {% badge href="https://xrpl.org/blog/2024/rippled-2.3.0" %}投票中: 2024-11-26{% /badge %} |
|
||||
| [fixAMMv1_2][] | v2.3.0 | {% badge href="https://xrpl.org/blog/2024/rippled-2.3.0" %}投票中: 2024-11-26{% /badge %} |
|
||||
| [fixEnforceNFTokenTrustline][] | v2.3.0 | {% badge href="https://xrpl.org/blog/2024/rippled-2.3.0" %}投票中: 2024-11-26{% /badge %} |
|
||||
| [fixInnerObjTemplate2][] | v2.3.0 | {% badge href="https://xrpl.org/blog/2024/rippled-2.3.0" %}投票中: 2024-11-26{% /badge %} |
|
||||
| [fixNFTokenPageLinks][] | v2.3.0 | {% badge href="https://xrpl.org/blog/2024/rippled-2.3.0" %}投票中: 2024-11-26{% /badge %} |
|
||||
| [fixReducedOffersV2][] | v2.3.0 | {% badge href="https://xrpl.org/blog/2024/rippled-2.3.0" %}投票中: 2024-11-26{% /badge %} |
|
||||
| [fixAMMv1_2][] | v2.3.0 | {% badge href="https://livenet.xrpl.org/transactions/71D5031A5BD927BDFE424E51699E69F2784097D615D0852BF20C168BA9B5EA76" %}有効: 2025-01-30{% /badge %} |
|
||||
| [fixEnforceNFTokenTrustline][] | v2.3.0 | {% badge href="https://livenet.xrpl.org/transactions/606FA84C4BA30F67582C11A39BBFC11A9D994E114CD515E9F63FC7D8701A8ED9" %}有効: 2025-01-30{% /badge %} |
|
||||
| [fixInnerObjTemplate2][] | v2.3.0 | {% badge href="https://livenet.xrpl.org/transactions/426314C8BC64BA339E97E53B278602ADC44F115056274BF7971F694C9A8AF946" %}有効: 2025-01-30{% /badge %} |
|
||||
| [fixNFTokenPageLinks][] | v2.3.0 | {% badge href="https://livenet.xrpl.org/transactions/2D9A29768A7FA4BAC01DF1941380077E304785279E5E49267EC269F53ABADF5A" %}有効: 2025-01-30{% /badge %} |
|
||||
| [fixReducedOffersV2][] | v2.3.0 | {% badge href="https://livenet.xrpl.org/transactions/6D325D5EFF8230F1FECA3EE6418C9678637F3F56B0CA247013F70B3BDCFE75C8" %}有効: 2025-01-30{% /badge %} |
|
||||
| [MPTokensV1][] | v2.3.0 | {% badge href="https://xrpl.org/blog/2024/rippled-2.3.0" %}投票中: 2024-11-26{% /badge %} |
|
||||
| [NFTokenMintOffer][] | v2.3.0 | {% badge href="https://xrpl.org/blog/2024/rippled-2.3.0" %}投票中: 2024-11-26{% /badge %} |
|
||||
| [fixXChainRewardRounding][] | v2.2.0 | {% badge href="https://xrpl.org/blog/2024/rippled-2.2.0" %}投票中: 2024-06-04{% /badge %} |
|
||||
@@ -170,7 +175,7 @@ labels:
|
||||
| Amendment | AMMClawback |
|
||||
| :----------------------------- | :--------------------------------------------------------------- |
|
||||
| Amendment ID | 726F944886BCDF7433203787E93DD9AA87FAB74DFE3AF4785BA03BEFC97ADA1F |
|
||||
| ステータス | 投票中 |
|
||||
| ステータス | 有効 |
|
||||
| デフォルトの投票(最新の安定版) | いいえ |
|
||||
| Amendment前の機能は廃止? | いいえ |
|
||||
|
||||
@@ -178,7 +183,7 @@ labels:
|
||||
|
||||
- **AMMClawback** - トークンにClawbackが有効になっている場合、発行者は、AMMに預けられたトークンをClawbackできるようになります。
|
||||
|
||||
AMMDepositトランザクションタイプを修正し、AMMに凍結されたトークンを預けることを防ぎます。
|
||||
AMMDepositトランザクションタイプを修正し、AMMにフリーズされたトークンを預けることを防ぎます。
|
||||
|
||||
詳細については、[XLS-73: AMMClawback specification](https://github.com/XRPLF/XRPL-Standards/discussions/212)をご覧ください。
|
||||
|
||||
|
||||
@@ -478,8 +478,8 @@ Trust Lines: トラストライン
|
||||
No spamming of wallets without permission.: 許可なくウォレットにスパムを送信することはありません。
|
||||
Authorized Trustlines: 認可トラストライン
|
||||
Control who can hold your tokens with allowlisting.: ホワイトリスト形式で誰がトークンを保持できるかを制御します。
|
||||
Freeze & Clawbacks: 凍結とクローバック
|
||||
Freeze: 凍結
|
||||
Freeze & Clawbacks: フリーズとクローバック
|
||||
Freeze: フリーズ
|
||||
If you see signs of suspicious activity, you can suspend trading of your token while investigating the issue.: 不審な活動の兆候が見られた場合は、問題を調査する間、トークンの取引を停止することができます。
|
||||
Clawback: クローバック
|
||||
"Recover tokens distributed to accounts in error: for example, reclaim funds sent to an account sanctioned for illegal activity.": 誤ってアカウントに送信されたトークンを回収することができます。たとえば、違法行為に対して制裁を受けたアカウントに送金された資金を回収します。
|
||||
|
||||
@@ -6,32 +6,64 @@ import { Link } from "@redocly/theme/components/Link/Link";
|
||||
import { ColorModeSwitcher } from "@redocly/theme/components/ColorModeSwitcher/ColorModeSwitcher";
|
||||
import { Search } from "@redocly/theme/components/Search/Search";
|
||||
import arrowUpRight from "../../../static/img/icons/arrow-up-right-custom.svg";
|
||||
import moment from "moment-timezone";
|
||||
|
||||
// @ts-ignore
|
||||
|
||||
const alertBanner = {
|
||||
show: true,
|
||||
show: false,
|
||||
message: "APEX 2025",
|
||||
button: "REGISTER",
|
||||
link: "https://www.xrpledgerapex.com/?utm_source=xrplwebsite&utm_medium=direct&utm_campaign=xrpl-event-ho-xrplapex-glb-2025-q1_xrplwebsite_ari_arp_bf_rsvp&utm_content=cta_btn_english_pencilbanner",
|
||||
date: "AGENDA NOW LIVE",
|
||||
link: "https://www.xrpledgerapex.com/?utm_source=xrplwebsite&utm_medium=direct&utm_campaign=xrpl-event-ho-xrplapex-glb-2025-q1_xrplwebsite_ari_arp_bf_rsvp&utm_content=cta_btn_english_pencilbanner"
|
||||
};
|
||||
export function AlertBanner({ message, date, button, link, show }) {
|
||||
|
||||
export function AlertBanner({ message, button, link, show }) {
|
||||
const { useTranslate } = useThemeHooks();
|
||||
const { translate } = useTranslate();
|
||||
const bannerRef = React.useRef(null);
|
||||
const [displayDate, setDisplayDate] = React.useState("JUNE 10-12");
|
||||
|
||||
React.useEffect(() => {
|
||||
const calculateCountdown = () => {
|
||||
// Calculate days until June 11, 2025 8AM Singapore time
|
||||
// This will automatically adjust for the user's timezone
|
||||
const target = moment.tz('2025-06-11 08:00:00', 'Asia/Singapore');
|
||||
const now = moment();
|
||||
const daysUntil = target.diff(now, 'days');
|
||||
|
||||
// Show countdown if event is in the future, otherwise show the provided date
|
||||
let newDisplayDate = "JUNE 10-12";
|
||||
if (daysUntil > 0) {
|
||||
newDisplayDate = daysUntil === 1 ? 'IN 1 DAY' : `IN ${daysUntil} DAYS`;
|
||||
} else if (daysUntil === 0) {
|
||||
// Check if it's today
|
||||
const hoursUntil = target.diff(now, 'hours');
|
||||
newDisplayDate = hoursUntil > 0 ? 'TODAY' : "JUNE 10-12";
|
||||
}
|
||||
|
||||
setDisplayDate(newDisplayDate);
|
||||
};
|
||||
|
||||
// Calculate immediately
|
||||
calculateCountdown();
|
||||
|
||||
// Update every hour
|
||||
const interval = setInterval(calculateCountdown, 60 * 60 * 1000);
|
||||
|
||||
return () => clearInterval(interval);
|
||||
}, []);
|
||||
|
||||
React.useEffect(() => {
|
||||
const banner = bannerRef.current;
|
||||
if (!banner) return;
|
||||
const handleMouseEnter = () => {
|
||||
banner.classList.add('has-hover');
|
||||
banner.classList.add("has-hover");
|
||||
};
|
||||
// Attach the event listener
|
||||
banner.addEventListener('mouseenter', handleMouseEnter);
|
||||
banner.addEventListener("mouseenter", handleMouseEnter);
|
||||
// Clean up the event listener on unmount
|
||||
return () => {
|
||||
banner.removeEventListener('mouseenter', handleMouseEnter);
|
||||
banner.removeEventListener("mouseenter", handleMouseEnter);
|
||||
};
|
||||
}, []);
|
||||
|
||||
@@ -47,11 +79,15 @@ export function AlertBanner({ message, date, button, link, show }) {
|
||||
>
|
||||
<div className="banner-event-details">
|
||||
<div className="event-info">{translate(message)}</div>
|
||||
<div className="event-date">{translate(date)}</div>
|
||||
<div className="event-date">{displayDate}</div>
|
||||
</div>
|
||||
<div className="banner-button">
|
||||
<div className="button-text">{translate(button)}</div>
|
||||
<img className="button-icon" src={arrowUpRight} alt="Get Tickets Icon" />
|
||||
<img
|
||||
className="button-icon"
|
||||
src={arrowUpRight}
|
||||
alt="Get Tickets Icon"
|
||||
/>
|
||||
</div>
|
||||
</a>
|
||||
);
|
||||
@@ -91,7 +127,6 @@ export function Navbar(props) {
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
React.useEffect(() => {
|
||||
// Turns out jQuery is necessary for firing events on Bootstrap v4
|
||||
// dropdowns. These events set classes so that the search bar and other
|
||||
@@ -139,7 +174,7 @@ export function Navbar(props) {
|
||||
<NavItems>
|
||||
{navItems}
|
||||
<div id="topnav-search" className="nav-item search">
|
||||
<Search className="topnav-search"/>
|
||||
<Search className="topnav-search" />
|
||||
</div>
|
||||
<div id="topnav-language" className="nav-item">
|
||||
<LanguagePicker
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
"https-browserify": "^1.0.0",
|
||||
"stream-browserify": "^3.0.0",
|
||||
"stream-http": "^3.2.0",
|
||||
"vite": "^4.5.13"
|
||||
"vite": "^4.5.14"
|
||||
},
|
||||
"dependencies": {
|
||||
"dotenv": "^16.0.3",
|
||||
|
||||
@@ -172,6 +172,13 @@ asn1.js@^4.10.1:
|
||||
inherits "^2.0.1"
|
||||
minimalistic-assert "^1.0.0"
|
||||
|
||||
available-typed-arrays@^1.0.7:
|
||||
version "1.0.7"
|
||||
resolved "https://registry.yarnpkg.com/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz#a5cc375d6a03c2efc87a553f3e0b1522def14846"
|
||||
integrity sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==
|
||||
dependencies:
|
||||
possible-typed-array-names "^1.0.0"
|
||||
|
||||
bignumber.js@^9.0.0:
|
||||
version "9.1.2"
|
||||
resolved "https://registry.yarnpkg.com/bignumber.js/-/bignumber.js-9.1.2.tgz#b7c4242259c008903b13707983b5f4bbd31eda0c"
|
||||
@@ -258,6 +265,32 @@ builtin-status-codes@^3.0.0:
|
||||
resolved "https://registry.yarnpkg.com/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz#85982878e21b98e1c66425e03d0174788f569ee8"
|
||||
integrity sha512-HpGFw18DgFWlncDfjTa2rcQ4W88O1mC8e8yZ2AvQY5KDaktSTwo+KRf6nHK6FRI5FyRyb/5T6+TSxfP7QyGsmQ==
|
||||
|
||||
call-bind-apply-helpers@^1.0.0, call-bind-apply-helpers@^1.0.1, call-bind-apply-helpers@^1.0.2:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz#4b5428c222be985d79c3d82657479dbe0b59b2d6"
|
||||
integrity sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==
|
||||
dependencies:
|
||||
es-errors "^1.3.0"
|
||||
function-bind "^1.1.2"
|
||||
|
||||
call-bind@^1.0.8:
|
||||
version "1.0.8"
|
||||
resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.8.tgz#0736a9660f537e3388826f440d5ec45f744eaa4c"
|
||||
integrity sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww==
|
||||
dependencies:
|
||||
call-bind-apply-helpers "^1.0.0"
|
||||
es-define-property "^1.0.0"
|
||||
get-intrinsic "^1.2.4"
|
||||
set-function-length "^1.2.2"
|
||||
|
||||
call-bound@^1.0.3, call-bound@^1.0.4:
|
||||
version "1.0.4"
|
||||
resolved "https://registry.yarnpkg.com/call-bound/-/call-bound-1.0.4.tgz#238de935d2a2a692928c538c7ccfa91067fd062a"
|
||||
integrity sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==
|
||||
dependencies:
|
||||
call-bind-apply-helpers "^1.0.2"
|
||||
get-intrinsic "^1.3.0"
|
||||
|
||||
cipher-base@^1.0.0, cipher-base@^1.0.1, cipher-base@^1.0.3:
|
||||
version "1.0.6"
|
||||
resolved "https://registry.yarnpkg.com/cipher-base/-/cipher-base-1.0.6.tgz#8fe672437d01cd6c4561af5334e0cc50ff1955f7"
|
||||
@@ -279,7 +312,7 @@ create-ecdh@^4.0.4:
|
||||
bn.js "^4.1.0"
|
||||
elliptic "^6.5.3"
|
||||
|
||||
create-hash@^1.1.0, create-hash@^1.1.2, create-hash@^1.2.0:
|
||||
create-hash@^1.1.0, create-hash@^1.2.0:
|
||||
version "1.2.0"
|
||||
resolved "https://registry.yarnpkg.com/create-hash/-/create-hash-1.2.0.tgz#889078af11a63756bcfb59bd221996be3a9ef196"
|
||||
integrity sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==
|
||||
@@ -290,7 +323,17 @@ create-hash@^1.1.0, create-hash@^1.1.2, create-hash@^1.2.0:
|
||||
ripemd160 "^2.0.1"
|
||||
sha.js "^2.4.0"
|
||||
|
||||
create-hmac@^1.1.4, create-hmac@^1.1.7:
|
||||
create-hash@~1.1.3:
|
||||
version "1.1.3"
|
||||
resolved "https://registry.yarnpkg.com/create-hash/-/create-hash-1.1.3.tgz#606042ac8b9262750f483caddab0f5819172d8fd"
|
||||
integrity sha512-snRpch/kwQhcdlnZKYanNF1m0RDlrCdSKQaH87w1FCFPVPNCQ/Il9QJKAX2jVBZddRdaHBMC+zXa9Gw9tmkNUA==
|
||||
dependencies:
|
||||
cipher-base "^1.0.1"
|
||||
inherits "^2.0.1"
|
||||
ripemd160 "^2.0.0"
|
||||
sha.js "^2.4.0"
|
||||
|
||||
create-hmac@^1.1.7:
|
||||
version "1.1.7"
|
||||
resolved "https://registry.yarnpkg.com/create-hmac/-/create-hmac-1.1.7.tgz#69170c78b3ab957147b2b8b04572e47ead2243ff"
|
||||
integrity sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==
|
||||
@@ -320,6 +363,15 @@ crypto-browserify@^3.12.0:
|
||||
randombytes "^2.1.0"
|
||||
randomfill "^1.0.4"
|
||||
|
||||
define-data-property@^1.1.4:
|
||||
version "1.1.4"
|
||||
resolved "https://registry.yarnpkg.com/define-data-property/-/define-data-property-1.1.4.tgz#894dc141bb7d3060ae4366f6a0107e68fbe48c5e"
|
||||
integrity sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==
|
||||
dependencies:
|
||||
es-define-property "^1.0.0"
|
||||
es-errors "^1.3.0"
|
||||
gopd "^1.0.1"
|
||||
|
||||
des.js@^1.0.0:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/des.js/-/des.js-1.1.0.tgz#1d37f5766f3bbff4ee9638e871a8768c173b81da"
|
||||
@@ -342,6 +394,15 @@ dotenv@^16.0.3:
|
||||
resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-16.4.7.tgz#0e20c5b82950140aa99be360a8a5f52335f53c26"
|
||||
integrity sha512-47qPchRCykZC03FhkYAhrvwU4xDBFIj1QPqaarj6mdM/hgUzfPHcpkHJOn3mJAufFeeAxAzeGsr5X0M4k6fLZQ==
|
||||
|
||||
dunder-proto@^1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/dunder-proto/-/dunder-proto-1.0.1.tgz#d7ae667e1dc83482f8b70fd0f6eefc50da30f58a"
|
||||
integrity sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==
|
||||
dependencies:
|
||||
call-bind-apply-helpers "^1.0.1"
|
||||
es-errors "^1.3.0"
|
||||
gopd "^1.2.0"
|
||||
|
||||
elliptic@^6.5.3, elliptic@^6.5.5:
|
||||
version "6.6.1"
|
||||
resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.6.1.tgz#3b8ffb02670bf69e382c7f65bf524c97c5405c06"
|
||||
@@ -355,6 +416,23 @@ elliptic@^6.5.3, elliptic@^6.5.5:
|
||||
minimalistic-assert "^1.0.1"
|
||||
minimalistic-crypto-utils "^1.0.1"
|
||||
|
||||
es-define-property@^1.0.0, es-define-property@^1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/es-define-property/-/es-define-property-1.0.1.tgz#983eb2f9a6724e9303f61addf011c72e09e0b0fa"
|
||||
integrity sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==
|
||||
|
||||
es-errors@^1.3.0:
|
||||
version "1.3.0"
|
||||
resolved "https://registry.yarnpkg.com/es-errors/-/es-errors-1.3.0.tgz#05f75a25dab98e4fb1dcd5e1472c0546d5057c8f"
|
||||
integrity sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==
|
||||
|
||||
es-object-atoms@^1.0.0, es-object-atoms@^1.1.1:
|
||||
version "1.1.1"
|
||||
resolved "https://registry.yarnpkg.com/es-object-atoms/-/es-object-atoms-1.1.1.tgz#1c4f2c4837327597ce69d2ca190a7fdd172338c1"
|
||||
integrity sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==
|
||||
dependencies:
|
||||
es-errors "^1.3.0"
|
||||
|
||||
esbuild@^0.18.10:
|
||||
version "0.18.20"
|
||||
resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.18.20.tgz#4709f5a34801b43b799ab7d6d82f7284a9b7a7a6"
|
||||
@@ -401,11 +479,78 @@ evp_bytestokey@^1.0.0, evp_bytestokey@^1.0.3:
|
||||
md5.js "^1.3.4"
|
||||
safe-buffer "^5.1.1"
|
||||
|
||||
for-each@^0.3.5:
|
||||
version "0.3.5"
|
||||
resolved "https://registry.yarnpkg.com/for-each/-/for-each-0.3.5.tgz#d650688027826920feeb0af747ee7b9421a41d47"
|
||||
integrity sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==
|
||||
dependencies:
|
||||
is-callable "^1.2.7"
|
||||
|
||||
fsevents@~2.3.2:
|
||||
version "2.3.3"
|
||||
resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.3.tgz#cac6407785d03675a2a5e1a5305c697b347d90d6"
|
||||
integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==
|
||||
|
||||
function-bind@^1.1.2:
|
||||
version "1.1.2"
|
||||
resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.2.tgz#2c02d864d97f3ea6c8830c464cbd11ab6eab7a1c"
|
||||
integrity sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==
|
||||
|
||||
get-intrinsic@^1.2.4, get-intrinsic@^1.3.0:
|
||||
version "1.3.0"
|
||||
resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.3.0.tgz#743f0e3b6964a93a5491ed1bffaae054d7f98d01"
|
||||
integrity sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==
|
||||
dependencies:
|
||||
call-bind-apply-helpers "^1.0.2"
|
||||
es-define-property "^1.0.1"
|
||||
es-errors "^1.3.0"
|
||||
es-object-atoms "^1.1.1"
|
||||
function-bind "^1.1.2"
|
||||
get-proto "^1.0.1"
|
||||
gopd "^1.2.0"
|
||||
has-symbols "^1.1.0"
|
||||
hasown "^2.0.2"
|
||||
math-intrinsics "^1.1.0"
|
||||
|
||||
get-proto@^1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/get-proto/-/get-proto-1.0.1.tgz#150b3f2743869ef3e851ec0c49d15b1d14d00ee1"
|
||||
integrity sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==
|
||||
dependencies:
|
||||
dunder-proto "^1.0.1"
|
||||
es-object-atoms "^1.0.0"
|
||||
|
||||
gopd@^1.0.1, gopd@^1.2.0:
|
||||
version "1.2.0"
|
||||
resolved "https://registry.yarnpkg.com/gopd/-/gopd-1.2.0.tgz#89f56b8217bdbc8802bd299df6d7f1081d7e51a1"
|
||||
integrity sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==
|
||||
|
||||
has-property-descriptors@^1.0.2:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz#963ed7d071dc7bf5f084c5bfbe0d1b6222586854"
|
||||
integrity sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==
|
||||
dependencies:
|
||||
es-define-property "^1.0.0"
|
||||
|
||||
has-symbols@^1.0.3, has-symbols@^1.1.0:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.1.0.tgz#fc9c6a783a084951d0b971fe1018de813707a338"
|
||||
integrity sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==
|
||||
|
||||
has-tostringtag@^1.0.2:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/has-tostringtag/-/has-tostringtag-1.0.2.tgz#2cdc42d40bef2e5b4eeab7c01a73c54ce7ab5abc"
|
||||
integrity sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==
|
||||
dependencies:
|
||||
has-symbols "^1.0.3"
|
||||
|
||||
hash-base@^2.0.0:
|
||||
version "2.0.2"
|
||||
resolved "https://registry.yarnpkg.com/hash-base/-/hash-base-2.0.2.tgz#66ea1d856db4e8a5470cadf6fce23ae5244ef2e1"
|
||||
integrity sha512-0TROgQ1/SxE6KmxWSvXHvRj90/Xo1JvZShofnYF+f6ZsGtR4eES7WfrQzPalmyagfKZCXpVnitiRebZulWsbiw==
|
||||
dependencies:
|
||||
inherits "^2.0.1"
|
||||
|
||||
hash-base@^3.0.0:
|
||||
version "3.1.0"
|
||||
resolved "https://registry.yarnpkg.com/hash-base/-/hash-base-3.1.0.tgz#55c381d9e06e1d2997a883b4a3fddfe7f0d3af33"
|
||||
@@ -431,6 +576,13 @@ hash.js@^1.0.0, hash.js@^1.0.3:
|
||||
inherits "^2.0.3"
|
||||
minimalistic-assert "^1.0.1"
|
||||
|
||||
hasown@^2.0.2:
|
||||
version "2.0.2"
|
||||
resolved "https://registry.yarnpkg.com/hasown/-/hasown-2.0.2.tgz#003eaf91be7adc372e84ec59dc37252cedb80003"
|
||||
integrity sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==
|
||||
dependencies:
|
||||
function-bind "^1.1.2"
|
||||
|
||||
hmac-drbg@^1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/hmac-drbg/-/hmac-drbg-1.0.1.tgz#d2745701025a6c775a6c545793ed502fc0c649a1"
|
||||
@@ -450,11 +602,33 @@ inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.3, inherits@~2.
|
||||
resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c"
|
||||
integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==
|
||||
|
||||
is-callable@^1.2.7:
|
||||
version "1.2.7"
|
||||
resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.7.tgz#3bc2a85ea742d9e36205dcacdd72ca1fdc51b055"
|
||||
integrity sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==
|
||||
|
||||
is-typed-array@^1.1.14:
|
||||
version "1.1.15"
|
||||
resolved "https://registry.yarnpkg.com/is-typed-array/-/is-typed-array-1.1.15.tgz#4bfb4a45b61cee83a5a46fba778e4e8d59c0ce0b"
|
||||
integrity sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==
|
||||
dependencies:
|
||||
which-typed-array "^1.1.16"
|
||||
|
||||
isarray@^2.0.5:
|
||||
version "2.0.5"
|
||||
resolved "https://registry.yarnpkg.com/isarray/-/isarray-2.0.5.tgz#8af1e4c1221244cc62459faf38940d4e644a5723"
|
||||
integrity sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==
|
||||
|
||||
isarray@~1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11"
|
||||
integrity sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==
|
||||
|
||||
math-intrinsics@^1.1.0:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/math-intrinsics/-/math-intrinsics-1.1.0.tgz#a0dd74be81e2aa5c2f27e65ce283605ee4e2b7f9"
|
||||
integrity sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==
|
||||
|
||||
md5.js@^1.3.4:
|
||||
version "1.3.5"
|
||||
resolved "https://registry.yarnpkg.com/md5.js/-/md5.js-1.3.5.tgz#b5d07b8e3216e3e27cd728d72f70d1e6a342005f"
|
||||
@@ -500,21 +674,27 @@ parse-asn1@^5.0.0, parse-asn1@^5.1.7:
|
||||
safe-buffer "^5.2.1"
|
||||
|
||||
pbkdf2@^3.1.2:
|
||||
version "3.1.2"
|
||||
resolved "https://registry.yarnpkg.com/pbkdf2/-/pbkdf2-3.1.2.tgz#dd822aa0887580e52f1a039dc3eda108efae3075"
|
||||
integrity sha512-iuh7L6jA7JEGu2WxDwtQP1ddOpaJNC4KlDEFfdQajSGgGPNi4OyDc2R7QnbY2bR9QjBVGwgvTdNJZoE7RaxUMA==
|
||||
version "3.1.3"
|
||||
resolved "https://registry.yarnpkg.com/pbkdf2/-/pbkdf2-3.1.3.tgz#8be674d591d65658113424592a95d1517318dd4b"
|
||||
integrity sha512-wfRLBZ0feWRhCIkoMB6ete7czJcnNnqRpcoWQBLqatqXXmelSRqfdDK4F3u9T2s2cXas/hQJcryI/4lAL+XTlA==
|
||||
dependencies:
|
||||
create-hash "^1.1.2"
|
||||
create-hmac "^1.1.4"
|
||||
ripemd160 "^2.0.1"
|
||||
safe-buffer "^5.0.1"
|
||||
sha.js "^2.4.8"
|
||||
create-hash "~1.1.3"
|
||||
create-hmac "^1.1.7"
|
||||
ripemd160 "=2.0.1"
|
||||
safe-buffer "^5.2.1"
|
||||
sha.js "^2.4.11"
|
||||
to-buffer "^1.2.0"
|
||||
|
||||
picocolors@^1.1.1:
|
||||
version "1.1.1"
|
||||
resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.1.1.tgz#3d321af3eab939b083c8f929a1d12cda81c26b6b"
|
||||
integrity sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==
|
||||
|
||||
possible-typed-array-names@^1.0.0:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/possible-typed-array-names/-/possible-typed-array-names-1.1.0.tgz#93e3582bc0e5426586d9d07b79ee40fc841de4ae"
|
||||
integrity sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==
|
||||
|
||||
postcss@^8.4.27:
|
||||
version "8.5.1"
|
||||
resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.5.1.tgz#e2272a1f8a807fafa413218245630b5db10a3214"
|
||||
@@ -578,6 +758,14 @@ readable-stream@^3.5.0, readable-stream@^3.6.0:
|
||||
string_decoder "^1.1.1"
|
||||
util-deprecate "^1.0.1"
|
||||
|
||||
ripemd160@=2.0.1:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/ripemd160/-/ripemd160-2.0.1.tgz#0f4584295c53a3628af7e6d79aca21ce57d1c6e7"
|
||||
integrity sha512-J7f4wutN8mdbV08MJnXibYpCOPHR+yzy+iQ/AsjMv2j8cLavQ8VGagDFUwwTAdF8FmRKVeNpbTTEwNHCW1g94w==
|
||||
dependencies:
|
||||
hash-base "^2.0.0"
|
||||
inherits "^2.0.1"
|
||||
|
||||
ripemd160@^2.0.0, ripemd160@^2.0.1:
|
||||
version "2.0.2"
|
||||
resolved "https://registry.yarnpkg.com/ripemd160/-/ripemd160-2.0.2.tgz#a1c1a6f624751577ba5d07914cbc92850585890c"
|
||||
@@ -629,7 +817,19 @@ safe-buffer@~5.1.0, safe-buffer@~5.1.1:
|
||||
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d"
|
||||
integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==
|
||||
|
||||
sha.js@^2.4.0, sha.js@^2.4.8:
|
||||
set-function-length@^1.2.2:
|
||||
version "1.2.2"
|
||||
resolved "https://registry.yarnpkg.com/set-function-length/-/set-function-length-1.2.2.tgz#aac72314198eaed975cf77b2c3b6b880695e5449"
|
||||
integrity sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==
|
||||
dependencies:
|
||||
define-data-property "^1.1.4"
|
||||
es-errors "^1.3.0"
|
||||
function-bind "^1.1.2"
|
||||
get-intrinsic "^1.2.4"
|
||||
gopd "^1.0.1"
|
||||
has-property-descriptors "^1.0.2"
|
||||
|
||||
sha.js@^2.4.0, sha.js@^2.4.11, sha.js@^2.4.8:
|
||||
version "2.4.11"
|
||||
resolved "https://registry.yarnpkg.com/sha.js/-/sha.js-2.4.11.tgz#37a5cf0b81ecbc6943de109ba2960d1b26584ae7"
|
||||
integrity sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==
|
||||
@@ -674,15 +874,33 @@ string_decoder@~1.1.1:
|
||||
dependencies:
|
||||
safe-buffer "~5.1.0"
|
||||
|
||||
to-buffer@^1.2.0:
|
||||
version "1.2.1"
|
||||
resolved "https://registry.yarnpkg.com/to-buffer/-/to-buffer-1.2.1.tgz#2ce650cdb262e9112a18e65dc29dcb513c8155e0"
|
||||
integrity sha512-tB82LpAIWjhLYbqjx3X4zEeHN6M8CiuOEy2JY8SEQVdYRe3CCHOFaqrBW1doLDrfpWhplcW7BL+bO3/6S3pcDQ==
|
||||
dependencies:
|
||||
isarray "^2.0.5"
|
||||
safe-buffer "^5.2.1"
|
||||
typed-array-buffer "^1.0.3"
|
||||
|
||||
typed-array-buffer@^1.0.3:
|
||||
version "1.0.3"
|
||||
resolved "https://registry.yarnpkg.com/typed-array-buffer/-/typed-array-buffer-1.0.3.tgz#a72395450a4869ec033fd549371b47af3a2ee536"
|
||||
integrity sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==
|
||||
dependencies:
|
||||
call-bound "^1.0.3"
|
||||
es-errors "^1.3.0"
|
||||
is-typed-array "^1.1.14"
|
||||
|
||||
util-deprecate@^1.0.1, util-deprecate@~1.0.1:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf"
|
||||
integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==
|
||||
|
||||
vite@^4.5.13:
|
||||
version "4.5.13"
|
||||
resolved "https://registry.yarnpkg.com/vite/-/vite-4.5.13.tgz#778534a947112c6c455e89737730fae5d458a294"
|
||||
integrity sha512-Hgp8IF/yZDzKsN1hQWOuQZbrKiaFsbQud+07jJ8h9m9PaHWkpvZ5u55Xw5yYjWRXwRQ4jwFlJvY7T7FUJG9MCA==
|
||||
vite@^4.5.14:
|
||||
version "4.5.14"
|
||||
resolved "https://registry.yarnpkg.com/vite/-/vite-4.5.14.tgz#2e652bc1d898265d987d6543ce866ecd65fa4086"
|
||||
integrity sha512-+v57oAaoYNnO3hIu5Z/tJRZjq5aHM2zDve9YZ8HngVHbhk66RStobhb1sqPMIPEleV6cNKYK4eGrAbE9Ulbl2g==
|
||||
dependencies:
|
||||
esbuild "^0.18.10"
|
||||
postcss "^8.4.27"
|
||||
@@ -690,6 +908,19 @@ vite@^4.5.13:
|
||||
optionalDependencies:
|
||||
fsevents "~2.3.2"
|
||||
|
||||
which-typed-array@^1.1.16:
|
||||
version "1.1.19"
|
||||
resolved "https://registry.yarnpkg.com/which-typed-array/-/which-typed-array-1.1.19.tgz#df03842e870b6b88e117524a4b364b6fc689f956"
|
||||
integrity sha512-rEvr90Bck4WZt9HHFC4DJMsjvu7x+r6bImz0/BrbWb7A2djJ8hnZMrWnHo9F8ssv0OMErasDhftrfROTyqSDrw==
|
||||
dependencies:
|
||||
available-typed-arrays "^1.0.7"
|
||||
call-bind "^1.0.8"
|
||||
call-bound "^1.0.4"
|
||||
for-each "^0.3.5"
|
||||
get-proto "^1.0.1"
|
||||
gopd "^1.2.0"
|
||||
has-tostringtag "^1.0.2"
|
||||
|
||||
ws@^8.13.0:
|
||||
version "8.18.0"
|
||||
resolved "https://registry.yarnpkg.com/ws/-/ws-8.18.0.tgz#0d7505a6eafe2b0e712d232b42279f53bc289bbc"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
xrpl-py>=3.0.0
|
||||
wxPython==4.2.1
|
||||
toml==0.10.2
|
||||
requests==2.32.0
|
||||
requests==2.32.4
|
||||
|
||||
@@ -12,13 +12,11 @@ import {
|
||||
|
||||
const client = new Client('wss://s.altnet.rippletest.net:51233')
|
||||
|
||||
void claimPayChannel()
|
||||
|
||||
// The snippet walks us through creating and claiming a Payment Channel.
|
||||
async function claimPayChannel(): Promise<void> {
|
||||
await client.connect()
|
||||
|
||||
// creating wallets as prerequisite
|
||||
// Creating wallets as prerequisite
|
||||
const { wallet: wallet1 } = await client.fundWallet()
|
||||
const { wallet: wallet2 } = await client.fundWallet()
|
||||
|
||||
@@ -26,16 +24,17 @@ async function claimPayChannel(): Promise<void> {
|
||||
console.log(`Balance of ${wallet1.address} is ${await client.getXrpBalance(wallet1.address)} XRP`)
|
||||
console.log(`Balance of ${wallet2.address} is ${await client.getXrpBalance(wallet2.address)} XRP`)
|
||||
|
||||
// create a Payment Channel and submit and wait for tx to be validated
|
||||
// Create a Payment Channel transaction
|
||||
const paymentChannelCreate: PaymentChannelCreate = {
|
||||
TransactionType: 'PaymentChannelCreate',
|
||||
Account: wallet1.classicAddress,
|
||||
Amount: '100',
|
||||
Amount: '3000000', // 3 XRP in drops
|
||||
Destination: wallet2.classicAddress,
|
||||
SettleDelay: 86400,
|
||||
SettleDelay: 86400, // 1 day in seconds
|
||||
PublicKey: wallet1.publicKey,
|
||||
}
|
||||
|
||||
|
||||
// Submit and wait for the transaction to be validated
|
||||
console.log("Submitting a PaymentChannelCreate transaction...")
|
||||
const paymentChannelResponse = await client.submitAndWait(
|
||||
paymentChannelCreate,
|
||||
@@ -44,7 +43,7 @@ async function claimPayChannel(): Promise<void> {
|
||||
console.log("PaymentChannelCreate transaction response:")
|
||||
console.log(paymentChannelResponse)
|
||||
|
||||
// check that the object was actually created
|
||||
// Check that the object was actually created
|
||||
const accountObjectsRequest: AccountObjectsRequest = {
|
||||
command: 'account_objects',
|
||||
account: wallet1.classicAddress,
|
||||
@@ -55,14 +54,14 @@ async function claimPayChannel(): Promise<void> {
|
||||
|
||||
console.log("Account Objects:", accountObjects)
|
||||
|
||||
// destination claims the Payment Channel and we see the balances to verify.
|
||||
// Destination claims the Payment Channel and we see the balances to verify.
|
||||
const paymentChannelClaim: PaymentChannelClaim = {
|
||||
Account: wallet2.classicAddress,
|
||||
TransactionType: 'PaymentChannelClaim',
|
||||
Channel: hashes.hashPaymentChannel(
|
||||
wallet1.classicAddress,
|
||||
wallet2.classicAddress,
|
||||
paymentChannelResponse.result.Sequence ?? 0,
|
||||
paymentChannelResponse.result.tx_json.Sequence ?? 0,
|
||||
),
|
||||
Amount: '100',
|
||||
}
|
||||
@@ -70,7 +69,7 @@ async function claimPayChannel(): Promise<void> {
|
||||
console.log("Submitting a PaymentChannelClaim transaction...")
|
||||
|
||||
const channelClaimResponse = await client.submit(paymentChannelClaim, {
|
||||
wallet: wallet1,
|
||||
wallet: wallet2,
|
||||
})
|
||||
console.log("PaymentChannelClaim transaction response:")
|
||||
console.log(channelClaimResponse)
|
||||
@@ -81,3 +80,5 @@ async function claimPayChannel(): Promise<void> {
|
||||
|
||||
await client.disconnect()
|
||||
}
|
||||
|
||||
void claimPayChannel()
|
||||
|
||||
97
_code-samples/claim-payment-channel/py/claim_pay_channel.py
Normal file
97
_code-samples/claim-payment-channel/py/claim_pay_channel.py
Normal file
@@ -0,0 +1,97 @@
|
||||
"""
|
||||
Create, claim and verify a Payment Channel.
|
||||
Reference: https://xrpl.org/paychannel.html
|
||||
"""
|
||||
from xrpl.clients import JsonRpcClient
|
||||
from xrpl.models import (
|
||||
AccountObjects,
|
||||
PaymentChannelCreate,
|
||||
PaymentChannelClaim,
|
||||
)
|
||||
from xrpl.wallet import generate_faucet_wallet
|
||||
from xrpl.transaction import submit_and_wait, submit
|
||||
from xrpl.account import get_balance
|
||||
|
||||
|
||||
def claim_pay_channel():
|
||||
"""The snippet walks us through creating and claiming a Payment Channel."""
|
||||
|
||||
client = JsonRpcClient("https://s.altnet.rippletest.net:51234")
|
||||
|
||||
try:
|
||||
# Creating wallets as prerequisite
|
||||
print("Creating and funding wallets...")
|
||||
wallet1 = generate_faucet_wallet(client, debug=True)
|
||||
wallet2 = generate_faucet_wallet(client, debug=True)
|
||||
|
||||
print("Balances of wallets before Payment Channel is claimed:")
|
||||
balance1 = get_balance(wallet1.address, client)
|
||||
balance2 = get_balance(wallet2.address, client)
|
||||
print(f"Balance of {wallet1.address} is {balance1} XRP")
|
||||
print(f"Balance of {wallet2.address} is {balance2} XRP")
|
||||
|
||||
# Create a Payment Channel transaction
|
||||
payment_channel_create = PaymentChannelCreate(
|
||||
account=wallet1.address,
|
||||
amount="3000000", # 3 XRP in drops
|
||||
destination=wallet2.address,
|
||||
settle_delay=86400,
|
||||
public_key=wallet1.public_key,
|
||||
)
|
||||
|
||||
# Submit and wait for the transaction to be validated
|
||||
print("Submitting a PaymentChannelCreate transaction...")
|
||||
payment_channel_response = submit_and_wait(
|
||||
payment_channel_create,
|
||||
client,
|
||||
wallet1
|
||||
)
|
||||
print("PaymentChannelCreate transaction response:")
|
||||
print(payment_channel_response)
|
||||
|
||||
# Check that the object was actually created and get the channel ID
|
||||
account_objects_request = AccountObjects(
|
||||
account=wallet1.address,
|
||||
)
|
||||
account_objects_response = client.request(account_objects_request)
|
||||
account_objects = account_objects_response.result["account_objects"]
|
||||
|
||||
# Find the payment channel from account objects and get its ID
|
||||
channel_id = None
|
||||
for obj in account_objects:
|
||||
if obj.get("LedgerEntryType") == "PayChannel":
|
||||
channel_id = obj["index"]
|
||||
break
|
||||
|
||||
if not channel_id:
|
||||
raise Exception("Could not find PayChannel in account objects")
|
||||
|
||||
print(f"Payment Channel ID: {channel_id}")
|
||||
|
||||
# Destination claims the Payment Channel
|
||||
payment_channel_claim = PaymentChannelClaim(
|
||||
account=wallet2.address,
|
||||
channel=channel_id,
|
||||
amount="100",
|
||||
sequence=payment_channel_response.result["tx_json"]["Sequence"],
|
||||
fee="12", # Fee in drops (0.000012 XRP)
|
||||
)
|
||||
|
||||
print("Submitting a PaymentChannelClaim transaction...")
|
||||
channel_claim_response = submit(
|
||||
payment_channel_claim,
|
||||
wallet2,
|
||||
)
|
||||
print("PaymentChannelClaim transaction response:")
|
||||
print(channel_claim_response)
|
||||
|
||||
print("Balances of wallets after Payment Channel is claimed:")
|
||||
print(f"Balance of {wallet1.address} is {get_balance(wallet1.address, client)} XRP")
|
||||
print(f"Balance of {wallet2.address} is {get_balance(wallet2.address, client)} XRP")
|
||||
|
||||
except Exception as e:
|
||||
print(f"An error occurred: {e}")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
claim_pay_channel()
|
||||
1
_code-samples/claim-payment-channel/py/requirements.txt
Normal file
1
_code-samples/claim-payment-channel/py/requirements.txt
Normal file
@@ -0,0 +1 @@
|
||||
xrpl-py>=2.0.0
|
||||
223
_code-samples/modular-tutorials/account-support.js
Normal file
223
_code-samples/modular-tutorials/account-support.js
Normal file
@@ -0,0 +1,223 @@
|
||||
// ******************************************************
|
||||
// ************* Get the Preferred Network **************
|
||||
// ******************************************************
|
||||
|
||||
function getNet() {
|
||||
let net
|
||||
if (document.getElementById("tn").checked) net = "wss://s.altnet.rippletest.net:51233/"
|
||||
if (document.getElementById("dn").checked) net = "wss://s.devnet.rippletest.net:51233/"
|
||||
return net
|
||||
} // End of getNet()
|
||||
|
||||
// *******************************************************
|
||||
// ************* Get Account *****************************
|
||||
// *******************************************************
|
||||
|
||||
async function getAccount() {
|
||||
let net = getNet()
|
||||
const client = new xrpl.Client(net)
|
||||
await client.connect()
|
||||
resultField.value = `===Getting Account===\n\nConnected to ${net}.`
|
||||
try {
|
||||
let faucetHost = null
|
||||
const my_wallet = (await client.fundWallet(null, { faucetHost})).wallet
|
||||
const newAccount = [my_wallet.address, my_wallet.seed]
|
||||
return (newAccount)
|
||||
}
|
||||
catch (error) {
|
||||
console.error('===Error getting account:', error);
|
||||
results += `\nError: ${error.message}\n`
|
||||
resultField.value = results
|
||||
throw error; // Re-throw the error to be handled by the caller
|
||||
}
|
||||
finally {
|
||||
// Disconnect from the client
|
||||
if (client && client.isConnected()) {
|
||||
await client.disconnect();
|
||||
} }
|
||||
} // End of getAccount()
|
||||
|
||||
async function getNewAccount1() {
|
||||
account1address.value = "=== Getting new account. ===\n\n"
|
||||
account1seed.value = ""
|
||||
const accountInfo= await getAccount()
|
||||
account1address.value = accountInfo[0]
|
||||
account1seed.value = accountInfo[1]
|
||||
}
|
||||
|
||||
async function getNewAccount2() {
|
||||
account2address.value = "=== Getting new account. ===\n\n"
|
||||
account2seed.value = ""
|
||||
const accountInfo= await getAccount()
|
||||
account2address.value = accountInfo[0]
|
||||
account2seed.value = accountInfo[1]
|
||||
}
|
||||
|
||||
// *****************************************************
|
||||
// ********** Get Account from Seed ********************
|
||||
// *****************************************************
|
||||
|
||||
async function getAccountFromSeed(my_seed) {
|
||||
const net = getNet()
|
||||
const client = new xrpl.Client(net)
|
||||
await client.connect()
|
||||
let results = '===Finding wallet.===\n\n'
|
||||
resultField.value = results
|
||||
try {
|
||||
const wallet = xrpl.Wallet.fromSeed(my_seed)
|
||||
const address = wallet.address
|
||||
results += "===Wallet found.===\n\n"
|
||||
results += "Account address: " + address + "\n\n"
|
||||
resultField.value = results
|
||||
return (address)
|
||||
}
|
||||
catch (error) {
|
||||
console.error('===Error getting account from seed:', error);
|
||||
results += `\nError: ${error.message}\n`
|
||||
resultField.value = results
|
||||
throw error; // Re-throw the error to be handled by the caller
|
||||
}
|
||||
finally {
|
||||
// Disconnect from the client
|
||||
if (client && client.isConnected()) {
|
||||
await client.disconnect();
|
||||
} }
|
||||
} // End of getAccountFromSeed()
|
||||
|
||||
// *****************************************************
|
||||
// ********** Get Account from Seed1 *******************
|
||||
// *****************************************************
|
||||
|
||||
async function getAccountFromSeed1() {
|
||||
account1address.value = await getAccountFromSeed(account1seed.value)
|
||||
}
|
||||
|
||||
// *****************************************************
|
||||
// ********** Get Account from Seed2 *******************
|
||||
// *****************************************************
|
||||
|
||||
async function getAccountFromSeed2() {
|
||||
account2address.value = await getAccountFromSeed(account2seed.value)
|
||||
}
|
||||
|
||||
// *****************************************************
|
||||
// ************ Gather Account Info ********************
|
||||
// *****************************************************
|
||||
|
||||
function gatherAccountInfo() {
|
||||
let accountData = account1name.value + "\n" + account1address.value + "\n" + account1seed.value + "\n"
|
||||
accountData += account2name.value + "\n" + account2address.value + "\n" + account2seed.value
|
||||
resultField.value = accountData
|
||||
}
|
||||
|
||||
// *****************************************************
|
||||
// ********** Distribute Account Info ******************
|
||||
// *****************************************************
|
||||
|
||||
function distributeAccountInfo() {
|
||||
let accountInfo = resultField.value.split("\n")
|
||||
account1name.value = accountInfo[0]
|
||||
account1address.value = accountInfo[1]
|
||||
account1seed.value = accountInfo[2]
|
||||
account2name.value = accountInfo[3]
|
||||
account2address.value = accountInfo[4]
|
||||
account2seed.value = accountInfo[5]
|
||||
}
|
||||
|
||||
// *****************************************************
|
||||
// ************ Populate Active Form 1 *****************
|
||||
// *****************************************************
|
||||
|
||||
function populate1() {
|
||||
accountNameField.value = account1name.value
|
||||
accountAddressField.value = account1address.value
|
||||
accountSeedField.value = account1seed.value
|
||||
getXrpBalance()
|
||||
}
|
||||
|
||||
// *****************************************************
|
||||
// ************ Populate Active Form 2 *****************
|
||||
// *****************************************************
|
||||
|
||||
function populate2() {
|
||||
accountNameField.value = account2name.value
|
||||
accountAddressField.value = account2address.value
|
||||
accountSeedField.value = account2seed.value
|
||||
getXrpBalance()
|
||||
}
|
||||
|
||||
// *******************************************************
|
||||
// **************** Get XRP Balance *********************
|
||||
// *******************************************************
|
||||
|
||||
async function getXrpBalance() {
|
||||
const net = getNet()
|
||||
const client = new xrpl.Client(net)
|
||||
await client.connect()
|
||||
let results = `\n===Getting XRP balance...===\n\n`
|
||||
resultField.value = results
|
||||
try {
|
||||
const wallet = xrpl.Wallet.fromSeed(accountSeedField.value)
|
||||
const balance = await client.getXrpBalance(wallet.address)
|
||||
results += accountNameField.value + " current XRP balance: " + balance + "\n\n"
|
||||
xrpBalanceField.value = await client.getXrpBalance(accountAddressField.value)
|
||||
resultField.value = results
|
||||
}
|
||||
catch (error) {
|
||||
console.error('Error getting XRP balance:', error);
|
||||
results += `\nError: ${error.message}\n`
|
||||
resultField.value = results
|
||||
throw error; // Re-throw the error to be handled by the caller
|
||||
}
|
||||
finally {
|
||||
// Disconnect from the client
|
||||
if (client && client.isConnected()) {
|
||||
await client.disconnect();
|
||||
} }
|
||||
} // End of getXrpBalance()
|
||||
|
||||
// *******************************************************
|
||||
// ************** Get Token Balance *********************
|
||||
// *******************************************************
|
||||
|
||||
async function getTokenBalance() {
|
||||
let net = getNet()
|
||||
const client = new xrpl.Client(net)
|
||||
await client.connect()
|
||||
let results = `===Connected to ${net}.===\n===Getting account token balance...===\n\n`
|
||||
resultField.value += results
|
||||
try {
|
||||
const wallet = xrpl.Wallet.fromSeed(accountSeedField.value)
|
||||
const balance = await client.request({
|
||||
command: "gateway_balances",
|
||||
account: wallet.address,
|
||||
ledger_index: "validated",
|
||||
})
|
||||
results = accountNameField.value + "\'s token balance(s): " + JSON.stringify(balance.result, null, 2) + "\n"
|
||||
resultField.value += results
|
||||
xrpBalanceField.value = (await client.getXrpBalance(wallet.address))
|
||||
}
|
||||
catch (error) {
|
||||
console.error('Error getting token balance:', error);
|
||||
results = `\nError: ${error.message}\n`
|
||||
resultField.value += results
|
||||
throw error; // Re-throw the error to be handled by the caller
|
||||
}
|
||||
finally {
|
||||
// Disconnect from the client
|
||||
if (client && client.isConnected()) {
|
||||
await client.disconnect();
|
||||
} }
|
||||
} // End of getTokenBalance()
|
||||
|
||||
// *******************************************************
|
||||
// **************** Scroll Results ***********************
|
||||
// *******************************************************
|
||||
let results
|
||||
|
||||
async function updateResults() {
|
||||
resultField.value += results;
|
||||
resultField.scrollTop = resultField.scrollHeight;
|
||||
}
|
||||
|
||||
// End of updateResults()
|
||||
201
_code-samples/modular-tutorials/base-module.html
Normal file
201
_code-samples/modular-tutorials/base-module.html
Normal file
@@ -0,0 +1,201 @@
|
||||
<html>
|
||||
<head>
|
||||
<title>XRPL Base Module</title>
|
||||
<link href='https://fonts.googleapis.com/css?family=Work Sans' rel='stylesheet'>
|
||||
<link href="modular-tutorials.css" rel="stylesheet">
|
||||
<script src='https://unpkg.com/xrpl@4.1.0/build/xrpl-latest.js'></script>
|
||||
<script src="account-support.js"></script>
|
||||
<script src='send-xrp.js'></script>
|
||||
</head>
|
||||
|
||||
<!-- ************************************************************** -->
|
||||
<!-- ********************** The Form ****************************** -->
|
||||
<!-- ************************************************************** -->
|
||||
|
||||
<body>
|
||||
<h1>XRPL Base Module</h1>
|
||||
<form id="theForm">
|
||||
<span class="tooltip" tooltip-data="Choose the XRPL host server for your account.">
|
||||
Choose your ledger instance:
|
||||
</span>
|
||||
|
||||
<input type="radio" id="dn" name="server" value="wss://s.devnet.rippletest.net:51233" checked>
|
||||
<label for="dn">Devnet</label>
|
||||
|
||||
<input type="radio" id="tn" name="server" value="wss://s.altnet.rippletest.net:51233">
|
||||
<label for="tn">Testnet</label>
|
||||
<br /><br />
|
||||
<table>
|
||||
<tr>
|
||||
<td>
|
||||
<button type="button" onClick="getNewAccount1()">Get New Account 1</button>
|
||||
</td>
|
||||
<td>
|
||||
<button type="button" onClick="getAccountFromSeed1()">Get Account 1 From Seed</button>
|
||||
</td>
|
||||
<td>
|
||||
<button type="button" onClick="getNewAccount2()">Get New Account 2</button>
|
||||
</td>
|
||||
<td>
|
||||
<button type="button" onClick="getAccountFromSeed2()">Get Account 2 From Seed</button>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<span class="tooltip" tooltip-data="Arbitrary human-readable name for the account."><label for="account1name">Account 1 Name</label>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="account1name" size="40"></input>
|
||||
</td>
|
||||
<td>
|
||||
<span class="tooltip" tooltip-data="Arbitrary human-readable name for the account.">
|
||||
<label for="account2name">Account 2 Name</label>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="account2name" size="40"></input>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<span class="tooltip" tooltip-data="Identifying address for the account.">
|
||||
<label for="account1address">Account 1 Address</label>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="account1address" size="40"></input>
|
||||
</td>
|
||||
<td>
|
||||
<span class="tooltip" tooltip-data="Identifying address for the account.">
|
||||
<label for="account2address">Account 2 Address</label>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="account2address" size="40"></input>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<span class="tooltip" tooltip-data="Seed for deriving public and private keys for the account.">
|
||||
<label for="account1seed">Account 1 Seed</label>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="account1seed" size="40"></input>
|
||||
</td>
|
||||
<td>
|
||||
<span class="tooltip" tooltip-data="Seed for deriving public and private keys for the account.">
|
||||
<label for="account2seed">Account 2 Seed</label>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="account2seed" size="40"></input>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<hr />
|
||||
<table>
|
||||
<tr valign="top">
|
||||
<td align="right">
|
||||
<span class="tooltip" tooltip-data="Name of the currently selected account.">
|
||||
<label for="accountNameField">Account Name</label>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="accountNameField" size="40" readonly></input>
|
||||
<input type="radio" id="account1" name="accounts" value="account1">
|
||||
<label for="account1">Account 1</label>
|
||||
</td>
|
||||
</tr>
|
||||
<tr valign="top">
|
||||
<td align="right">
|
||||
<span class="tooltip" tooltip-data="Address of the currently selected account.">
|
||||
<label for="accountAddressField">Account Address</label>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="accountAddressField" size="40" readonly></input>
|
||||
<input type="radio" id="account2" name="accounts" value="account2">
|
||||
<label for="account2">Account 2</label>
|
||||
</td>
|
||||
</tr>
|
||||
<tr valign="top">
|
||||
<td align="right">
|
||||
<span class="tooltip" tooltip-data="Seed of the currently selected account.">
|
||||
<label for="accountSeedField">Account Seed</label>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="accountSeedField" size="40" readonly></input>
|
||||
<br>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="right">
|
||||
<span class="tooltip" tooltip-data="XRP balance for the currently selected account.">
|
||||
<label for="xrpBalanceField">XRP Balance</label>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="xrpBalanceField" size="40" readonly></input>
|
||||
</td>
|
||||
<td>
|
||||
<button type="button" onClick="sendXRP()">Send XRP</button>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="right">
|
||||
<span class="tooltip" tooltip-data="Amount of XRP to send.">
|
||||
<label for="amountField">Amount</label>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="amountField" size="40"></input>
|
||||
<br>
|
||||
</td>
|
||||
<td align="left" valign="top">
|
||||
<button type="button" onClick="getXrpBalance()">Get XRP Balance</button>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="right">
|
||||
<span class="tooltip" tooltip-data="Destination account address where XRP is sent.">
|
||||
<lable for="destinationField">Destination</lable>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="destinationField" size="40"></input>
|
||||
<br>
|
||||
</td>
|
||||
<td align="left" valign="top">
|
||||
<button type="button" onClick="getTokenBalance()">Get Token Balance</button>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="2">
|
||||
<p align="right">
|
||||
<textarea id="resultField" cols="80" rows="20"></textarea>
|
||||
</p>
|
||||
</td>
|
||||
<td align="left" valign="top">
|
||||
<button type="button" onClick="gatherAccountInfo()">Gather Account Info</button><br/>
|
||||
<button type="button" onClick="distributeAccountInfo()">Distribute Account Info</button>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</form>
|
||||
</body>
|
||||
<script>
|
||||
const radioButtons = document.querySelectorAll('input[type="radio"]');
|
||||
radioButtons.forEach(radio => {
|
||||
radio.addEventListener('change', function() {
|
||||
if (this.value === 'account1') {
|
||||
populate1()
|
||||
} else if (this.value === 'account2') {
|
||||
populate2()
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
</html>
|
||||
280
_code-samples/modular-tutorials/create-conditional-escrow.html
Normal file
280
_code-samples/modular-tutorials/create-conditional-escrow.html
Normal file
@@ -0,0 +1,280 @@
|
||||
<html>
|
||||
<head>
|
||||
<title>Create a Conditional Escrow</title>
|
||||
<link href='https://fonts.googleapis.com/css?family=Work Sans' rel='stylesheet'>
|
||||
<link href="modular-tutorials.css" rel="stylesheet">
|
||||
<script src='https://unpkg.com/xrpl@4.1.0/build/xrpl-latest.js'></script>
|
||||
<script src="account-support.js"></script>
|
||||
<script src="create-time-escrow.js"></script>
|
||||
<script src='create-conditional-escrow.js'></script>
|
||||
<script>
|
||||
if (typeof module !== "undefined") {
|
||||
const xrpl = require('xrpl')
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
|
||||
<!-- ************************************************************** -->
|
||||
<!-- ********************** The Form ****************************** -->
|
||||
<!-- ************************************************************** -->
|
||||
|
||||
<body>
|
||||
<h1>Create a Conditional Escrow</h1>
|
||||
<form id="theForm">
|
||||
<span class="tooltip" tooltip-data="Choose the XRPL host server for your account.">
|
||||
Choose your ledger instance:
|
||||
</span>
|
||||
|
||||
<input type="radio" id="dn" name="server" value="wss://s.devnet.rippletest.net:51233" checked>
|
||||
<label for="dn">Devnet</label>
|
||||
|
||||
<input type="radio" id="tn" name="server" value="wss://s.altnet.rippletest.net:51233">
|
||||
<label for="tn">Testnet</label>
|
||||
<br /><br />
|
||||
<table>
|
||||
<tr>
|
||||
<td>
|
||||
<button type="button" onClick="getNewAccount1()">Get New Account 1</button>
|
||||
</td>
|
||||
<td>
|
||||
<button type="button" onClick="getAccountFromSeed1()">Get Account 1 From Seed</button>
|
||||
</td>
|
||||
<td>
|
||||
<button type="button" onClick="getNewAccount2()">Get New Account 2</button>
|
||||
</td>
|
||||
<td>
|
||||
<button type="button" onClick="getAccountFromSeed2()">Get Account 2 From Seed</button>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<span class="tooltip" tooltip-data="Arbitrary human-readable name for the account."><label for="account1name">Account 1 Name</label>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="account1name" size="40"></input>
|
||||
</td>
|
||||
<td>
|
||||
<span class="tooltip" tooltip-data="Arbitrary human-readable name for the account.">
|
||||
<label for="account2name">Account 2 Name</label>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="account2name" size="40"></input>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<span class="tooltip" tooltip-data="Identifying address for the account.">
|
||||
<label for="account1address">Account 1 Address</label>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="account1address" size="40"></input>
|
||||
</td>
|
||||
<td>
|
||||
<span class="tooltip" tooltip-data="Identifying address for the account.">
|
||||
<label for="account2address">Account 2 Address</label>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="account2address" size="40"></input>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<span class="tooltip" tooltip-data="Seed for deriving public and private keys for the account.">
|
||||
<label for="account1seed">Account 1 Seed</label>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="account1seed" size="40"></input>
|
||||
</td>
|
||||
<td>
|
||||
<span class="tooltip" tooltip-data="Seed for deriving public and private keys for the account.">
|
||||
<label for="account2seed">Account 2 Seed</label>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="account2seed" size="40"></input>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<hr />
|
||||
<table>
|
||||
<tr valign="top">
|
||||
<td align="right">
|
||||
<span class="tooltip" tooltip-data="Name of the currently selected account.">
|
||||
<label for="accountNameField">Account Name</label>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="accountNameField" size="40" readonly></input>
|
||||
<input type="radio" id="account1" name="accounts" value="account1">
|
||||
<label for="account1">Account 1</label>
|
||||
</td>
|
||||
</tr>
|
||||
<tr valign="top">
|
||||
<td align="right">
|
||||
<span class="tooltip" tooltip-data="Address of the currently selected account.">
|
||||
<label for="accountAddressField">Account Address</label>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="accountAddressField" size="40" readonly></input>
|
||||
<input type="radio" id="account2" name="accounts" value="account2">
|
||||
<label for="account2">Account 2</label>
|
||||
</td>
|
||||
</tr>
|
||||
<tr valign="top">
|
||||
<td align="right">
|
||||
<span class="tooltip" tooltip-data="Seed of the currently selected account.">
|
||||
<label for="accountSeedField">Account Seed</label>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="accountSeedField" size="40" readonly></input>
|
||||
<br>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="right">
|
||||
<span class="tooltip" tooltip-data="XRP balance for the currently selected account.">
|
||||
<label for="xrpBalanceField">XRP Balance</label>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="xrpBalanceField" size="40" readonly></input>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="right">
|
||||
<span class="tooltip" tooltip-data="Amount of XRP to send.">
|
||||
<label for="amountField">Amount</label>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="amountField" size="40"></input>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="right">
|
||||
<span class="tooltip" tooltip-data="Destination account address where the escrow is sent.">
|
||||
<lable for="destinationField">Destination</lable>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="destinationField" size="40"></input>
|
||||
<br>
|
||||
</td>
|
||||
<td align="left" valign="top">
|
||||
<button type="button" onClick="createConditionalEscrow()">Create Escrow</button>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="right">
|
||||
<span class="tooltip" tooltip-data="Condition code used to begin the escrow transaction.">
|
||||
<lable for="escrowConditionField">Escrow Condition</lable>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="escrowConditionField" size="40"></input>
|
||||
<br>
|
||||
</td>
|
||||
<td align="left" valign="top">
|
||||
<button type="button" onClick="getEscrows()">Get Escrows</button>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="right">
|
||||
<span class="tooltip" tooltip-data="Fullfillment code to complete the escrow transaction.">
|
||||
<lable for="escrowFulfillmentField">Escrow Fulfillment</lable>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="escrowFulfillmentField" size="40"></input>
|
||||
<br>
|
||||
</td>
|
||||
<td>
|
||||
<button type="button" onClick="finishConditionalEscrow()">Finish Escrow</button>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="right">
|
||||
<span class="tooltip" tooltip-data="Escrow cancel time, in seconds.">
|
||||
<lable for="escrowCancelDateField">Escrow Cancel Time</lable>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="escrowCancelDateField" size="40"></input>
|
||||
<br>
|
||||
</td>
|
||||
<td align="left" valign="top">
|
||||
<button type="button" onClick="cancelEscrow()">Cancel Escrow</button>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="right">
|
||||
<span class="tooltip" tooltip-data="Escrow sequence number, used when finishing the escrow.">
|
||||
<lable for="escrowSequenceNumberField">Escrow Sequence Number</lable>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="escrowSequenceNumberField" size="40"></input>
|
||||
<br>
|
||||
</td>
|
||||
<td>
|
||||
<button type="button" onClick="getTransaction()">Get Transaction</button>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="right">
|
||||
<span class="tooltip" tooltip-data="Escrow owner, the account that created the escrow.">
|
||||
<lable for="escrowOwnerField">Escrow Owner</lable>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="escrowOwnerField" size="40"></input>
|
||||
<br>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="right">
|
||||
<span class="tooltip" tooltip-data="Transaction number, used with the Get Transaction button.">
|
||||
<lable for="transactionField">Transaction</lable>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="transactionField" size="40"></input>
|
||||
<br>
|
||||
</td>
|
||||
<td>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="2">
|
||||
<p align="right">
|
||||
<textarea id="resultField" cols="80" rows="20"></textarea>
|
||||
</p>
|
||||
</td>
|
||||
<td align="left" valign="top">
|
||||
<button type="button" onClick="gatherAccountInfo()">Gather Account Info</button><br/>
|
||||
<button type="button" onClick="distributeAccountInfo()">Distribute Account Info</button>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</form>
|
||||
</body>
|
||||
<script>
|
||||
const radioButtons = document.querySelectorAll('input[type="radio"]');
|
||||
radioButtons.forEach(radio => {
|
||||
radio.addEventListener('change', function() {
|
||||
if (this.value === 'account1') {
|
||||
populate1()
|
||||
} else if (this.value === 'account2') {
|
||||
populate2()
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
</html>
|
||||
86
_code-samples/modular-tutorials/create-conditional-escrow.js
Normal file
86
_code-samples/modular-tutorials/create-conditional-escrow.js
Normal file
@@ -0,0 +1,86 @@
|
||||
// *******************************************************
|
||||
// ************* Create Conditional Escrow ***************
|
||||
// *******************************************************
|
||||
|
||||
async function createConditionalEscrow() {
|
||||
|
||||
//------------------------------------------------------Connect to the Ledger
|
||||
let net = getNet()
|
||||
const client = new xrpl.Client(net)
|
||||
await client.connect()
|
||||
const wallet = xrpl.Wallet.fromSeed(accountSeedField.value)
|
||||
const sendAmount = amountField.value
|
||||
let results = `===Connected to ${net}===\n===Creating conditional escrow.===\n\n`
|
||||
resultField.value = results
|
||||
let escrow_cancel_date = new Date()
|
||||
escrow_cancel_date = addSeconds(parseInt(escrowCancelDateField.value))
|
||||
|
||||
// ------------------------------------------------------- Prepare transaction
|
||||
try {
|
||||
const escrowTx = await client.autofill({
|
||||
"TransactionType": "EscrowCreate",
|
||||
"Account": wallet.address,
|
||||
"Amount": xrpl.xrpToDrops(sendAmount),
|
||||
"Destination": destinationField.value,
|
||||
"CancelAfter": escrow_cancel_date,
|
||||
"Condition": escrowConditionField.value
|
||||
})
|
||||
|
||||
// ------------------------------------------------ Sign prepared instructions
|
||||
const signed = wallet.sign(escrowTx)
|
||||
|
||||
// -------------------------------------------------------- Submit signed blob
|
||||
const tx = await client.submitAndWait(signed.tx_blob)
|
||||
results = "\n=== *** Sequence Number (Save!): " + tx.result.tx_json.Sequence
|
||||
results += "\n\n===Balance changes===\n" +
|
||||
JSON.stringify(xrpl.getBalanceChanges(tx.result.meta), null, 2)
|
||||
xrpBalanceField.value = (await client.getXrpBalance(wallet.address))
|
||||
resultField.value += results
|
||||
}
|
||||
catch (error) {
|
||||
results += "\n===Error: " + error.message
|
||||
resultField.value = results
|
||||
}
|
||||
finally {
|
||||
// -------------------------------------------------------- Disconnect
|
||||
client.disconnect()
|
||||
}
|
||||
} // End of createTimeEscrow()
|
||||
|
||||
// *******************************************************
|
||||
// ************** Finish Conditional Escrow **************
|
||||
// *******************************************************
|
||||
|
||||
async function finishConditionalEscrow() {
|
||||
let net = getNet()
|
||||
const client = new xrpl.Client(net)
|
||||
await client.connect()
|
||||
let results = `===Connected to ${net}===\n===Fulfilling conditional escrow.===\n`
|
||||
resultField.value = results
|
||||
const wallet = xrpl.Wallet.fromSeed(accountSeedField.value)
|
||||
try {
|
||||
// ------------------------------------------------------- Prepare transaction
|
||||
const prepared = await client.autofill({
|
||||
"TransactionType": "EscrowFinish",
|
||||
"Account": accountAddressField.value,
|
||||
"Owner": escrowOwnerField.value,
|
||||
"OfferSequence": parseInt(escrowSequenceNumberField.value),
|
||||
"Condition": escrowConditionField.value,
|
||||
"Fulfillment": escrowFulfillmentField.value
|
||||
})
|
||||
const signed = wallet.sign(prepared)
|
||||
const tx = await client.submitAndWait(signed.tx_blob)
|
||||
results += "\n===Balance changes===" +
|
||||
JSON.stringify(xrpl.getBalanceChanges(tx.result.meta), null, 2)
|
||||
resultField.value = results
|
||||
xrpBalanceField.value = (await client.getXrpBalance(wallet.address))
|
||||
}
|
||||
catch (error) {
|
||||
results += "\n===Error: " + error.message + ".===\n"
|
||||
resultField.value = results
|
||||
}
|
||||
finally {
|
||||
// -------------------------------------------------------- Disconnect
|
||||
client.disconnect()
|
||||
}
|
||||
} // End of finisConditionalEscrow()
|
||||
249
_code-samples/modular-tutorials/create-offer.html
Normal file
249
_code-samples/modular-tutorials/create-offer.html
Normal file
@@ -0,0 +1,249 @@
|
||||
<html>
|
||||
<head>
|
||||
<title>Create Offers</title>
|
||||
<link href='https://fonts.googleapis.com/css?family=Work Sans' rel='stylesheet'>
|
||||
<link href="modular-tutorials.css" rel="stylesheet">
|
||||
<script src='https://unpkg.com/xrpl@4.1.0/build/xrpl-latest.js'></script>
|
||||
<script src="account-support.js"></script>
|
||||
<script src='send-xrp.js'></script>
|
||||
<script src='create-offer.js'></script>
|
||||
<script>
|
||||
if (typeof module !== "undefined") {
|
||||
const xrpl = require('xrpl')
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
|
||||
<!-- ************************************************************** -->
|
||||
<!-- ********************** The Form ****************************** -->
|
||||
<!-- ************************************************************** -->
|
||||
|
||||
<body>
|
||||
<h1>Create Offers</h1>
|
||||
<form id="theForm">
|
||||
<span class="tooltip" tooltip-data="Choose the XRPL host server for your account.">
|
||||
Choose your ledger instance:
|
||||
</span>
|
||||
|
||||
<input type="radio" id="dn" name="server" value="wss://s.devnet.rippletest.net:51233" checked>
|
||||
<label for="dn">Devnet</label>
|
||||
|
||||
<input type="radio" id="tn" name="server" value="wss://s.altnet.rippletest.net:51233">
|
||||
<label for="tn">Testnet</label>
|
||||
<br /><br />
|
||||
<table>
|
||||
<tr>
|
||||
<td>
|
||||
<button type="button" onClick="getNewAccount1()">Get New Account 1</button>
|
||||
</td>
|
||||
<td>
|
||||
<button type="button" onClick="getAccountFromSeed1()">Get Account 1 From Seed</button>
|
||||
</td>
|
||||
<td>
|
||||
<button type="button" onClick="getNewAccount2()">Get New Account 2</button>
|
||||
</td>
|
||||
<td>
|
||||
<button type="button" onClick="getAccountFromSeed2()">Get Account 2 From Seed</button>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<span class="tooltip" tooltip-data="Arbitrary human-readable name for the account."><label for="account1name">Account 1 Name</label>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="account1name" size="40"></input>
|
||||
</td>
|
||||
<td>
|
||||
<span class="tooltip" tooltip-data="Arbitrary human-readable name for the account.">
|
||||
<label for="account2name">Account 2 Name</label>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="account2name" size="40"></input>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<span class="tooltip" tooltip-data="Identifying address for the account.">
|
||||
<label for="account1address">Account 1 Address</label>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="account1address" size="40"></input>
|
||||
</td>
|
||||
<td>
|
||||
<span class="tooltip" tooltip-data="Identifying address for the account.">
|
||||
<label for="account2address">Account 2 Address</label>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="account2address" size="40"></input>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<span class="tooltip" tooltip-data="Seed for deriving public and private keys for the account.">
|
||||
<label for="account1seed">Account 1 Seed</label>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="account1seed" size="40"></input>
|
||||
</td>
|
||||
<td>
|
||||
<span class="tooltip" tooltip-data="Seed for deriving public and private keys for the account.">
|
||||
<label for="account2seed">Account 2 Seed</label>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="account2seed" size="40"></input>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<hr />
|
||||
<table>
|
||||
<tr valign="top">
|
||||
<td align="right">
|
||||
<span class="tooltip" tooltip-data="Name of the currently selected account.">
|
||||
<label for="accountNameField">Account Name</label>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="accountNameField" size="40" readonly></input>
|
||||
<input type="radio" id="account1" name="accounts" value="account1">
|
||||
<label for="account1">Account 1</label>
|
||||
</td>
|
||||
</tr>
|
||||
<tr valign="top">
|
||||
<td align="right">
|
||||
<span class="tooltip" tooltip-data="Address of the currently selected account.">
|
||||
<label for="accountAddressField">Account Address</label>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="accountAddressField" size="40" readonly></input>
|
||||
<input type="radio" id="account2" name="accounts" value="account2">
|
||||
<label for="account2">Account 2</label>
|
||||
</td>
|
||||
</tr>
|
||||
<tr valign="top">
|
||||
<td align="right">
|
||||
<span class="tooltip" tooltip-data="Seed of the currently selected account.">
|
||||
<label for="accountSeedField">Account Seed</label>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="accountSeedField" size="40" readonly></input>
|
||||
<br>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="right">
|
||||
<span class="tooltip" tooltip-data="XRP balance for the currently selected account.">
|
||||
<label for="xrpBalanceField">XRP Balance</label>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="xrpBalanceField" size="40" readonly></input>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<table>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td>
|
||||
<h4 align="center">Taker Pays</h4>
|
||||
</td>
|
||||
<td>
|
||||
<h4 align="center">Taker Gets</h4>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="right">
|
||||
<span class="tooltip" tooltip-data="Currency codes for the Pay and Get offers.">
|
||||
<lable for="payCurrencyField">Currency Code</lable>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="payCurrencyField" size="40"></input>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="getCurrencyField" size="40"></input>
|
||||
</td>
|
||||
<td>
|
||||
<button type="button" onClick="createOffer()">Create Offer</button>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="right">
|
||||
<span class="tooltip" tooltip-data="Issuers of the offered currencies.">
|
||||
<lable for="payIssuerField">Issuer</lable>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="payIssuerField" size="40"></input>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="getIssuerField" size="40"></input>
|
||||
</td>
|
||||
<td>
|
||||
<button type="button" onClick="getOffers()">Get Offers</button>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="right">
|
||||
<span class="tooltip" tooltip-data="Amounts of offered currencies.">
|
||||
<lable for="amountField">Amount</lable>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="payAmountField" size="40"></input>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="getAmountField" size="40"></input>
|
||||
</td>
|
||||
<td>
|
||||
<button type="button" onClick="cancelOffer()">Cancel Offer</button>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="right">
|
||||
<span class="tooltip" tooltip-data="Sequence number of the offer.">
|
||||
<lable for="offerSequenceField">Offer Sequence</lable>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="offerSequenceField" size="40"></input>
|
||||
</td>
|
||||
<td></td>
|
||||
<td>
|
||||
<button type="button" onClick="getTokenBalance()">Get Token Balance</button>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="3">
|
||||
<p align="right">
|
||||
<textarea id="resultField" cols="80" rows="20"></textarea>
|
||||
</p>
|
||||
</td>
|
||||
<td align="left" valign="top">
|
||||
<button type="button" onClick="gatherAccountInfo()">Gather Account Info</button><br/>
|
||||
<button type="button" onClick="distributeAccountInfo()">Distribute Account Info</button>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</form>
|
||||
</body>
|
||||
<script>
|
||||
const radioButtons = document.querySelectorAll('input[type="radio"]');
|
||||
radioButtons.forEach(radio => {
|
||||
radio.addEventListener('change', function() {
|
||||
if (this.value === 'account1') {
|
||||
populate1()
|
||||
} else if (this.value === 'account2') {
|
||||
populate2()
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
</html>
|
||||
121
_code-samples/modular-tutorials/create-offer.js
Normal file
121
_code-samples/modular-tutorials/create-offer.js
Normal file
@@ -0,0 +1,121 @@
|
||||
/***********************************
|
||||
*********** Create Offer **********
|
||||
**********************************/
|
||||
|
||||
async function createOffer() {
|
||||
let net = getNet()
|
||||
const client = new xrpl.Client(net)
|
||||
await client.connect()
|
||||
let results = `===Connected to ${net}, getting wallet....===\n`
|
||||
resultField.value = results
|
||||
const wallet = xrpl.Wallet.fromSeed(accountSeedField.value)
|
||||
try {
|
||||
if (getCurrencyField.value == 'XRP') {
|
||||
takerGets = xrpl.xrpToDrops(getAmountField.value)
|
||||
}
|
||||
else {
|
||||
takerGetsString = '{"currency": "' + getCurrencyField.value + '",\n' +
|
||||
'"issuer": "' + getIssuerField.value + '",\n' +
|
||||
'"value": "' + getAmountField.value + '"}'
|
||||
takerGets = JSON.parse(takerGetsString)
|
||||
}
|
||||
|
||||
if (payCurrencyField.value == 'XRP') {
|
||||
takerPays = xrpl.xrpToDrops(payAmountField.value)
|
||||
} else {
|
||||
takerPaysString = '{"currency": "' + payCurrencyField.value + '",\n' +
|
||||
'"issuer": "' + payIssuerField.value + '",\n' +
|
||||
'"value": "' + payAmountField.value + '"}'
|
||||
takerPays = JSON.parse(takerPaysString)
|
||||
}
|
||||
const prepared = await client.autofill({
|
||||
"TransactionType": "OfferCreate",
|
||||
"Account": wallet.address,
|
||||
"TakerGets": takerGets,
|
||||
"TakerPays": takerPays
|
||||
})
|
||||
const signed = wallet.sign(prepared)
|
||||
const tx = await client.submitAndWait(signed.tx_blob)
|
||||
results = '\n\n===Offer created===\n\n' +
|
||||
JSON.stringify(xrpl.getBalanceChanges(tx.result.meta), null, 2)
|
||||
resultField.value += results
|
||||
xrpBalanceField.value = (await client.getXrpBalance(wallet.address))
|
||||
} catch (err) {
|
||||
console.error('Error creating offer:', err);
|
||||
results = `\nError: ${err.message}\n`
|
||||
resultField.value += results
|
||||
throw err; // Re-throw the error to be handled by the caller
|
||||
}
|
||||
finally {
|
||||
// Disconnect from the client
|
||||
client.disconnect()
|
||||
}
|
||||
} // End of createOffer()
|
||||
|
||||
/***********************************
|
||||
************ Get Offers ***********
|
||||
**********************************/
|
||||
|
||||
async function getOffers() {
|
||||
let net = getNet()
|
||||
const client = new xrpl.Client(net)
|
||||
await client.connect()
|
||||
let results = `===Connected to ' + ${net}, getting offers....===\n`
|
||||
const wallet = xrpl.Wallet.fromSeed(accountSeedField.value)
|
||||
resultField.value = results
|
||||
results += '\n\n=== Offers ===\n'
|
||||
let offers
|
||||
try {
|
||||
offers = await client.request({
|
||||
method: "account_offers",
|
||||
account: wallet.address,
|
||||
ledger_index: "validated"
|
||||
})
|
||||
results = JSON.stringify(offers, null, 2)
|
||||
resultField.value += results
|
||||
} catch (err) {
|
||||
console.error('Error getting offers:', err);
|
||||
results = `\nError: ${err.message}\n`
|
||||
resultField.value += results
|
||||
throw err; // Re-throw the error to be handled by the caller
|
||||
}
|
||||
finally {
|
||||
client.disconnect()
|
||||
}
|
||||
}// End of getOffers()
|
||||
|
||||
/***********************************
|
||||
*********** Cancel Offer **********
|
||||
**********************************/
|
||||
async function cancelOffer() {
|
||||
let net = getNet()
|
||||
const client = new xrpl.Client(net)
|
||||
await client.connect()
|
||||
let results = `===Connected to ${net}, canceling offer.===\n`
|
||||
resultField.value = results
|
||||
const wallet = xrpl.Wallet.fromSeed(accountSeedField.value)
|
||||
try {
|
||||
// OfferSequence is the _seq_ value from getOffers.
|
||||
const prepared = await client.autofill({
|
||||
"TransactionType": "OfferCancel",
|
||||
"Account": wallet.address,
|
||||
"OfferSequence": parseInt(offerSequenceField.value)
|
||||
})
|
||||
const signed = wallet.sign(prepared)
|
||||
const tx = await client.submitAndWait(signed.tx_blob)
|
||||
results += "\nOffer canceled. Balance changes: \n" +
|
||||
JSON.stringify(xrpl.getBalanceChanges(tx.result.meta), null, 2)
|
||||
resultField.value = results
|
||||
xrpBalanceField.value = (await client.getXrpBalance(wallet.address))
|
||||
}
|
||||
catch (err) {
|
||||
console.error('Error canceling offer:', err);
|
||||
results = `\nError: ${err.message}\n`
|
||||
resultField.value += results
|
||||
throw err; // Re-throw the error to be handled by the caller
|
||||
}
|
||||
finally {
|
||||
// Disconnect from the client
|
||||
client.disconnect()
|
||||
}
|
||||
}// End of cancelOffer()
|
||||
211
_code-samples/modular-tutorials/create-permissioned-domain.html
Normal file
211
_code-samples/modular-tutorials/create-permissioned-domain.html
Normal file
@@ -0,0 +1,211 @@
|
||||
<html>
|
||||
<head>
|
||||
<title>Create Permissioned Domain</title>
|
||||
<link href='https://fonts.googleapis.com/css?family=Work Sans' rel='stylesheet'>
|
||||
<link href="modular-tutorials.css" rel="stylesheet">
|
||||
<script src='https://unpkg.com/xrpl@4.2.5/build/xrpl-latest.js'></script>
|
||||
<script src="account-support.js"></script>
|
||||
<script src='credential-manager.js'></script>
|
||||
<script src='permissioned-domain-manager.js'></script>
|
||||
</head>
|
||||
|
||||
<!-- ************************************************************** -->
|
||||
<!-- ********************** The Form ****************************** -->
|
||||
<!-- ************************************************************** -->
|
||||
|
||||
<body>
|
||||
<h1>Create Permissioned Domain</h1>
|
||||
<form id="theForm">
|
||||
<span class="tooltip" tooltip-data="Choose the XRPL host server for your account.">
|
||||
Choose your ledger instance:
|
||||
</span>
|
||||
|
||||
<input type="radio" id="dn" name="server" value="wss://s.devnet.rippletest.net:51233" checked>
|
||||
<label for="dn">Devnet</label>
|
||||
|
||||
<input type="radio" id="tn" name="server" value="wss://s.altnet.rippletest.net:51233">
|
||||
<label for="tn">Testnet</label>
|
||||
<br /><br />
|
||||
<table>
|
||||
<tr>
|
||||
<td>
|
||||
<button type="button" onClick="getNewAccount1()">Get New Account 1</button>
|
||||
</td>
|
||||
<td>
|
||||
<button type="button" onClick="getAccountFromSeed1()">Get Account 1 From Seed</button>
|
||||
</td>
|
||||
<td>
|
||||
<button type="button" onClick="getNewAccount2()">Get New Account 2</button>
|
||||
</td>
|
||||
<td>
|
||||
<button type="button" onClick="getAccountFromSeed2()">Get Account 2 From Seed</button>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<span class="tooltip" tooltip-data="Arbitrary human-readable name for the account."><label for="account1name">Account 1 Name</label>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="account1name" size="40"></input>
|
||||
</td>
|
||||
<td>
|
||||
<span class="tooltip" tooltip-data="Arbitrary human-readable name for the account.">
|
||||
<label for="account2name">Account 2 Name</label>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="account2name" size="40"></input>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<span class="tooltip" tooltip-data="Identifying address for the account.">
|
||||
<label for="account1address">Account 1 Address</label>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="account1address" size="40"></input>
|
||||
</td>
|
||||
<td>
|
||||
<span class="tooltip" tooltip-data="Identifying address for the account.">
|
||||
<label for="account2address">Account 2 Address</label>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="account2address" size="40"></input>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<span class="tooltip" tooltip-data="Seed for deriving public and private keys for the account.">
|
||||
<label for="account1seed">Account 1 Seed</label>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="account1seed" size="40"></input>
|
||||
</td>
|
||||
<td>
|
||||
<span class="tooltip" tooltip-data="Seed for deriving public and private keys for the account.">
|
||||
<label for="account2seed">Account 2 Seed</label>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="account2seed" size="40"></input>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<hr />
|
||||
<table>
|
||||
<tr valign="top">
|
||||
<td align="right">
|
||||
<span class="tooltip" tooltip-data="Name of the currently selected account.">
|
||||
<label for="accountNameField">Account Name</label>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="accountNameField" size="40" readonly></input>
|
||||
<input type="radio" id="account1" name="accounts" value="account1">
|
||||
<label for="account1">Account 1</label>
|
||||
</td>
|
||||
</tr>
|
||||
<tr valign="top">
|
||||
<td align="right">
|
||||
<span class="tooltip" tooltip-data="Address of the currently selected account.">
|
||||
<label for="accountAddressField">Account Address</label>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="accountAddressField" size="40" readonly></input>
|
||||
<input type="radio" id="account2" name="accounts" value="account2">
|
||||
<label for="account2">Account 2</label>
|
||||
</td>
|
||||
</tr>
|
||||
<tr valign="top">
|
||||
<td align="right">
|
||||
<span class="tooltip" tooltip-data="Seed of the currently selected account.">
|
||||
<label for="accountSeedField">Account Seed</label>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="accountSeedField" size="40" readonly></input>
|
||||
<br>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="right">
|
||||
<span class="tooltip" tooltip-data="XRP balance for the currently selected account.">
|
||||
<label for="xrpBalanceField">XRP Balance</label>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="xrpBalanceField" size="40" readonly></input>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="right">
|
||||
<span class="tooltip" tooltip-data="Account receiving the credential.">
|
||||
<label for="subjectField">Subject</label>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="subjectField" size="40"></input>
|
||||
<br>
|
||||
</td>
|
||||
<td align="left" valign="top">
|
||||
<button type="button" onClick="createCredential()">Create Credential</button>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="right">
|
||||
<span class="tooltip" tooltip-data="Arbitrary data defining the type of credential this entry represents.">
|
||||
<lable for="credentialTypeField">Credential Type</lable>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="credentialTypeField" size="40"></input>
|
||||
<br>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="right">
|
||||
<span class="tooltip" tooltip-data="The ledger entry ID of an existing permissioned domain to modify. If omitted, creates a new permissioned domain.">
|
||||
<label for="domainIDField">Domain ID</label>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="domainIDField" size="40"></input>
|
||||
<br>
|
||||
</td>
|
||||
<td align="left" valign="top">
|
||||
<button type="button" onClick="createDomain()">Create Permissioned Domain</button>
|
||||
<button type="button" onClick="deleteDomain()">Delete Permissioned Domain</button>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="2">
|
||||
<p align="right">
|
||||
<textarea id="resultField" cols="80" rows="20"></textarea>
|
||||
</p>
|
||||
</td>
|
||||
<td align="left" valign="top">
|
||||
<button type="button" onClick="gatherAccountInfo()">Gather Account Info</button><br/>
|
||||
<button type="button" onClick="distributeAccountInfo()">Distribute Account Info</button>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</form>
|
||||
</body>
|
||||
<script>
|
||||
const radioButtons = document.querySelectorAll('input[type="radio"]');
|
||||
radioButtons.forEach(radio => {
|
||||
radio.addEventListener('change', function() {
|
||||
if (this.value === 'account1') {
|
||||
populate1()
|
||||
} else if (this.value === 'account2') {
|
||||
populate2()
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
</html>
|
||||
269
_code-samples/modular-tutorials/create-time-escrow.html
Normal file
269
_code-samples/modular-tutorials/create-time-escrow.html
Normal file
@@ -0,0 +1,269 @@
|
||||
<html>
|
||||
<head>
|
||||
<title>Create a Time-based Escrow</title>
|
||||
<link href='https://fonts.googleapis.com/css?family=Work Sans' rel='stylesheet'>
|
||||
<link href="modular-tutorials.css" rel="stylesheet">
|
||||
<script src='https://unpkg.com/xrpl@4.1.0/build/xrpl-latest.js'></script>
|
||||
<script src="account-support.js"></script>
|
||||
<script src='create-time-escrow.js'></script>
|
||||
<script>
|
||||
if (typeof module !== "undefined") {
|
||||
const xrpl = require('xrpl')
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
|
||||
<!-- ************************************************************** -->
|
||||
<!-- ********************** The Form ****************************** -->
|
||||
<!-- ************************************************************** -->
|
||||
|
||||
<body>
|
||||
<h1>Create a Time-based Escrow</h1>
|
||||
<form id="theForm">
|
||||
<span class="tooltip" tooltip-data="Choose the XRPL host server for your account.">
|
||||
Choose your ledger instance:
|
||||
</span>
|
||||
|
||||
<input type="radio" id="dn" name="server" value="wss://s.devnet.rippletest.net:51233" checked>
|
||||
<label for="dn">Devnet</label>
|
||||
|
||||
<input type="radio" id="tn" name="server" value="wss://s.altnet.rippletest.net:51233">
|
||||
<label for="tn">Testnet</label>
|
||||
<br /><br />
|
||||
<table>
|
||||
<tr>
|
||||
<td>
|
||||
<button type="button" onClick="getNewAccount1()">Get New Account 1</button>
|
||||
</td>
|
||||
<td>
|
||||
<button type="button" onClick="getAccountFromSeed1()">Get Account 1 From Seed</button>
|
||||
</td>
|
||||
<td>
|
||||
<button type="button" onClick="getNewAccount2()">Get New Account 2</button>
|
||||
</td>
|
||||
<td>
|
||||
<button type="button" onClick="getAccountFromSeed2()">Get Account 2 From Seed</button>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<span class="tooltip" tooltip-data="Arbitrary human-readable name for the account."><label for="account1name">Account 1 Name</label>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="account1name" size="40"></input>
|
||||
</td>
|
||||
<td>
|
||||
<span class="tooltip" tooltip-data="Arbitrary human-readable name for the account.">
|
||||
<label for="account2name">Account 2 Name</label>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="account2name" size="40"></input>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<span class="tooltip" tooltip-data="Identifying address for the account.">
|
||||
<label for="account1address">Account 1 Address</label>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="account1address" size="40"></input>
|
||||
</td>
|
||||
<td>
|
||||
<span class="tooltip" tooltip-data="Identifying address for the account.">
|
||||
<label for="account2address">Account 2 Address</label>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="account2address" size="40"></input>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<span class="tooltip" tooltip-data="Seed for deriving public and private keys for the account.">
|
||||
<label for="account1seed">Account 1 Seed</label>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="account1seed" size="40"></input>
|
||||
</td>
|
||||
<td>
|
||||
<span class="tooltip" tooltip-data="Seed for deriving public and private keys for the account.">
|
||||
<label for="account2seed">Account 2 Seed</label>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="account2seed" size="40"></input>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<hr />
|
||||
<table>
|
||||
<tr valign="top">
|
||||
<td align="right">
|
||||
<span class="tooltip" tooltip-data="Name of the currently selected account.">
|
||||
<label for="accountNameField">Account Name</label>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="accountNameField" size="40" readonly></input>
|
||||
<input type="radio" id="account1" name="accounts" value="account1">
|
||||
<label for="account1">Account 1</label>
|
||||
</td>
|
||||
</tr>
|
||||
<tr valign="top">
|
||||
<td align="right">
|
||||
<span class="tooltip" tooltip-data="Address of the currently selected account.">
|
||||
<label for="accountAddressField">Account Address</label>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="accountAddressField" size="40" readonly></input>
|
||||
<input type="radio" id="account2" name="accounts" value="account2">
|
||||
<label for="account2">Account 2</label>
|
||||
</td>
|
||||
</tr>
|
||||
<tr valign="top">
|
||||
<td align="right">
|
||||
<span class="tooltip" tooltip-data="Seed of the currently selected account.">
|
||||
<label for="accountSeedField">Account Seed</label>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="accountSeedField" size="40" readonly></input>
|
||||
<br>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="right">
|
||||
<span class="tooltip" tooltip-data="XRP balance for the currently selected account.">
|
||||
<label for="xrpBalanceField">XRP Balance</label>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="xrpBalanceField" size="40" readonly></input>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="right">
|
||||
<span class="tooltip" tooltip-data="Amount of XRP to send.">
|
||||
<label for="amountField">Amount</label>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="amountField" size="40"></input>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="right">
|
||||
<span class="tooltip" tooltip-data="Destination account address where the escrow is sent.">
|
||||
<lable for="destinationField">Destination</lable>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="destinationField" size="40"></input>
|
||||
<br>
|
||||
</td>
|
||||
<td align="left" valign="top">
|
||||
<button type="button" onClick="createTimeBasedEscrow()">Create Time-based Escrow</button>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="right">
|
||||
<span class="tooltip" tooltip-data="Escrow finish time, in seconds.">
|
||||
<lable for="escrowFinishTimeField">Escrow Finish Time</lable>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="escrowFinishTimeField" size="40"></input>
|
||||
<br>
|
||||
</td>
|
||||
<td align="left" valign="top">
|
||||
<button type="button" onClick="getEscrows()">Get Escrows</button>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="right">
|
||||
<span class="tooltip" tooltip-data="Escrow cancel time, in seconds.">
|
||||
<lable for="escrowCancelTimeField">Escrow Cancel Time</lable>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="escrowCancelTimeField" size="40"></input>
|
||||
<br>
|
||||
</td>
|
||||
<td align="left" valign="top">
|
||||
<button type="button" onClick="finishTimeBasedEscrow()">Finish Time-based Escrow</button>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="right">
|
||||
<span class="tooltip" tooltip-data="Escrow sequence number, used when finishing the escrow.">
|
||||
<lable for="escrowSequenceNumberField">Escrow Sequence Number</lable>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="escrowSequenceNumberField" size="40"></input>
|
||||
<br>
|
||||
</td>
|
||||
<td>
|
||||
<button type="button" onClick="cancelEscrow()">Cancel Escrow</button>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="right">
|
||||
<span class="tooltip" tooltip-data="Escrow owner, the account that created the escrow.">
|
||||
<lable for="escrowOwnerField">Escrow Owner</lable>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="escrowOwnerField" size="40"></input>
|
||||
<br>
|
||||
</td>
|
||||
<td>
|
||||
<button type="button" onClick="getTransaction()">Get Transaction</button>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="right">
|
||||
<span class="tooltip" tooltip-data="Transaction number, used with the Get Transaction button.">
|
||||
<lable for="transactionField">Transaction</lable>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="transactionField" size="40"></input>
|
||||
<br>
|
||||
</td>
|
||||
<td>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="2">
|
||||
<p align="right">
|
||||
<textarea id="resultField" cols="80" rows="20"></textarea>
|
||||
</p>
|
||||
</td>
|
||||
<td align="left" valign="top">
|
||||
<button type="button" onClick="gatherAccountInfo()">Gather Account Info</button><br/>
|
||||
<button type="button" onClick="distributeAccountInfo()">Distribute Account Info</button>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</form>
|
||||
</body>
|
||||
<script>
|
||||
const radioButtons = document.querySelectorAll('input[type="radio"]');
|
||||
radioButtons.forEach(radio => {
|
||||
radio.addEventListener('change', function() {
|
||||
if (this.value === 'account1') {
|
||||
populate1()
|
||||
} else if (this.value === 'account2') {
|
||||
populate2()
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
</html>
|
||||
177
_code-samples/modular-tutorials/create-time-escrow.js
Normal file
177
_code-samples/modular-tutorials/create-time-escrow.js
Normal file
@@ -0,0 +1,177 @@
|
||||
// *******************************************************
|
||||
// ************* Add Seconds to Current Date *************
|
||||
// *******************************************************
|
||||
|
||||
function addSeconds(numOfSeconds, date = new Date()) {
|
||||
date.setSeconds(date.getSeconds() + numOfSeconds);
|
||||
date = Math.floor(date / 1000)
|
||||
date = date - 946684800
|
||||
|
||||
return date;
|
||||
}
|
||||
|
||||
// *******************************************************
|
||||
// ************* Create Time-based Escrow ****************
|
||||
// *******************************************************
|
||||
|
||||
async function createTimeBasedEscrow() {
|
||||
//-------------------------------------------- Prepare Finish and Cancel Dates
|
||||
let escrow_finish_date = new Date()
|
||||
let escrow_cancel_date = new Date()
|
||||
escrow_finish_date = addSeconds(parseInt(escrowFinishTimeField.value))
|
||||
escrow_cancel_date = addSeconds(parseInt(escrowCancelTimeField.value))
|
||||
let net = getNet()
|
||||
const client = new xrpl.Client(net)
|
||||
await client.connect()
|
||||
let results = `===Connected to ${net}.===\n\n===Creating time-based escrow.===\n`
|
||||
resultField.value = results
|
||||
try {
|
||||
const wallet = xrpl.Wallet.fromSeed(accountSeedField.value)
|
||||
const sendAmount = amountField.value
|
||||
const escrowTx = await client.autofill({
|
||||
"TransactionType": "EscrowCreate",
|
||||
"Account": wallet.address,
|
||||
"Amount": xrpl.xrpToDrops(sendAmount),
|
||||
"Destination": destinationField.value,
|
||||
"FinishAfter": escrow_finish_date,
|
||||
"CancelAfter": escrow_cancel_date
|
||||
})
|
||||
const signed = wallet.sign(escrowTx)
|
||||
const tx = await client.submitAndWait(signed.tx_blob)
|
||||
results += "\n===Success! === *** Save this sequence number: " + tx.result.tx_json.Sequence
|
||||
xrpBalanceField.value = (await client.getXrpBalance(wallet.address))
|
||||
resultField.value = results
|
||||
}
|
||||
catch (error) {
|
||||
results += "\n===Error: " + error.message
|
||||
resultField.value = results
|
||||
}
|
||||
finally {
|
||||
client.disconnect()
|
||||
}
|
||||
} // End of createTimeEscrow()
|
||||
|
||||
// *******************************************************
|
||||
// ***************** Finish Time- Based Escrow ***********
|
||||
// *******************************************************
|
||||
|
||||
async function finishTimeBasedEscrow() {
|
||||
let net = getNet()
|
||||
const client = new xrpl.Client(net)
|
||||
await client.connect()
|
||||
let results = `===Connected to ${net}. Finishing escrow.===\n`
|
||||
resultField.value = results
|
||||
const wallet = xrpl.Wallet.fromSeed(accountSeedField.value)
|
||||
try {
|
||||
const prepared = await client.autofill({
|
||||
"TransactionType": "EscrowFinish",
|
||||
"Account": accountAddressField.value,
|
||||
"Owner": escrowOwnerField.value,
|
||||
"OfferSequence": parseInt(escrowSequenceNumberField.value)
|
||||
})
|
||||
const signed = wallet.sign(prepared)
|
||||
const tx = await client.submitAndWait(signed.tx_blob)
|
||||
results += "\n===Balance changes===" +
|
||||
JSON.stringify(xrpl.getBalanceChanges(tx.result.meta), null, 2)
|
||||
resultField.value = results
|
||||
xrpBalanceField.value = (await client.getXrpBalance(wallet.address))
|
||||
}
|
||||
catch (error) {
|
||||
results += "\n===Error: " + error.message + "==="
|
||||
resultField.value = results
|
||||
}
|
||||
finally {
|
||||
client.disconnect()
|
||||
}
|
||||
} // End of finishTimeBasedEscrow()
|
||||
|
||||
// *******************************************************
|
||||
// ******************* Get Escrows ***********************
|
||||
// *******************************************************
|
||||
|
||||
async function getEscrows() {
|
||||
let net = getNet()
|
||||
const client = new xrpl.Client(net)
|
||||
await client.connect()
|
||||
let results = `\n===Connected to ${net}.\nGetting account escrows.===\n`
|
||||
resultField.value = results
|
||||
try {
|
||||
const escrow_objects = await client.request({
|
||||
"id": 5,
|
||||
"command": "account_objects",
|
||||
"account": accountAddressField.value,
|
||||
"ledger_index": "validated",
|
||||
"type": "escrow"
|
||||
})
|
||||
results += JSON.stringify(escrow_objects.result, null, 2)
|
||||
resultField.value = results
|
||||
}
|
||||
catch (error) {
|
||||
results += "\nError: " + error.message
|
||||
resultField.value = results
|
||||
}
|
||||
finally {
|
||||
client.disconnect()
|
||||
}
|
||||
}
|
||||
|
||||
// *******************************************************
|
||||
// ************** Get Transaction Info *******************
|
||||
// *******************************************************
|
||||
|
||||
async function getTransaction() {
|
||||
let net = getNet()
|
||||
const client = new xrpl.Client(net)
|
||||
await client.connect()
|
||||
let results = `\n===Connected to ${net}.===\n===Getting transaction information.===\n`
|
||||
resultField.value = results
|
||||
try {
|
||||
const tx_info = await client.request({
|
||||
"id": 1,
|
||||
"command": "tx",
|
||||
"transaction": transactionField.value,
|
||||
})
|
||||
results += JSON.stringify(tx_info.result, null, 2)
|
||||
resultField.value = results
|
||||
}
|
||||
catch (error) {
|
||||
results += "\nError: " + error.message
|
||||
resultField.value = results
|
||||
}
|
||||
finally {
|
||||
client.disconnect()
|
||||
}
|
||||
} // End of getTransaction()
|
||||
|
||||
// *******************************************************
|
||||
// ****************** Cancel Escrow **********************
|
||||
// *******************************************************
|
||||
|
||||
async function cancelEscrow() {
|
||||
let net = getNet()
|
||||
const client = new xrpl.Client(net)
|
||||
await client.connect()
|
||||
let results = `\n===Connected to ${net}. Cancelling escrow.===`
|
||||
resultField.value = results
|
||||
try {
|
||||
const prepared = await client.autofill({
|
||||
"TransactionType": "EscrowCancel",
|
||||
"Account": accountAddressField.value,
|
||||
"Owner": escrowOwnerField.value,
|
||||
"OfferSequence": parseInt(escrowSequenceNumberField.value)
|
||||
})
|
||||
const wallet = xrpl.Wallet.fromSeed(accountSeedField.value)
|
||||
const signed = wallet.sign(prepared)
|
||||
const tx = await client.submitAndWait(signed.tx_blob)
|
||||
results += "\n===Balance changes: " +
|
||||
JSON.stringify(xrpl.getBalanceChanges(tx.result.meta), null, 2)
|
||||
resultField.value = results
|
||||
}
|
||||
catch (error) {
|
||||
results += "\n===Error: " + error.message
|
||||
resultField.value = results
|
||||
}
|
||||
finally {
|
||||
client.disconnect()
|
||||
}
|
||||
}
|
||||
64
_code-samples/modular-tutorials/credential-manager.js
Normal file
64
_code-samples/modular-tutorials/credential-manager.js
Normal file
@@ -0,0 +1,64 @@
|
||||
// Create credential function
|
||||
async function createCredential() {
|
||||
|
||||
let net = getNet()
|
||||
const client = new xrpl.Client(net)
|
||||
results = `\n\n===Creating Credential===\n\nConnecting to ${getNet()} ...`
|
||||
updateResults()
|
||||
await client.connect()
|
||||
results = `\n\nConnected.`
|
||||
updateResults()
|
||||
|
||||
// Gather transaction info
|
||||
try {
|
||||
|
||||
// Get account wallet from seed
|
||||
const wallet = xrpl.Wallet.fromSeed(accountSeedField.value)
|
||||
|
||||
// Get subject
|
||||
const subject = subjectField.value
|
||||
|
||||
// Get credential type - convert string to hex if needed
|
||||
let credentialType = credentialTypeField.value;
|
||||
if (!/^[0-9A-F]+$/i.test(credentialType)) {
|
||||
let hex = '';
|
||||
for (let i = 0; i < credentialType.length; i++) {
|
||||
const charCode = credentialType.charCodeAt(i);
|
||||
const hexCharCode = charCode.toString(16).padStart(2, '0');
|
||||
hex += hexCharCode;
|
||||
}
|
||||
credentialType = hex.toUpperCase();
|
||||
}
|
||||
|
||||
// Prepare transaction
|
||||
const transaction = {
|
||||
"TransactionType": "CredentialCreate",
|
||||
"Account": wallet.address,
|
||||
"Subject": subject,
|
||||
"CredentialType": credentialType
|
||||
}
|
||||
|
||||
results = `\n\n===Preparing and Sending Transaction===\n\n${JSON.stringify(transaction, null, 2)}`
|
||||
updateResults()
|
||||
|
||||
// Submit transaction
|
||||
const tx = await client.submitAndWait(transaction, {autofill: true, wallet: wallet})
|
||||
|
||||
if (tx.result.meta.TransactionResult == "tesSUCCESS") {
|
||||
// Parse for credential info
|
||||
const parsedResponse = JSON.parse(JSON.stringify(tx.result.meta.AffectedNodes, null, 2))
|
||||
const credentialInfo = parsedResponse.find( node => node.CreatedNode && node.CreatedNode.LedgerEntryType === "Credential" )
|
||||
results = `\n\n===Create Credential Result===\n\n${JSON.stringify(credentialInfo.CreatedNode, null, 2)}`
|
||||
} else {
|
||||
results = `\n\n===Error===\n\n${JSON.stringify(tx.result.meta.TransactionResult, null, 2)}: Check codes at https://xrpl.org/docs/references/protocol/transactions/types/credentialcreate#error-cases`
|
||||
}
|
||||
|
||||
updateResults()
|
||||
|
||||
} catch (error) {
|
||||
results = `\n\n===Error===\n\n${error}`
|
||||
updateResults()
|
||||
}
|
||||
|
||||
client.disconnect()
|
||||
}
|
||||
24
_code-samples/modular-tutorials/five-bells.cjs
Normal file
24
_code-samples/modular-tutorials/five-bells.cjs
Normal file
@@ -0,0 +1,24 @@
|
||||
const cc = require('five-bells-condition');
|
||||
const crypto = require('crypto');
|
||||
|
||||
// 1. Generate a random 32-byte seed
|
||||
const preimageData = crypto.randomBytes(32);
|
||||
|
||||
// 2. Create a PreimageSha256 fulfillment object
|
||||
const fulfillment = new cc.PreimageSha256();
|
||||
|
||||
// 3. Set the preimage
|
||||
fulfillment.setPreimage(preimageData);
|
||||
|
||||
// 4. Generate the condition (binary)
|
||||
const conditionBinary = fulfillment.getConditionBinary();
|
||||
|
||||
// 5. Generate the fulfillment (binary)
|
||||
const fulfillmentBinary = fulfillment.serializeBinary();
|
||||
|
||||
// Convert to hex for easier use
|
||||
const conditionHex = conditionBinary.toString('hex').toUpperCase();
|
||||
const fulfillmentHex = fulfillmentBinary.toString('hex').toUpperCase();
|
||||
|
||||
console.log('Condition (hex):', conditionHex);
|
||||
console.log('Fulfillment (hex):', fulfillmentHex);
|
||||
150
_code-samples/modular-tutorials/modular-tutorials.css
Normal file
150
_code-samples/modular-tutorials/modular-tutorials.css
Normal file
@@ -0,0 +1,150 @@
|
||||
body {
|
||||
font-family: "Inter", sans-serif;
|
||||
padding: 20px;
|
||||
background: #abe2ff;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
td {
|
||||
padding-left: 25px;
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
input,
|
||||
button {
|
||||
padding: 6px;
|
||||
margin-bottom: 8px;
|
||||
border: none
|
||||
}
|
||||
|
||||
input:read-only {
|
||||
background-color:rgb(11, 96, 132);
|
||||
color:white;
|
||||
border: 0;
|
||||
}
|
||||
|
||||
button {
|
||||
font-weight: bold;
|
||||
font-family: "Work Sans", sans-serif;
|
||||
background-color: #006aff;
|
||||
-webkit-text-fill-color: white;
|
||||
}
|
||||
|
||||
button:hover {
|
||||
background-color: #0555c5;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
td {
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
/* The switch - the box around the slider */
|
||||
.switch {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
width: 30px;
|
||||
height: 16px;
|
||||
}
|
||||
|
||||
/* Hide default HTML checkbox */
|
||||
.switch input {
|
||||
opacity: 0;
|
||||
width: 0;
|
||||
height: 0;
|
||||
}
|
||||
|
||||
/* The slider */
|
||||
.slider {
|
||||
position: absolute;
|
||||
cursor: pointer;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background-color: #ccc;
|
||||
-webkit-transition: .4s;
|
||||
transition: .4s;
|
||||
}
|
||||
|
||||
.slider:before {
|
||||
position: absolute;
|
||||
content: "";
|
||||
height: 13px;
|
||||
width: 13px;
|
||||
left: 4px;
|
||||
bottom: 2px;
|
||||
background-color: white;
|
||||
-webkit-transition: .4s;
|
||||
transition: .4s;
|
||||
}
|
||||
|
||||
input:checked+.slider {
|
||||
background-color: #2196F3;
|
||||
}
|
||||
|
||||
input:focus+.slider {
|
||||
box-shadow: 0 0 1px #2196F3;
|
||||
}
|
||||
|
||||
input:checked+.slider:before {
|
||||
-webkit-transform: translateX(13px);
|
||||
-ms-transform: translateX(13px);
|
||||
transform: translateX(13px);
|
||||
}
|
||||
|
||||
/* Rounded sliders */
|
||||
.slider.round {
|
||||
border-radius: 17px;
|
||||
}
|
||||
|
||||
.slider.round:before {
|
||||
border-radius: 50%;
|
||||
}
|
||||
.tooltip {
|
||||
position: relative;
|
||||
border-bottom: 1px dotted black;
|
||||
}
|
||||
|
||||
.tooltip:before {
|
||||
content: attr(tooltip-data);
|
||||
position: absolute;
|
||||
width: 250px;
|
||||
background-color: #006aff;
|
||||
color: #fff;
|
||||
text-align: center;
|
||||
padding: 15px;
|
||||
line-height: 1.1;
|
||||
border-radius: 5px;
|
||||
z-index: 1;
|
||||
opacity: 0;
|
||||
transition: opacity .5s;
|
||||
bottom: 125%;
|
||||
left: 50%;
|
||||
margin-left: -60px;
|
||||
font-size: 0.70em;
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
.tooltip:after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
bottom: 75%;
|
||||
left: 50%;
|
||||
margin-left: -5px;
|
||||
border-width: 5px;
|
||||
border-style: solid;
|
||||
opacity: 0;
|
||||
transition: opacity .5s;
|
||||
border-color: #000 transparent transparent transparent;
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
.tooltip:hover:before,
|
||||
.tooltip:hover:after {
|
||||
opacity: 1;
|
||||
visibility: visible;
|
||||
}
|
||||
BIN
_code-samples/modular-tutorials/payment-modular-tutorials.zip
Normal file
BIN
_code-samples/modular-tutorials/payment-modular-tutorials.zip
Normal file
Binary file not shown.
127
_code-samples/modular-tutorials/permissioned-domain-manager.js
Normal file
127
_code-samples/modular-tutorials/permissioned-domain-manager.js
Normal file
@@ -0,0 +1,127 @@
|
||||
/// Create permissioned domain
|
||||
async function createDomain() {
|
||||
|
||||
let net = getNet()
|
||||
const client = new xrpl.Client(net)
|
||||
results = `\n\n===Creating Permissioned Domain===\n\nConnecting to ${getNet()} ...`
|
||||
updateResults()
|
||||
await client.connect()
|
||||
results = `\n\nConnected.`
|
||||
updateResults()
|
||||
|
||||
// Gather transaction info
|
||||
try {
|
||||
|
||||
// Get account wallet from seed
|
||||
const wallet = xrpl.Wallet.fromSeed(accountSeedField.value)
|
||||
|
||||
// Get Domain ID
|
||||
const domainID = domainIDField.value
|
||||
|
||||
// Get credential type - convert string to hex if needed
|
||||
let credentialType = credentialTypeField.value;
|
||||
if (!/^[0-9A-F]+$/i.test(credentialType)) {
|
||||
let hex = '';
|
||||
for (let i = 0; i < credentialType.length; i++) {
|
||||
const charCode = credentialType.charCodeAt(i);
|
||||
const hexCharCode = charCode.toString(16).padStart(2, '0');
|
||||
hex += hexCharCode;
|
||||
}
|
||||
credentialType = hex.toUpperCase();
|
||||
}
|
||||
|
||||
// Prepare transaction
|
||||
const transaction = {
|
||||
"TransactionType": "PermissionedDomainSet",
|
||||
"Account": wallet.address,
|
||||
"AcceptedCredentials": [
|
||||
{
|
||||
"Credential": {
|
||||
"Issuer": wallet.address,
|
||||
"CredentialType": credentialType
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
if (domainID) {
|
||||
transaction.DomainID = domainID
|
||||
}
|
||||
|
||||
results = `\n\n===Preparing and Sending Transaction===\n\n${JSON.stringify(transaction, null, 2)}`
|
||||
updateResults()
|
||||
|
||||
// Submit transaction
|
||||
const tx = await client.submitAndWait(transaction, {autofill: true, wallet: wallet})
|
||||
|
||||
if (tx.result.meta.TransactionResult == "tesSUCCESS") {
|
||||
// Parse for domain info
|
||||
if (domainID) {
|
||||
results = `\n\n===Create Permissioned Domain Result===\n\n${JSON.stringify(tx.result.tx_json, null, 2)}`
|
||||
} else {
|
||||
const parsedResponse = JSON.parse(JSON.stringify(tx.result.meta.AffectedNodes, null, 2))
|
||||
const domainInfo = parsedResponse.find( node => node.CreatedNode && node.CreatedNode.LedgerEntryType === "PermissionedDomain" )
|
||||
results = `\n\n===Create Permissioned Domain Result===\n\n${JSON.stringify(domainInfo.CreatedNode, null, 2)}`
|
||||
}
|
||||
} else {
|
||||
results = `\n\n===Error===\n\n${JSON.stringify(tx.result.meta.TransactionResult, null, 2)}: Check codes at https://xrpl.org/docs/references/protocol/transactions/types/permissioneddomainset#error-cases`
|
||||
}
|
||||
updateResults()
|
||||
|
||||
} catch (error) {
|
||||
results = `\n\n===Error===\n\n${error}`
|
||||
updateResults()
|
||||
}
|
||||
|
||||
client.disconnect()
|
||||
}
|
||||
// End create permissioned domain
|
||||
|
||||
|
||||
// Delete permissioned domain
|
||||
async function deleteDomain() {
|
||||
|
||||
let net = getNet()
|
||||
const client = new xrpl.Client(net)
|
||||
results = `\n\n===Delete Permissioned Domain===\n\nConnecting to ${getNet()} ...`
|
||||
updateResults()
|
||||
await client.connect()
|
||||
results = `\n\nConnected.`
|
||||
updateResults()
|
||||
|
||||
// Get delete domain transaction info
|
||||
try {
|
||||
|
||||
// Get account wallet from seed
|
||||
const wallet = xrpl.Wallet.fromSeed(accountSeedField.value)
|
||||
|
||||
// Get Domain ID
|
||||
const domainID = domainIDField.value
|
||||
|
||||
// Prepare transaction
|
||||
const transaction = {
|
||||
"TransactionType": "PermissionedDomainDelete",
|
||||
"Account": wallet.address,
|
||||
"DomainID": domainID
|
||||
}
|
||||
|
||||
results = `\n\n===Preparing and Sending Transaction===\n\n${JSON.stringify(transaction, null, 2)}`
|
||||
updateResults()
|
||||
|
||||
// Submit delete domain transaction
|
||||
const tx = await client.submitAndWait(transaction, {autofill: true, wallet: wallet})
|
||||
|
||||
if (tx.result.meta.TransactionResult == "tesSUCCESS") {
|
||||
results = `\n\n===Delete Permissioned Domain Result===\n\nSuccessfully deleted the permissioned domain.`
|
||||
} else {
|
||||
results = `\n\n===Error===\n\n${JSON.stringify(tx.result.meta.TransactionResult, null, 2)}: Check codes at https://xrpl.org/docs/references/protocol/transactions/types/permissioneddomaindelete#error-cases`
|
||||
}
|
||||
updateResults()
|
||||
|
||||
} catch (error) {
|
||||
results = `\n\n===Error===\n\n${error}`
|
||||
updateResults()
|
||||
}
|
||||
|
||||
client.disconnect()
|
||||
}
|
||||
247
_code-samples/modular-tutorials/send-checks.html
Normal file
247
_code-samples/modular-tutorials/send-checks.html
Normal file
@@ -0,0 +1,247 @@
|
||||
<html>
|
||||
<head>
|
||||
<title>Send Checks</title>
|
||||
<link href='https://fonts.googleapis.com/css?family=Work Sans' rel='stylesheet'>
|
||||
<link href="modular-tutorials.css" rel="stylesheet">
|
||||
<script src='https://unpkg.com/xrpl@4.1.0/build/xrpl-latest.js'></script>
|
||||
<script src="account-support.js"></script>
|
||||
<script src='send-xrp.js'></script>
|
||||
<script src='send-currency.js'></script>
|
||||
<script src='send-checks.js'></script>
|
||||
<script>
|
||||
if (typeof module !== "undefined") {
|
||||
const xrpl = require('xrpl')
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
|
||||
<!-- ************************************************************** -->
|
||||
<!-- ********************** The Form ****************************** -->
|
||||
<!-- ************************************************************** -->
|
||||
|
||||
<body>
|
||||
<h1>Send Checks</h1>
|
||||
<form id="theForm">
|
||||
<span class="tooltip" tooltip-data="Choose the XRPL host server for your account.">
|
||||
Choose your ledger instance:
|
||||
</span>
|
||||
|
||||
<input type="radio" id="dn" name="server" value="wss://s.devnet.rippletest.net:51233" checked>
|
||||
<label for="dn">Devnet</label>
|
||||
|
||||
<input type="radio" id="tn" name="server" value="wss://s.altnet.rippletest.net:51233">
|
||||
<label for="tn">Testnet</label>
|
||||
<br /><br />
|
||||
<table>
|
||||
<tr>
|
||||
<td>
|
||||
<button type="button" onClick="getNewAccount1()">Get New Account 1</button>
|
||||
</td>
|
||||
<td>
|
||||
<button type="button" onClick="getAccountFromSeed1()">Get Account 1 From Seed</button>
|
||||
</td>
|
||||
<td>
|
||||
<button type="button" onClick="getNewAccount2()">Get New Account 2</button>
|
||||
</td>
|
||||
<td>
|
||||
<button type="button" onClick="getAccountFromSeed2()">Get Account 2 From Seed</button>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<span class="tooltip" tooltip-data="Arbitrary human-readable name for the account."><label for="account1name">Account 1 Name</label>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="account1name" size="40"></input>
|
||||
</td>
|
||||
<td>
|
||||
<span class="tooltip" tooltip-data="Arbitrary human-readable name for the account.">
|
||||
<label for="account2name">Account 2 Name</label>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="account2name" size="40"></input>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<span class="tooltip" tooltip-data="Identifying address for the account.">
|
||||
<label for="account1address">Account 1 Address</label>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="account1address" size="40"></input>
|
||||
</td>
|
||||
<td>
|
||||
<span class="tooltip" tooltip-data="Identifying address for the account.">
|
||||
<label for="account2address">Account 2 Address</label>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="account2address" size="40"></input>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<span class="tooltip" tooltip-data="Seed for deriving public and private keys for the account.">
|
||||
<label for="account1seed">Account 1 Seed</label>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="account1seed" size="40"></input>
|
||||
</td>
|
||||
<td>
|
||||
<span class="tooltip" tooltip-data="Seed for deriving public and private keys for the account.">
|
||||
<label for="account2seed">Account 2 Seed</label>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="account2seed" size="40"></input>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<hr />
|
||||
<table>
|
||||
<tr valign="top">
|
||||
<td align="right">
|
||||
<span class="tooltip" tooltip-data="Name of the currently selected account.">
|
||||
<label for="accountNameField">Account Name</label>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="accountNameField" size="40" readonly></input>
|
||||
<input type="radio" id="account1" name="accounts" value="account1">
|
||||
<label for="account1">Account 1</label>
|
||||
</td>
|
||||
</tr>
|
||||
<tr valign="top">
|
||||
<td align="right">
|
||||
<span class="tooltip" tooltip-data="Address of the currently selected account.">
|
||||
<label for="accountAddressField">Account Address</label>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="accountAddressField" size="40" readonly></input>
|
||||
<input type="radio" id="account2" name="accounts" value="account2">
|
||||
<label for="account2">Account 2</label>
|
||||
</td>
|
||||
</tr>
|
||||
<tr valign="top">
|
||||
<td align="right">
|
||||
<span class="tooltip" tooltip-data="Seed of the currently selected account.">
|
||||
<label for="accountSeedField">Account Seed</label>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="accountSeedField" size="40" readonly></input>
|
||||
<br>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="right">
|
||||
<span class="tooltip" tooltip-data="XRP balance for the currently selected account.">
|
||||
<label for="xrpBalanceField">XRP Balance</label>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="xrpBalanceField" size="40" readonly></input>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="right">
|
||||
<span class="tooltip" tooltip-data="Currency code for the check.">
|
||||
<lable for="currencyField">Currency Code</lable>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="currencyField" size="40"></input>
|
||||
<br>
|
||||
</td>
|
||||
<td>
|
||||
<button type="button" onClick="sendCheck()">Send Check</button>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="right">
|
||||
<span class="tooltip" tooltip-data="Issuing account for the currency.">
|
||||
<lable for="issuerField">Issuer</lable>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="issuerField" size="40"></input>
|
||||
<br>
|
||||
</td>
|
||||
<td>
|
||||
<button type="button" onClick="cashCheck()">Cash Check</button>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="right">
|
||||
<span class="tooltip" tooltip-data="Amount of XRP to send.">
|
||||
<label for="amountField">Amount</label>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="amountField" size="40"></input>
|
||||
<br>
|
||||
</td>
|
||||
<td align="left" valign="top">
|
||||
<button type="button" onClick="getChecks()">Get Checks</button>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="right">
|
||||
<span class="tooltip" tooltip-data="Destination account address where XRP is sent.">
|
||||
<lable for="destinationField">Destination</lable>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="destinationField" size="40"></input>
|
||||
<br>
|
||||
</td>
|
||||
<td align="left" valign="top">
|
||||
<button type="button" onClick="cancelCheck()">Cancel Check</button>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="right">
|
||||
<span class="tooltip" tooltip-data="Check ID.">
|
||||
<lable for="checkIdField">Check ID</lable>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="checkIdField" size="40"></input>
|
||||
<br>
|
||||
</td>
|
||||
<td align="left" valign="top">
|
||||
<button type="button" onClick="getTokenBalance()">Get Token Balance</button>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="2">
|
||||
<p align="right">
|
||||
<textarea id="resultField" cols="80" rows="20"></textarea>
|
||||
</p>
|
||||
</td>
|
||||
<td align="left" valign="top">
|
||||
<button type="button" onClick="gatherAccountInfo()">Gather Account Info</button><br/>
|
||||
<button type="button" onClick="distributeAccountInfo()">Distribute Account Info</button>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</form>
|
||||
</body>
|
||||
<script>
|
||||
const radioButtons = document.querySelectorAll('input[type="radio"]');
|
||||
radioButtons.forEach(radio => {
|
||||
radio.addEventListener('change', function() {
|
||||
if (this.value === 'account1') {
|
||||
populate1()
|
||||
} else if (this.value === 'account2') {
|
||||
populate2()
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
</html>
|
||||
152
_code-samples/modular-tutorials/send-checks.js
Normal file
152
_code-samples/modular-tutorials/send-checks.js
Normal file
@@ -0,0 +1,152 @@
|
||||
// *******************************************************
|
||||
// ***************** Send Check **************************
|
||||
// *******************************************************
|
||||
async function sendCheck() {
|
||||
let net = getNet()
|
||||
const client = new xrpl.Client(net)
|
||||
await client.connect()
|
||||
results = `\n===Connected to ${net}.===\n===Sending check.===\n`
|
||||
resultField.value = results
|
||||
try {
|
||||
const wallet = xrpl.Wallet.fromSeed(accountSeedField.value)
|
||||
let check_amount = amountField.value
|
||||
if (currencyField.value != "XRP") {
|
||||
check_amount = {
|
||||
"currency": currencyField.value,
|
||||
"value": amountField.value,
|
||||
"issuer": wallet.address
|
||||
}
|
||||
}
|
||||
const send_check_tx = {
|
||||
"TransactionType": "CheckCreate",
|
||||
"Account": wallet.address,
|
||||
"SendMax": check_amount,
|
||||
"Destination": destinationField.value
|
||||
}
|
||||
const check_prepared = await client.autofill(send_check_tx)
|
||||
const check_signed = wallet.sign(check_prepared)
|
||||
results = '\n===Sending ' + amountField.value + ' ' + currencyField.
|
||||
value + ' to ' + destinationField.value + '.===\n'
|
||||
resultField.value += results
|
||||
const check_result = await client.submitAndWait(check_signed.tx_blob)
|
||||
if (check_result.result.meta.TransactionResult == "tesSUCCESS") {
|
||||
results += '===Transaction succeeded===\n\n'
|
||||
resultField.value += JSON.stringify(check_result.result, null, 2)
|
||||
xrpBalanceField.value = (await client.getXrpBalance(wallet.address))
|
||||
}
|
||||
}
|
||||
catch (error) {
|
||||
results = `Error sending transaction: ${error}`
|
||||
resultField.value += results
|
||||
}
|
||||
finally {
|
||||
client.disconnect()
|
||||
}
|
||||
} // end of sendCheck()
|
||||
|
||||
// *******************************************************
|
||||
// ********************* Get Checks **********************
|
||||
// *******************************************************
|
||||
|
||||
async function getChecks() {
|
||||
let net = getNet()
|
||||
const client = new xrpl.Client(net)
|
||||
await client.connect()
|
||||
let results = `\n===Connected to ${net}.===\n===Getting account checks.===\n\n`
|
||||
resultField.value = results
|
||||
try {
|
||||
const check_objects = await client.request({
|
||||
"id": 5,
|
||||
"command": "account_objects",
|
||||
"account": accountAddressField.value,
|
||||
"ledger_index": "validated",
|
||||
"type": "check"
|
||||
})
|
||||
resultField.value += JSON.stringify(check_objects.result, null, 2)
|
||||
} catch (error) {
|
||||
results = `Error getting checks: ${error}`
|
||||
resultField.value += results
|
||||
}
|
||||
finally {
|
||||
client.disconnect()
|
||||
}
|
||||
} // End of getChecks()
|
||||
|
||||
// *******************************************************
|
||||
// ******************** Cash Check **********************
|
||||
// *******************************************************
|
||||
|
||||
async function cashCheck() {
|
||||
let net = getNet()
|
||||
const client = new xrpl.Client(net)
|
||||
await client.connect()
|
||||
results = `\n===Connected to ${net}.===\n===Cashing check.===\n`
|
||||
resultField.value = results
|
||||
try {
|
||||
const wallet = xrpl.Wallet.fromSeed(accountSeedField.value)
|
||||
let check_amount = amountField.value
|
||||
if (currencyField.value != "XRP") {
|
||||
check_amount = {
|
||||
"value": amountField.value,
|
||||
"currency": currencyField.value,
|
||||
"issuer": issuerField.value
|
||||
}
|
||||
}
|
||||
const cash_check_tx = {
|
||||
"TransactionType": "CheckCash",
|
||||
"Account": wallet.address,
|
||||
"Amount": check_amount,
|
||||
"CheckID": checkIdField.value
|
||||
}
|
||||
const cash_prepared = await client.autofill(cash_check_tx)
|
||||
const cash_signed = wallet.sign(cash_prepared)
|
||||
results = ' Receiving ' + amountField.value + ' ' + currencyField.value + '.\n'
|
||||
resultField.value += results
|
||||
const check_result = await client.submitAndWait(cash_signed.tx_blob)
|
||||
if (check_result.result.meta.TransactionResult == "tesSUCCESS") {
|
||||
results = '===Transaction succeeded===\n' + JSON.stringify(check_result.result, null, 2)
|
||||
resultField.value += results
|
||||
}
|
||||
xrpBalanceField.value = (await client.getXrpBalance(wallet.address))
|
||||
} catch (error) {
|
||||
results = `Error sending transaction: ${error}`
|
||||
resultField.value += results
|
||||
}
|
||||
finally {
|
||||
client.disconnect()
|
||||
}
|
||||
} // end of cashCheck()
|
||||
|
||||
// *******************************************************
|
||||
// **************** Cancel Check *************************
|
||||
// *******************************************************
|
||||
|
||||
async function cancelCheck() {
|
||||
let net = getNet()
|
||||
const client = new xrpl.Client(net)
|
||||
await client.connect()
|
||||
results = `\n===Connected to ${net}.===\n===Cancelling check.===\n`
|
||||
resultField.value = results
|
||||
try {
|
||||
const wallet = xrpl.Wallet.fromSeed(accountSeedField.value)
|
||||
const cancel_check_tx = {
|
||||
"TransactionType": "CheckCancel",
|
||||
"Account": wallet.address,
|
||||
"CheckID": checkIdField.value
|
||||
}
|
||||
const cancel_prepared = await client.autofill(cancel_check_tx)
|
||||
const cancel_signed = wallet.sign(cancel_prepared)
|
||||
const check_result = await client.submitAndWait(cancel_signed.tx_blob)
|
||||
if (check_result.result.meta.TransactionResult == "tesSUCCESS") {
|
||||
results += `===Transaction succeeded===\n${check_result.result.meta.TransactionResult}`
|
||||
resultField.value = results
|
||||
}
|
||||
xrpBalanceField.value = (await client.getXrpBalance(wallet.address))
|
||||
} catch (error) {
|
||||
results = `Error sending transaction: ${error}`
|
||||
resultField.value += results
|
||||
}
|
||||
finally {
|
||||
client.disconnect()
|
||||
}
|
||||
} // end of cancelCheck()
|
||||
229
_code-samples/modular-tutorials/send-currency.html
Normal file
229
_code-samples/modular-tutorials/send-currency.html
Normal file
@@ -0,0 +1,229 @@
|
||||
<html>
|
||||
<head>
|
||||
<title>Send Currency</title>
|
||||
<link href='https://fonts.googleapis.com/css?family=Work Sans' rel='stylesheet'>
|
||||
<link href="modular-tutorials.css" rel="stylesheet">
|
||||
<script src='https://unpkg.com/xrpl@4.1.0/build/xrpl-latest.js'></script>
|
||||
<script src="account-support.js"></script>
|
||||
<script src='send-xrp.js'></script>
|
||||
<script src='send-currency.js'></script>
|
||||
<script>
|
||||
if (typeof module !== "undefined") {
|
||||
const xrpl = require('xrpl')
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
|
||||
<!-- ************************************************************** -->
|
||||
<!-- ********************** The Form ****************************** -->
|
||||
<!-- ************************************************************** -->
|
||||
|
||||
<body>
|
||||
<h1>Send Currency</h1>
|
||||
<form id="theForm">
|
||||
<span class="tooltip" tooltip-data="Choose the XRPL host server for your account.">
|
||||
Choose your ledger instance:
|
||||
</span>
|
||||
|
||||
<input type="radio" id="dn" name="server" value="wss://s.devnet.rippletest.net:51233" checked>
|
||||
<label for="dn">Devnet</label>
|
||||
|
||||
<input type="radio" id="tn" name="server" value="wss://s.altnet.rippletest.net:51233">
|
||||
<label for="tn">Testnet</label>
|
||||
<br /><br />
|
||||
<table>
|
||||
<tr>
|
||||
<td>
|
||||
<button type="button" onClick="getNewAccount1()">Get New Account 1</button>
|
||||
</td>
|
||||
<td>
|
||||
<button type="button" onClick="getAccountFromSeed1()">Get Account 1 From Seed</button>
|
||||
</td>
|
||||
<td>
|
||||
<button type="button" onClick="getNewAccount2()">Get New Account 2</button>
|
||||
</td>
|
||||
<td>
|
||||
<button type="button" onClick="getAccountFromSeed2()">Get Account 2 From Seed</button>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<span class="tooltip" tooltip-data="Arbitrary human-readable name for the account."><label for="account1name">Account 1 Name</label>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="account1name" size="40"></input>
|
||||
</td>
|
||||
<td>
|
||||
<span class="tooltip" tooltip-data="Arbitrary human-readable name for the account.">
|
||||
<label for="account2name">Account 2 Name</label>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="account2name" size="40"></input>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<span class="tooltip" tooltip-data="Identifying address for the account.">
|
||||
<label for="account1address">Account 1 Address</label>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="account1address" size="40"></input>
|
||||
</td>
|
||||
<td>
|
||||
<span class="tooltip" tooltip-data="Identifying address for the account.">
|
||||
<label for="account2address">Account 2 Address</label>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="account2address" size="40"></input>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<span class="tooltip" tooltip-data="Seed for deriving public and private keys for the account.">
|
||||
<label for="account1seed">Account 1 Seed</label>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="account1seed" size="40"></input>
|
||||
</td>
|
||||
<td>
|
||||
<span class="tooltip" tooltip-data="Seed for deriving public and private keys for the account.">
|
||||
<label for="account2seed">Account 2 Seed</label>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="account2seed" size="40"></input>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<hr />
|
||||
<table>
|
||||
<tr valign="top">
|
||||
<td align="right">
|
||||
<span class="tooltip" tooltip-data="Name of the currently selected account.">
|
||||
<label for="accountNameField">Account Name</label>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="accountNameField" size="40" readonly></input>
|
||||
<input type="radio" id="account1" name="accounts" value="account1">
|
||||
<label for="account1">Account 1</label>
|
||||
</td>
|
||||
</tr>
|
||||
<tr valign="top">
|
||||
<td align="right">
|
||||
<span class="tooltip" tooltip-data="Address of the currently selected account.">
|
||||
<label for="accountAddressField">Account Address</label>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="accountAddressField" size="40" readonly></input>
|
||||
<input type="radio" id="account2" name="accounts" value="account2">
|
||||
<label for="account2">Account 2</label>
|
||||
</td>
|
||||
</tr>
|
||||
<tr valign="top">
|
||||
<td align="right">
|
||||
<span class="tooltip" tooltip-data="Seed of the currently selected account.">
|
||||
<label for="accountSeedField">Account Seed</label>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="accountSeedField" size="40" readonly></input>
|
||||
<br>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="right">
|
||||
<span class="tooltip" tooltip-data="XRP balance for the currently selected account.">
|
||||
<label for="xrpBalanceField">XRP Balance</label>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="xrpBalanceField" size="40" readonly></input>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="right">
|
||||
<span class="tooltip" tooltip-data="Currency code for the trust line.">
|
||||
<lable for="currencyField">Currency Code</lable>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="currencyField" size="40"></input>
|
||||
<br>
|
||||
</td>
|
||||
<td>
|
||||
<button type="button" onClick="createTrustLine()">Create Trust Line</button>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="right">
|
||||
<span class="tooltip" tooltip-data="Issuing account for the currency.">
|
||||
<lable for="issuerField">Issuer</lable>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="issuerField" size="40"></input>
|
||||
<br>
|
||||
</td>
|
||||
<td>
|
||||
<button type="button" onClick="sendCurrency()">Send Currency</button>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="right">
|
||||
<span class="tooltip" tooltip-data="Amount of XRP to send.">
|
||||
<label for="amountField">Amount</label>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="amountField" size="40"></input>
|
||||
<br>
|
||||
</td>
|
||||
<td align="left" valign="top">
|
||||
<button type="button" onClick="getTokenBalance()">Get Token Balance</button>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="right">
|
||||
<span class="tooltip" tooltip-data="Destination account address where XRP is sent.">
|
||||
<lable for="destinationField">Destination</lable>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="destinationField" size="40"></input>
|
||||
<br>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="2">
|
||||
<p align="right">
|
||||
<textarea id="resultField" cols="80" rows="20"></textarea>
|
||||
</p>
|
||||
</td>
|
||||
<td align="left" valign="top">
|
||||
<button type="button" onClick="gatherAccountInfo()">Gather Account Info</button><br/>
|
||||
<button type="button" onClick="distributeAccountInfo()">Distribute Account Info</button>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</form>
|
||||
</body>
|
||||
<script>
|
||||
const radioButtons = document.querySelectorAll('input[type="radio"]');
|
||||
radioButtons.forEach(radio => {
|
||||
radio.addEventListener('change', function() {
|
||||
if (this.value === 'account1') {
|
||||
populate1()
|
||||
} else if (this.value === 'account2') {
|
||||
populate2()
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
</html>
|
||||
96
_code-samples/modular-tutorials/send-currency.js
Normal file
96
_code-samples/modular-tutorials/send-currency.js
Normal file
@@ -0,0 +1,96 @@
|
||||
// *******************************************************
|
||||
// ***************** Create TrustLine ********************
|
||||
// *******************************************************
|
||||
|
||||
async function createTrustLine() {
|
||||
const net = getNet()
|
||||
const client = new xrpl.Client(net)
|
||||
await client.connect()
|
||||
let results = "\nConnected. Creating trust line.\n"
|
||||
resultField.value = results
|
||||
try {
|
||||
const wallet = xrpl.Wallet.fromSeed(accountSeedField.value)
|
||||
const trustSet_tx = {
|
||||
"TransactionType": "TrustSet",
|
||||
"Account": accountAddressField.value,
|
||||
"LimitAmount": {
|
||||
"currency": currencyField.value,
|
||||
"issuer": issuerField.value,
|
||||
"value": amountField.value
|
||||
}
|
||||
}
|
||||
const ts_prepared = await client.autofill(trustSet_tx)
|
||||
const ts_signed = wallet.sign(ts_prepared)
|
||||
resultField.value = results
|
||||
const ts_result = await client.submitAndWait(ts_signed.tx_blob)
|
||||
if (ts_result.result.meta.TransactionResult == "tesSUCCESS") {
|
||||
results += '\n===Trustline established between account\n' +
|
||||
accountAddressField.value + "\nand account\n" + issuerField.value + '.'
|
||||
resultField.value = results
|
||||
} else {
|
||||
results += `\n===Transaction failed: ${ts_result.result.meta.TransactionResult}`
|
||||
resultField.value = results
|
||||
}
|
||||
}
|
||||
catch (error) {
|
||||
console.error('Error creating trust line:', error);
|
||||
results += `\n===Error: ${error.message}\n`
|
||||
resultField.value = results
|
||||
throw error; // Re-throw the error to be handled by the caller
|
||||
}
|
||||
finally {
|
||||
// Disconnect from the client
|
||||
await client.disconnect();
|
||||
}
|
||||
} //End of createTrustline()
|
||||
|
||||
// *******************************************************
|
||||
// *************** Send Issued Currency ******************
|
||||
// *******************************************************
|
||||
|
||||
async function sendCurrency() {
|
||||
let net = getNet()
|
||||
const client = new xrpl.Client(net)
|
||||
results = 'Connecting to ' + getNet() + '....'
|
||||
resultField.value = results
|
||||
await client.connect()
|
||||
results += '\nConnected.'
|
||||
resultField.value = results
|
||||
try {
|
||||
const wallet = xrpl.Wallet.fromSeed(accountSeedField.value)
|
||||
const send_currency_tx = {
|
||||
"TransactionType": "Payment",
|
||||
"Account": wallet.address,
|
||||
"Amount": {
|
||||
"currency": currencyField.value,
|
||||
"value": amountField.value,
|
||||
"issuer": issuerField.value
|
||||
},
|
||||
"Destination": destinationField.value
|
||||
}
|
||||
const pay_prepared = await client.autofill(send_currency_tx)
|
||||
const pay_signed = wallet.sign(pay_prepared)
|
||||
results += `\n\n===Sending ${amountField.value} ${currencyField.value} to ${destinationField.value} ...`
|
||||
resultField.value = results
|
||||
const pay_result = await client.submitAndWait(pay_signed.tx_blob)
|
||||
if (pay_result.result.meta.TransactionResult == "tesSUCCESS") {
|
||||
results += '\n===Transaction succeeded.'
|
||||
resultField.value = results
|
||||
getTokenBalance()
|
||||
} else {
|
||||
results += `\n===Transaction failed: ${pay_result.result.meta.TransactionResult}\n`
|
||||
resultField.value = results
|
||||
}
|
||||
xrpBalanceField.value = (await client.getXrpBalance(wallet.address))
|
||||
}
|
||||
catch (error) {
|
||||
console.error('Error sending transaction:', error);
|
||||
results += `\nError: ${error.message}\n`
|
||||
resultField.value = results
|
||||
throw error; // Re-throw the error to be handled by the caller
|
||||
}
|
||||
finally {
|
||||
// Disconnect from the client
|
||||
await client.disconnect();
|
||||
}
|
||||
} // end of sendCurrency()
|
||||
218
_code-samples/modular-tutorials/send-mpt.html
Normal file
218
_code-samples/modular-tutorials/send-mpt.html
Normal file
@@ -0,0 +1,218 @@
|
||||
<html>
|
||||
<head>
|
||||
<title>Send MPT</title>
|
||||
<link href='https://fonts.googleapis.com/css?family=Work Sans' rel='stylesheet'>
|
||||
<link href="modular-tutorials.css" rel="stylesheet">
|
||||
<script src='https://unpkg.com/xrpl@4.1.0/build/xrpl-latest.js'></script>
|
||||
<script src="account-support.js"></script>
|
||||
<script src='send-mpt.js'></script>
|
||||
<script>
|
||||
if (typeof module !== "undefined") {
|
||||
const xrpl = require('xrpl')
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
|
||||
<!-- ************************************************************** -->
|
||||
<!-- ********************** The Form ****************************** -->
|
||||
<!-- ************************************************************** -->
|
||||
|
||||
<body>
|
||||
<h1>Send MPT</h1>
|
||||
<form id="theForm">
|
||||
<span class="tooltip" tooltip-data="Choose the XRPL host server for your account.">
|
||||
Choose your ledger instance:
|
||||
</span>
|
||||
|
||||
<input type="radio" id="dn" name="server" value="wss://s.devnet.rippletest.net:51233" checked>
|
||||
<label for="dn">Devnet</label>
|
||||
|
||||
<input type="radio" id="tn" name="server" value="wss://s.altnet.rippletest.net:51233">
|
||||
<label for="tn">Testnet</label>
|
||||
<br /><br />
|
||||
<table>
|
||||
<tr>
|
||||
<td>
|
||||
<button type="button" onClick="getNewAccount1()">Get New Account 1</button>
|
||||
</td>
|
||||
<td>
|
||||
<button type="button" onClick="getAccountFromSeed1()">Get Account 1 From Seed</button>
|
||||
</td>
|
||||
<td>
|
||||
<button type="button" onClick="getNewAccount2()">Get New Account 2</button>
|
||||
</td>
|
||||
<td>
|
||||
<button type="button" onClick="getAccountFromSeed2()">Get Account 2 From Seed</button>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<span class="tooltip" tooltip-data="Arbitrary human-readable name for the account."><label for="account1name">Account 1 Name</label>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="account1name" size="40"></input>
|
||||
</td>
|
||||
<td>
|
||||
<span class="tooltip" tooltip-data="Arbitrary human-readable name for the account.">
|
||||
<label for="account2name">Account 2 Name</label>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="account2name" size="40"></input>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<span class="tooltip" tooltip-data="Identifying address for the account.">
|
||||
<label for="account1address">Account 1 Address</label>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="account1address" size="40"></input>
|
||||
</td>
|
||||
<td>
|
||||
<span class="tooltip" tooltip-data="Identifying address for the account.">
|
||||
<label for="account2address">Account 2 Address</label>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="account2address" size="40"></input>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<span class="tooltip" tooltip-data="Seed for deriving public and private keys for the account.">
|
||||
<label for="account1seed">Account 1 Seed</label>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="account1seed" size="40"></input>
|
||||
</td>
|
||||
<td>
|
||||
<span class="tooltip" tooltip-data="Seed for deriving public and private keys for the account.">
|
||||
<label for="account2seed">Account 2 Seed</label>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="account2seed" size="40"></input>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<hr />
|
||||
<table>
|
||||
<tr valign="top">
|
||||
<td align="right">
|
||||
<span class="tooltip" tooltip-data="Name of the currently selected account.">
|
||||
<label for="accountNameField">Account Name</label>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="accountNameField" size="40" readonly></input>
|
||||
<input type="radio" id="account1" name="accounts" value="account1">
|
||||
<label for="account1">Account 1</label>
|
||||
</td>
|
||||
</tr>
|
||||
<tr valign="top">
|
||||
<td align="right">
|
||||
<span class="tooltip" tooltip-data="Address of the currently selected account.">
|
||||
<label for="accountAddressField">Account Address</label>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="accountAddressField" size="40" readonly></input>
|
||||
<input type="radio" id="account2" name="accounts" value="account2">
|
||||
<label for="account2">Account 2</label>
|
||||
</td>
|
||||
</tr>
|
||||
<tr valign="top">
|
||||
<td align="right">
|
||||
<span class="tooltip" tooltip-data="Seed of the currently selected account.">
|
||||
<label for="accountSeedField">Account Seed</label>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="accountSeedField" size="40" readonly></input>
|
||||
<br>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="right">
|
||||
<span class="tooltip" tooltip-data="XRP balance for the currently selected account.">
|
||||
<label for="xrpBalanceField">XRP Balance</label>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="xrpBalanceField" size="40" readonly></input>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="right">
|
||||
<span class="tooltip" tooltip-data="Issuance ID of the MPT you want to trade.">
|
||||
<lable for="mptIdField">MPT Issuance ID</lable>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="mptIdField" size="40"></input>
|
||||
<br>
|
||||
</td>
|
||||
<td>
|
||||
<button type="button" onClick="authorizeMPT()">Authorize MPT</button>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="right">
|
||||
<span class="tooltip" tooltip-data="Number of MPTs to send.">
|
||||
<label for="amountField">Amount</label>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="amountField" size="40"></input>
|
||||
<br>
|
||||
</td>
|
||||
<td>
|
||||
<button type="button" onClick="sendMPT()">Send MPT</button>
|
||||
</td>
|
||||
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="right">
|
||||
<span class="tooltip" tooltip-data="Destination account address for MPT transfer.">
|
||||
<lable for="destinationField">Destination</lable>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="destinationField" size="40"></input>
|
||||
<br>
|
||||
</td>
|
||||
<td align="left" valign="top">
|
||||
<button type="button" onClick="getMPTs()">Get MPTs</button>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="2">
|
||||
<p align="right">
|
||||
<textarea id="resultField" cols="80" rows="20"></textarea>
|
||||
</p>
|
||||
</td>
|
||||
<td align="left" valign="top">
|
||||
<button type="button" onClick="gatherAccountInfo()">Gather Account Info</button><br/>
|
||||
<button type="button" onClick="distributeAccountInfo()">Distribute Account Info</button>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</form>
|
||||
</body>
|
||||
<script>
|
||||
let radioButtons = document.querySelectorAll('input[type="radio"]');
|
||||
radioButtons.forEach(radio => {
|
||||
radio.addEventListener('change', function() {
|
||||
if (this.value === 'account1') {
|
||||
populate1()
|
||||
} else if (this.value === 'account2') {
|
||||
populate2()
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
</html>
|
||||
113
_code-samples/modular-tutorials/send-mpt.js
Normal file
113
_code-samples/modular-tutorials/send-mpt.js
Normal file
@@ -0,0 +1,113 @@
|
||||
// *******************************************************
|
||||
// ********************* Send MPT ************************
|
||||
// *******************************************************
|
||||
|
||||
async function sendMPT() {
|
||||
let net = getNet()
|
||||
const client = new xrpl.Client(net)
|
||||
await client.connect()
|
||||
let results = `===Connected to ${net}. Sending MPT.===\n`
|
||||
resultField.value = results
|
||||
try {
|
||||
const wallet = xrpl.Wallet.fromSeed(accountSeedField.value)
|
||||
const mpt_issuance_id = mptIdField.value
|
||||
const mpt_quantity = amountField.value
|
||||
const send_mpt_tx = {
|
||||
"TransactionType": "Payment",
|
||||
"Account": wallet.address,
|
||||
"Amount": {
|
||||
"mpt_issuance_id": mpt_issuance_id,
|
||||
"value": mpt_quantity,
|
||||
},
|
||||
"Destination": destinationField.value,
|
||||
}
|
||||
const pay_prepared = await client.autofill(send_mpt_tx)
|
||||
const pay_signed = wallet.sign(pay_prepared)
|
||||
results = `\n===Sending ${mpt_quantity} ${mpt_issuance_id} to ${destinationField.value} ...`
|
||||
resultField.value += results
|
||||
const pay_result = await client.submitAndWait(pay_signed.tx_blob)
|
||||
results = '\n\n===Transaction succeeded.\n'
|
||||
results += JSON.stringify(pay_result.result, null, 2)
|
||||
resultField.value += results
|
||||
} catch (error) {
|
||||
results = `Error sending MPT: ${error}`
|
||||
resultField.value += results
|
||||
}
|
||||
finally {
|
||||
client.disconnect()
|
||||
}
|
||||
} // end of sendMPT()
|
||||
|
||||
// *******************************************************
|
||||
// ******************** Get MPTs *************************
|
||||
// *******************************************************
|
||||
|
||||
async function getMPTs() {
|
||||
let net = getNet()
|
||||
const client = new xrpl.Client(net)
|
||||
await client.connect()
|
||||
let results = ''
|
||||
resultField.value = `===Connected to ${net}. Getting MPTs.===`
|
||||
|
||||
try {
|
||||
const wallet = xrpl.Wallet.fromSeed(accountSeedField.value)
|
||||
const mpts = await client.request({
|
||||
command: "account_objects",
|
||||
account: wallet.address,
|
||||
ledger_index: "validated",
|
||||
type: "mptoken"
|
||||
})
|
||||
let JSONString = JSON.stringify(mpts.result, null, 2)
|
||||
let JSONParse = JSON.parse(JSONString)
|
||||
let numberOfMPTs = JSONParse.account_objects.length
|
||||
let x = 0
|
||||
while (x < numberOfMPTs){
|
||||
results += "\n\n===MPT Issuance ID: " + JSONParse.account_objects[x].MPTokenIssuanceID
|
||||
+ "\n===MPT Amount: " + JSONParse.account_objects[x].MPTAmount
|
||||
x++
|
||||
}
|
||||
results += "\n\n" + JSONString
|
||||
resultField.value += results
|
||||
} catch (error) {
|
||||
results = `===Error getting MPTs: ${error}`
|
||||
resultField.value += results
|
||||
}
|
||||
finally {
|
||||
client.disconnect()
|
||||
}
|
||||
} // End of getMPTs()
|
||||
|
||||
// **********************************************************************
|
||||
// ****** MPTAuthorize Transaction ***************************************
|
||||
// **********************************************************************
|
||||
|
||||
async function authorizeMPT() {
|
||||
let net = getNet()
|
||||
const client = new xrpl.Client(net)
|
||||
await client.connect()
|
||||
let results = `===Connected to ${net}. Authorizing MPT.===\n`
|
||||
resultField.value = results
|
||||
try {
|
||||
const wallet = xrpl.Wallet.fromSeed(accountSeedField.value)
|
||||
const mpt_issuance_id = mptIdField.value
|
||||
const auth_mpt_tx = {
|
||||
"TransactionType": "MPTokenAuthorize",
|
||||
"Account": wallet.address,
|
||||
"MPTokenIssuanceID": mpt_issuance_id,
|
||||
}
|
||||
const auth_prepared = await client.autofill(auth_mpt_tx)
|
||||
const auth_signed = wallet.sign(auth_prepared)
|
||||
results += `\n\n===Sending authorization.===\n`
|
||||
resultField.value = results
|
||||
const auth_result = await client.submitAndWait(auth_signed.tx_blob)
|
||||
results = '\n===Transaction succeeded===\n\n'
|
||||
resultField.value += results
|
||||
results += `\n\n` + JSON.stringify(auth_result.result, null, 2)
|
||||
} catch (error) {
|
||||
results = `===Error authorizing MPT: ${error}`
|
||||
resultField.value = results
|
||||
} finally {
|
||||
resultField.value = results
|
||||
}
|
||||
client.disconnect()
|
||||
} // end of MPTAuthorize()
|
||||
37
_code-samples/modular-tutorials/send-xrp.js
Normal file
37
_code-samples/modular-tutorials/send-xrp.js
Normal file
@@ -0,0 +1,37 @@
|
||||
// *******************************************************
|
||||
// ******************** Send XRP *************************
|
||||
// *******************************************************
|
||||
async function sendXRP() {
|
||||
const net = getNet()
|
||||
const client = new xrpl.Client(net)
|
||||
await client.connect()
|
||||
let results = `===Connected to ${net}.===\n\nSending XRP.\n`
|
||||
resultField.value = results
|
||||
try {
|
||||
const wallet = xrpl.Wallet.fromSeed(accountSeedField.value)
|
||||
const sendAmount = amountField.value
|
||||
// -------------------------------------------------------- Prepare transaction
|
||||
const prepared_tx = await client.autofill({
|
||||
"TransactionType": "Payment",
|
||||
"Account": wallet.address,
|
||||
"Amount": xrpl.xrpToDrops(sendAmount),
|
||||
"Destination": destinationField.value
|
||||
})
|
||||
// ------------------------------------------------- Sign prepared instructions
|
||||
const signed = wallet.sign(prepared_tx)
|
||||
// -------------------------------------------------------- Submit signed blob
|
||||
const tx = await client.submitAndWait(signed.tx_blob)
|
||||
results += JSON.stringify(xrpl.getBalanceChanges(tx.result.meta), null, 2)
|
||||
resultField.value = results
|
||||
xrpBalanceField.value = (await client.getXrpBalance(wallet.address))
|
||||
} catch (error) {
|
||||
console.error('Error sending transaction:', error);
|
||||
results += `\nError: ${error.message}\n`
|
||||
resultField.value = results
|
||||
throw error; // Re-throw the error to be handled by the caller
|
||||
}
|
||||
finally {
|
||||
// Disconnect from the client
|
||||
await xrplClient.disconnect();
|
||||
}
|
||||
} // End of sendXRP()
|
||||
209
_code-samples/nft-modular-tutorials/account-support.js
Normal file
209
_code-samples/nft-modular-tutorials/account-support.js
Normal file
@@ -0,0 +1,209 @@
|
||||
// ******************************************************
|
||||
// ************* Get the Preferred Network **************
|
||||
// ******************************************************
|
||||
|
||||
function getNet() {
|
||||
let net
|
||||
if (document.getElementById("tn").checked) net = "wss://s.altnet.rippletest.net:51233/"
|
||||
if (document.getElementById("dn").checked) net = "wss://s.devnet.rippletest.net:51233/"
|
||||
return net
|
||||
} // End of getNet()
|
||||
|
||||
// *******************************************************
|
||||
// ************* Get Account *****************************
|
||||
// *******************************************************
|
||||
|
||||
async function getAccount() {
|
||||
let net = getNet()
|
||||
const client = new xrpl.Client(net)
|
||||
await client.connect()
|
||||
resultField.value = `===Getting Account===\n\nConnected to ${net}.`
|
||||
try {
|
||||
let faucetHost = null
|
||||
const my_wallet = (await client.fundWallet(null, { faucetHost})).wallet
|
||||
const newAccount = [my_wallet.address, my_wallet.seed]
|
||||
return newAccount
|
||||
}
|
||||
catch (error) {
|
||||
console.error('===Error getting account:', error);
|
||||
results += `\nError: ${error.message}\n`
|
||||
resultField.value = results
|
||||
throw error; // Re-throw the error to be handled by the caller
|
||||
}
|
||||
finally {
|
||||
// Disconnect from the client
|
||||
if (client && client.isConnected()) {
|
||||
await client.disconnect();
|
||||
}
|
||||
}
|
||||
} // End of getAccount()
|
||||
|
||||
async function getNewAccount1() {
|
||||
account1address.value = "=== Getting new account. ===\n\n"
|
||||
account1seed.value = ""
|
||||
const accountInfo= await getAccount()
|
||||
account1address.value = accountInfo[0]
|
||||
account1seed.value = accountInfo[1]
|
||||
}
|
||||
|
||||
async function getNewAccount2() {
|
||||
account2address.value = "=== Getting new account. ===\n\n"
|
||||
account2seed.value = ""
|
||||
const accountInfo= await getAccount()
|
||||
account2address.value = accountInfo[0]
|
||||
account2seed.value = accountInfo[1]
|
||||
}
|
||||
|
||||
// *****************************************************
|
||||
// ********** Get Account from Seed ********************
|
||||
// *****************************************************
|
||||
|
||||
async function getAccountFromSeed(my_seed) {
|
||||
const net = getNet()
|
||||
const client = new xrpl.Client(net)
|
||||
await client.connect()
|
||||
let results = '===Finding wallet.===\n\n'
|
||||
resultField.value = results
|
||||
try {
|
||||
const wallet = xrpl.Wallet.fromSeed(my_seed)
|
||||
const address = wallet.address
|
||||
results += "===Wallet found.===\n\n"
|
||||
results += "Account address: " + address + "\n\n"
|
||||
resultField.value = results
|
||||
return (address)
|
||||
}
|
||||
catch (error) {
|
||||
console.error('===Error getting account from seed:', error);
|
||||
results += `\nError: ${error.message}\n`
|
||||
resultField.value = results
|
||||
throw error; // Re-throw the error to be handled by the caller
|
||||
}
|
||||
finally {
|
||||
// Disconnect from the client
|
||||
await client.disconnect();
|
||||
}
|
||||
} // End of getAccountFromSeed()
|
||||
|
||||
// *****************************************************
|
||||
// ********** Get Account from Seed1 *******************
|
||||
// *****************************************************
|
||||
|
||||
async function getAccountFromSeed1() {
|
||||
account1address.value = await getAccountFromSeed(account1seed.value)
|
||||
}
|
||||
|
||||
// *****************************************************
|
||||
// ********** Get Account from Seed2 *******************
|
||||
// *****************************************************
|
||||
|
||||
async function getAccountFromSeed2() {
|
||||
account2address.value = await getAccountFromSeed(account2seed.value)
|
||||
}
|
||||
|
||||
// *****************************************************
|
||||
// ************ Gather Account Info ********************
|
||||
// *****************************************************
|
||||
|
||||
function gatherAccountInfo() {
|
||||
let accountData = account1name.value + "\n" + account1address.value + "\n" + account1seed.value + "\n"
|
||||
accountData += account2name.value + "\n" + account2address.value + "\n" + account2seed.value
|
||||
resultField.value = accountData
|
||||
}
|
||||
|
||||
// *****************************************************
|
||||
// ********** Distribute Account Info ******************
|
||||
// *****************************************************
|
||||
|
||||
function distributeAccountInfo() {
|
||||
let accountInfo = resultField.value.split("\n")
|
||||
account1name.value = accountInfo[0]
|
||||
account1address.value = accountInfo[1]
|
||||
account1seed.value = accountInfo[2]
|
||||
account2name.value = accountInfo[3]
|
||||
account2address.value = accountInfo[4]
|
||||
account2seed.value = accountInfo[5]
|
||||
}
|
||||
|
||||
// *****************************************************
|
||||
// ************ Populate Active Form 1 *****************
|
||||
// *****************************************************
|
||||
|
||||
function populate1() {
|
||||
accountNameField.value = account1name.value
|
||||
accountAddressField.value = account1address.value
|
||||
accountSeedField.value = account1seed.value
|
||||
getXrpBalance()
|
||||
}
|
||||
|
||||
// *****************************************************
|
||||
// ************ Populate Active Form 2 *****************
|
||||
// *****************************************************
|
||||
|
||||
function populate2() {
|
||||
accountNameField.value = account2name.value
|
||||
accountAddressField.value = account2address.value
|
||||
accountSeedField.value = account2seed.value
|
||||
getXrpBalance()
|
||||
}
|
||||
|
||||
// *******************************************************
|
||||
// **************** Get XRP Balance *********************
|
||||
// *******************************************************
|
||||
|
||||
async function getXrpBalance() {
|
||||
const net = getNet()
|
||||
const client = new xrpl.Client(net)
|
||||
await client.connect()
|
||||
let results = `\n===Getting XRP balance...===\n\n`
|
||||
resultField.value = results
|
||||
try {
|
||||
const wallet = xrpl.Wallet.fromSeed(accountSeedField.value)
|
||||
const balance = await client.getXrpBalance(wallet.address)
|
||||
results += accountNameField.value + " current XRP balance: " + balance + "\n\n"
|
||||
xrpBalanceField.value = await client.getXrpBalance(accountAddressField.value)
|
||||
resultField.value = results
|
||||
}
|
||||
catch (error) {
|
||||
console.error('Error getting XRP balance:', error);
|
||||
results += `\nError: ${error.message}\n`
|
||||
resultField.value = results
|
||||
throw error; // Re-throw the error to be handled by the caller
|
||||
}
|
||||
finally {
|
||||
// Disconnect from the client
|
||||
await client.disconnect();
|
||||
}
|
||||
} // End of getXrpBalance()
|
||||
|
||||
// *******************************************************
|
||||
// ************** Get Token Balance *********************
|
||||
// *******************************************************
|
||||
|
||||
async function getTokenBalance() {
|
||||
let net = getNet()
|
||||
const client = new xrpl.Client(net)
|
||||
await client.connect()
|
||||
let results = `===Connected to ${net}.===\n===Getting account token balance...===\n\n`
|
||||
resultField.value += results
|
||||
try {
|
||||
const wallet = xrpl.Wallet.fromSeed(accountSeedField.value)
|
||||
const balance = await client.request({
|
||||
command: "gateway_balances",
|
||||
account: wallet.address,
|
||||
ledger_index: "validated",
|
||||
})
|
||||
results = accountNameField.value + "\'s token balance(s): " + JSON.stringify(balance.result, null, 2) + "\n"
|
||||
resultField.value += results
|
||||
xrpBalanceField.value = (await client.getXrpBalance(wallet.address))
|
||||
}
|
||||
catch (error) {
|
||||
console.error('Error getting token balance:', error);
|
||||
results = `\nError: ${error.message}\n`
|
||||
resultField.value += results
|
||||
throw error; // Re-throw the error to be handled by the caller
|
||||
}
|
||||
finally {
|
||||
// Disconnect from the client
|
||||
await client.disconnect();
|
||||
}
|
||||
} // End of getTokenBalance()
|
||||
340
_code-samples/nft-modular-tutorials/authorized-minter.html
Normal file
340
_code-samples/nft-modular-tutorials/authorized-minter.html
Normal file
@@ -0,0 +1,340 @@
|
||||
<html>
|
||||
<head>
|
||||
<title>Authorize Minter of NFTs</title>
|
||||
<link href='https://fonts.googleapis.com/css?family=Work Sans' rel='stylesheet'>
|
||||
<link href="modular-tutorials.css" rel="stylesheet">
|
||||
<script src='https://unpkg.com/xrpl@4.1.0/build/xrpl-latest.js'></script>
|
||||
<script src="account-support.js"></script>
|
||||
<script src='transaction-support.js'></script>
|
||||
<script src='mint-nfts.js'></script>
|
||||
<script src='authorized-minter.js'></script>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Authorize Minter of NFTs</h1>
|
||||
<form id="theForm">
|
||||
<span class="tooltip" tooltip-data="Choose the XRPL host server for your account.">
|
||||
Choose your ledger instance:
|
||||
</span>
|
||||
|
||||
<input type="radio" id="dn" name="server" value="wss://s.devnet.rippletest.net:51233" checked>
|
||||
<label for="dn">Devnet</label>
|
||||
|
||||
<input type="radio" id="tn" name="server" value="wss://s.altnet.rippletest.net:51233">
|
||||
<label for="tn">Testnet</label>
|
||||
<br /><br />
|
||||
<table>
|
||||
<tr>
|
||||
<td>
|
||||
<button type="button" onClick="getNewAccount1()">Get New Account 1</button>
|
||||
</td>
|
||||
<td>
|
||||
<button type="button" onClick="getAccountFromSeed1()">Get Account 1 From Seed</button>
|
||||
</td>
|
||||
<td>
|
||||
<button type="button" onClick="getNewAccount2()">Get New Account 2</button>
|
||||
</td>
|
||||
<td>
|
||||
<button type="button" onClick="getAccountFromSeed2()">Get Account 2 From Seed</button>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<span class="tooltip" tooltip-data="Arbitrary human-readable name for the account."><label
|
||||
for="account1name">Account 1 Name</label>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="account1name" size="40"></input>
|
||||
</td>
|
||||
<td>
|
||||
<span class="tooltip" tooltip-data="Arbitrary human-readable name for the account.">
|
||||
<label for="account2name">Account 2 Name</label>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="account2name" size="40"></input>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<span class="tooltip" tooltip-data="Identifying address for the account.">
|
||||
<label for="account1address">Account 1 Address</label>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="account1address" size="40"></input>
|
||||
</td>
|
||||
<td>
|
||||
<span class="tooltip" tooltip-data="Identifying address for the account.">
|
||||
<label for="account2address">Account 2 Address</label>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="account2address" size="40"></input>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<span class="tooltip" tooltip-data="Seed for deriving public and private keys for the account.">
|
||||
<label for="account1seed">Account 1 Seed</label>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="account1seed" size="40"></input>
|
||||
</td>
|
||||
<td>
|
||||
<span class="tooltip" tooltip-data="Seed for deriving public and private keys for the account.">
|
||||
<label for="account2seed">Account 2 Seed</label>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="account2seed" size="40"></input>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<hr />
|
||||
<table>
|
||||
<tr valign="top">
|
||||
<td align="right">
|
||||
<span class="tooltip" tooltip-data="Name of the currently selected account.">
|
||||
<label for="accountNameField">Account Name</label>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="accountNameField" size="40" readonly></input>
|
||||
<input type="radio" id="account1" name="accounts" value="account1">
|
||||
<label for="account1">Account 1</label>
|
||||
</td>
|
||||
<td rowspan="4" align="center">
|
||||
<p>
|
||||
<img id="nftImage"
|
||||
src="https://ipfs.io/ipfs/bafybeigjro2d2tc43bgv7e4sxqg7f5jga7kjizbk7nnmmyhmq35dtz6deq"
|
||||
width="150" height="150">
|
||||
</td>
|
||||
<tr valign="top">
|
||||
<td align="right">
|
||||
<span class="tooltip" tooltip-data="Address of the currently selected account.">
|
||||
<label for="accountAddressField">Account Address</label>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="accountAddressField" size="40" readonly></input>
|
||||
<input type="radio" id="account2" name="accounts" value="account2">
|
||||
<label for="account2">Account 2</label>
|
||||
</td>
|
||||
</tr>
|
||||
<tr valign="top">
|
||||
<td align="right">
|
||||
<span class="tooltip" tooltip-data="Seed of the currently selected account.">
|
||||
<label for="accountSeedField">Account Seed</label>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="accountSeedField" size="40" readonly></input>
|
||||
<br>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="right">
|
||||
<span class="tooltip" tooltip-data="XRP balance for the currently selected account.">
|
||||
<label for="xrpBalanceField">XRP Balance</label>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="xrpBalanceField" size="40" readonly></input>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="right">
|
||||
<span class="tooltip" tooltip-data="NFT configuration flags.">
|
||||
<label for="flagsField">Flags</label>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="flagsField" size="40"></input>
|
||||
</td>
|
||||
<td align="right">
|
||||
<span class="tooltip" tooltip-data="URL to the stored NFT.">
|
||||
<label for="nftURLfield">NFT URL</label>
|
||||
</span>
|
||||
<input type="text" id="nftURLfield" size="30"
|
||||
value="https://ipfs.io/ipfs/bafybeigjro2d2tc43bgv7e4sxqg7f5jga7kjizbk7nnmmyhmq35dtz6deq"></input>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="right">
|
||||
<span class="tooltip" tooltip-data="Percentage of sale price collected by the issuer when the NFT is sold. Enter a value from 0 to 50000, where 1000=1%.">
|
||||
<label for="transferFeeField">Transfer Fee</label>
|
||||
</span>
|
||||
<p id="error-message"></p>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="transferFeeField" size="40"></input>
|
||||
</td>
|
||||
<td>
|
||||
<button type="button" onClick="mintNFT()">Mint NFT</button>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="right">
|
||||
<span class="tooltip" tooltip-data="NFT Taxon. Integer value used to identify NFTs minted in a series or collection. This value is required. Set it to 0 if you have no use for it.">
|
||||
<label for="nftTaxonField">NFT Taxon</label>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="nftTaxonField" size="40" value="0"></input>
|
||||
</td>
|
||||
<td>
|
||||
<button type="button" onClick="getNFTs()">Get NFTs</button>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="right">
|
||||
<span class="tooltip" tooltip-data="Currency for the offer.">
|
||||
<label for="currencyField">Currency</label>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="currencyField" size="40"></input>
|
||||
<br>
|
||||
</td>
|
||||
<td>
|
||||
<button type="button" onClick="burnNFT()">Burn NFT</button>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="right">
|
||||
<span class="tooltip" tooltip-data="Issuer of the currency used.">
|
||||
<label for="issuerField">Issuer</label>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="issuerField" size="40"></input>
|
||||
<br>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="right">
|
||||
<span class="tooltip" tooltip-data="Amount of XRP to send.">
|
||||
<label for="amountField">Amount</label>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="amountField" size="40"></input>
|
||||
</td>
|
||||
<td>
|
||||
<button type="button" onClick="authorizeMinter()">Authorize Minter</button>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="right">
|
||||
<span class="tooltip" tooltip-data="Destination account address where XRP is sent.">
|
||||
<label for="destinationField">Destination</label>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="destinationField" size="40"></input>
|
||||
<br>
|
||||
</td>
|
||||
<td>
|
||||
<button type="button" onClick="mintOther()">Mint Other</button>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="right">
|
||||
<span class="tooltip" tooltip-data="Number of days the offer is valid.">
|
||||
<label for="expirationField">Expiration (days)</label>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="expirationField" size="40"></input>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="right">
|
||||
<span class="tooltip" tooltip-data="NFT ID, used to transfer or burn the NFT after it is created.">
|
||||
<label for="nftIdField">NFT ID</label>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="nftIdField" size="40"></input>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="right">
|
||||
<span class="tooltip" tooltip-data="Account address that is authorized to mint NFTs for this account.">
|
||||
<label for="authorizedMinterField">Authorized Minter</label>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="authorizedMinterField" size="40"></input>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="right">
|
||||
<span class="tooltip" tooltip-data="Account that is the original issuer of the NFT.">
|
||||
<label for="nftIssuerField">NFT Issuer</label>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="nftIssuerField" size="40"></input>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="2">
|
||||
<p align="left">
|
||||
<textarea id="resultField" cols="75" rows="20"></textarea>
|
||||
</p>
|
||||
</td>
|
||||
<td align="left" valign="top">
|
||||
<button type="button" onClick="gatherAccountInfo()">Gather Account Info</button><br />
|
||||
<button type="button" onClick="distributeAccountInfo()">Distribute Account Info</button>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</form>
|
||||
</body>
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
const imageURLInput = document.getElementById('nftURLfield'); // Correct ID to nftURLfield
|
||||
const displayImage = document.getElementById('nftImage');
|
||||
const errorMessage = document.getElementById('error-message');
|
||||
|
||||
if (imageURLInput) {
|
||||
imageURLInput.addEventListener('change', () => {
|
||||
const newURL = imageURLInput.value;
|
||||
displayImage.src = ''; // Clear previous image
|
||||
errorMessage.style.display = 'none';
|
||||
try {
|
||||
new URL(newURL);
|
||||
} catch (_) {
|
||||
errorMessage.textContent = 'Invalid URL. Please enter a valid URL, including "https://" or "http://".';
|
||||
errorMessage.style.display = 'block';
|
||||
return;
|
||||
}
|
||||
displayImage.onload = () => {
|
||||
// Image loaded. You might add a console log here, or update UI.
|
||||
console.log(`Image loaded from: ${newURL}`);
|
||||
};
|
||||
displayImage.onerror = () => {
|
||||
errorMessage.textContent = 'Error loading image from the provided URL.';
|
||||
errorMessage.style.display = 'block';
|
||||
displayImage.src = ''; // Clear the image on error
|
||||
};
|
||||
displayImage.src = newURL; // Load the image
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
const radioButtons = document.querySelectorAll('input[type="radio"]');
|
||||
radioButtons.forEach(radio => {
|
||||
radio.addEventListener('change', function () {
|
||||
if (this.value === 'account1') {
|
||||
populate1()
|
||||
} else if (this.value === 'account2') {
|
||||
populate2()
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
</html>
|
||||
97
_code-samples/nft-modular-tutorials/authorized-minter.js
Normal file
97
_code-samples/nft-modular-tutorials/authorized-minter.js
Normal file
@@ -0,0 +1,97 @@
|
||||
// *******************************************************
|
||||
// ************ Authorize Minter ***********************
|
||||
// *******************************************************
|
||||
|
||||
async function authorizeMinter() {
|
||||
const wallet = xrpl.Wallet.fromSeed(accountSeedField.value);
|
||||
const net = getNet();
|
||||
const client = new xrpl.Client(net);
|
||||
let results = `\n=== Connected. Authorizing Minter. ===`;
|
||||
resultField.value = results;
|
||||
|
||||
try {
|
||||
await client.connect();
|
||||
tx_json = {
|
||||
"TransactionType": "AccountSet",
|
||||
"Account": wallet.address,
|
||||
"NFTokenMinter": authorizedMinterField.value,
|
||||
"SetFlag": xrpl.AccountSetAsfFlags.asfAuthorizedNFTokenMinter
|
||||
}
|
||||
|
||||
const prepared = await client.autofill(tx_json)
|
||||
const signed = wallet.sign(prepared)
|
||||
const result = await client.submitAndWait(signed.tx_blob)
|
||||
results += '\nAccount setting succeeded.\n'
|
||||
results += JSON.stringify(result, null, 2)
|
||||
resultField.value = results
|
||||
} catch (error) {
|
||||
console.error("Error setting minter:", error);
|
||||
results = `\n\n=== Error setting minter: ${error.message}`;
|
||||
resultField.value += results;
|
||||
} finally {
|
||||
if (client && client.isConnected()) {
|
||||
await client.disconnect();
|
||||
}
|
||||
}
|
||||
} // End of authorizeMinter()
|
||||
|
||||
// *******************************************************
|
||||
// **************** Mint Other *************************
|
||||
// *******************************************************
|
||||
|
||||
async function mintOther() {
|
||||
let results = 'Connecting to ' + getNet() + '....'
|
||||
resultField.value = results
|
||||
const net = getNet()
|
||||
const wallet = xrpl.Wallet.fromSeed(accountSeedField.value)
|
||||
const client = new xrpl.Client(net)
|
||||
|
||||
try {
|
||||
await client.connect()
|
||||
results += '\nConnected. Minting NFT.'
|
||||
resultField.value = results
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
const tx_json = {
|
||||
"TransactionType": "NFTokenMint",
|
||||
"Account": wallet.classicAddress,
|
||||
"URI": xrpl.convertStringToHex(nftURLfield.value),
|
||||
"Flags": parseInt(flagsField.value),
|
||||
"TransferFee": parseInt(transferFeeField.value),
|
||||
"Issuer": nftIssuerField.value,
|
||||
"NFTokenTaxon": nftTaxonField.value //Required, but if you have no use for it, set to zero.
|
||||
}
|
||||
if (amountField.value) {
|
||||
tx_json.Amount = configureAmount(amountField.value);
|
||||
}
|
||||
|
||||
if (expirationField.value) {
|
||||
tx_json.Expiration = configureExpiration(expirationField.value);
|
||||
}
|
||||
|
||||
if (destinationField.value) {
|
||||
tx_json.Destination = destinationField.value;
|
||||
}
|
||||
// ----------------------------------------------------- Submit transaction
|
||||
const tx = await client.submitAndWait(tx_json, { wallet: wallet })
|
||||
const nfts = await client.request({
|
||||
method: "account_nfts",
|
||||
account: wallet.classicAddress
|
||||
})
|
||||
// ------------------------------------------------------- Report results
|
||||
results += '\n\n=== Transaction result: ' + tx.result.meta.TransactionResult
|
||||
results += '\n\n=== NFTs: ' + JSON.stringify(nfts, null, 2)
|
||||
resultField.value = results + (await client.getXrpBalance(wallet.address))
|
||||
} catch (error) {
|
||||
results += '\n\nAn error occurred: ' + error.message
|
||||
console.error(error) // Log the error for debugging
|
||||
resultField.value = results
|
||||
} finally {
|
||||
if (client.isConnected()) { // Check if the client is connected before attempting to disconnect
|
||||
client.disconnect()
|
||||
results += '\nDisconnected from XRPL.'
|
||||
resultField.value = results
|
||||
}
|
||||
}
|
||||
} //End of mintOther()
|
||||
|
||||
320
_code-samples/nft-modular-tutorials/batch-minting.html
Normal file
320
_code-samples/nft-modular-tutorials/batch-minting.html
Normal file
@@ -0,0 +1,320 @@
|
||||
<html>
|
||||
<head>
|
||||
<title>Batch Mint NFTs</title>
|
||||
<link href='https://fonts.googleapis.com/css?family=Work Sans' rel='stylesheet'>
|
||||
<link href="modular-tutorials.css" rel="stylesheet">
|
||||
<script src='https://unpkg.com/xrpl@4.1.0/build/xrpl-latest.js'></script>
|
||||
<script src="account-support.js"></script>
|
||||
<script src='transaction-support.js'></script>
|
||||
<script src='mint-nfts.js'></script>
|
||||
<script src="batch-minting.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Batch Mint NFTs</h1>
|
||||
<form id="theForm">
|
||||
<span class="tooltip" tooltip-data="Choose the XRPL host server for your account.">
|
||||
Choose your ledger instance:
|
||||
</span>
|
||||
|
||||
<input type="radio" id="dn" name="server" value="wss://s.devnet.rippletest.net:51233" checked>
|
||||
<label for="dn">Devnet</label>
|
||||
|
||||
<input type="radio" id="tn" name="server" value="wss://s.altnet.rippletest.net:51233">
|
||||
<label for="tn">Testnet</label>
|
||||
<br /><br />
|
||||
<table>
|
||||
<tr>
|
||||
<td>
|
||||
<button type="button" onClick="getNewAccount1()">Get New Account 1</button>
|
||||
</td>
|
||||
<td>
|
||||
<button type="button" onClick="getAccountFromSeed1()">Get Account 1 From Seed</button>
|
||||
</td>
|
||||
<td>
|
||||
<button type="button" onClick="getNewAccount2()">Get New Account 2</button>
|
||||
</td>
|
||||
<td>
|
||||
<button type="button" onClick="getAccountFromSeed2()">Get Account 2 From Seed</button>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<span class="tooltip" tooltip-data="Arbitrary human-readable name for the account."><label
|
||||
for="account1name">Account 1 Name</label>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="account1name" size="40"></input>
|
||||
</td>
|
||||
<td>
|
||||
<span class="tooltip" tooltip-data="Arbitrary human-readable name for the account.">
|
||||
<label for="account2name">Account 2 Name</label>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="account2name" size="40"></input>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<span class="tooltip" tooltip-data="Identifying address for the account.">
|
||||
<label for="account1address">Account 1 Address</label>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="account1address" size="40"></input>
|
||||
</td>
|
||||
<td>
|
||||
<span class="tooltip" tooltip-data="Identifying address for the account.">
|
||||
<label for="account2address">Account 2 Address</label>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="account2address" size="40"></input>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<span class="tooltip" tooltip-data="Seed for deriving public and private keys for the account.">
|
||||
<label for="account1seed">Account 1 Seed</label>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="account1seed" size="40"></input>
|
||||
</td>
|
||||
<td>
|
||||
<span class="tooltip" tooltip-data="Seed for deriving public and private keys for the account.">
|
||||
<label for="account2seed">Account 2 Seed</label>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="account2seed" size="40"></input>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<hr />
|
||||
<table>
|
||||
<tr valign="top">
|
||||
<td align="right">
|
||||
<span class="tooltip" tooltip-data="Name of the currently selected account.">
|
||||
<label for="accountNameField">Account Name</label>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="accountNameField" size="40" readonly></input>
|
||||
<input type="radio" id="account1" name="accounts" value="account1">
|
||||
<label for="account1">Account 1</label>
|
||||
</td>
|
||||
<td rowspan="4" align="center">
|
||||
<p>
|
||||
<img id="nftImage"
|
||||
src="https://ipfs.io/ipfs/bafybeigjro2d2tc43bgv7e4sxqg7f5jga7kjizbk7nnmmyhmq35dtz6deq"
|
||||
width="150" height="150">
|
||||
</td>
|
||||
<tr valign="top">
|
||||
<td align="right">
|
||||
<span class="tooltip" tooltip-data="Address of the currently selected account.">
|
||||
<label for="accountAddressField">Account Address</label>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="accountAddressField" size="40" readonly></input>
|
||||
<input type="radio" id="account2" name="accounts" value="account2">
|
||||
<label for="account2">Account 2</label>
|
||||
</td>
|
||||
</tr>
|
||||
<tr valign="top">
|
||||
<td align="right">
|
||||
<span class="tooltip" tooltip-data="Seed of the currently selected account.">
|
||||
<label for="accountSeedField">Account Seed</label>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="accountSeedField" size="40" readonly></input>
|
||||
<br>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="right">
|
||||
<span class="tooltip" tooltip-data="XRP balance for the currently selected account.">
|
||||
<label for="xrpBalanceField">XRP Balance</label>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="xrpBalanceField" size="40" readonly></input>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="right">
|
||||
<span class="tooltip" tooltip-data="NFT configuration flags.">
|
||||
<label for="flagsField">Flags</label>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="flagsField" size="40"></input>
|
||||
</td>
|
||||
<td align="right">
|
||||
<span class="tooltip" tooltip-data="URL to the stored NFT.">
|
||||
<label for="nftURLfield">NFT URL</label>
|
||||
</span>
|
||||
<input type="text" id="nftURLfield" size="30"
|
||||
value="https://ipfs.io/ipfs/bafybeigjro2d2tc43bgv7e4sxqg7f5jga7kjizbk7nnmmyhmq35dtz6deq"></input>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="right">
|
||||
<span class="tooltip" tooltip-data="Percentage of sale price collected by the issuer when the NFT is sold. Enter a value from 0 to 50000, where 1000=1%.">
|
||||
<label for="transferFeeField">Transfer Fee</label>
|
||||
</span>
|
||||
<p id="error-message"></p>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="transferFeeField" size="40"></input>
|
||||
</td>
|
||||
<td>
|
||||
<button type="button" onClick="batchMintNFTs()">Batch Mint NFTs</button>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="right">
|
||||
<span class="tooltip" tooltip-data="NFT Taxon. Integer value used to identify NFTs minted in a series or collection. This value is required. Set it to 0 if you have no use for it.">
|
||||
<label for="nftTaxonField">NFT Taxon</label>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="nftTaxonField" size="40" value="0"></input>
|
||||
</td>
|
||||
<td>
|
||||
<button type="button" onClick="getBatchNFTs()">Get Batch NFTs</button>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="right">
|
||||
<span class="tooltip" tooltip-data="Currency for the offer.">
|
||||
<label for="currencyField">Currency</label>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="currencyField" size="40"></input>
|
||||
<br>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="right">
|
||||
<span class="tooltip" tooltip-data="Issuer of the currency used.">
|
||||
<label for="issuerField">Issuer</label>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="issuerField" size="40"></input>
|
||||
<br>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="right">
|
||||
<span class="tooltip" tooltip-data="Amount of XRP to send.">
|
||||
<label for="amountField">Amount</label>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="amountField" size="40"></input>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="right">
|
||||
<span class="tooltip" tooltip-data="Destination account address where XRP is sent.">
|
||||
<label for="destinationField">Destination</label>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="destinationField" size="40"></input>
|
||||
<br>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="right">
|
||||
<span class="tooltip" tooltip-data="Number of days the offer is valid.">
|
||||
<label for="expirationField">Expiration (days)</label>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="expirationField" size="40"></input>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="right">
|
||||
<span class="tooltip" tooltip-data="Number of NFTs to produce in a batch.">
|
||||
<label for="nftCountField">NFT Count</label>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="nftCountField" size="40"></input>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="right">
|
||||
<span class="tooltip" tooltip-data="NFT ID, used to transfer or burn the NFT after it is created.">
|
||||
<label for="nftIdField">NFT ID</label>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="nftIdField" size="40"></input>
|
||||
</td>
|
||||
</tr> <tr>
|
||||
<td colspan="2">
|
||||
<p align="left">
|
||||
<textarea id="resultField" cols="75" rows="20"></textarea>
|
||||
</p>
|
||||
</td>
|
||||
<td align="left" valign="top">
|
||||
<button type="button" onClick="gatherAccountInfo()">Gather Account Info</button><br />
|
||||
<button type="button" onClick="distributeAccountInfo()">Distribute Account Info</button>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</form>
|
||||
</body>
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
const imageURLInput = document.getElementById('nftURLfield'); // Correct ID to nftURLfield
|
||||
const displayImage = document.getElementById('nftImage');
|
||||
const errorMessage = document.getElementById('error-message');
|
||||
|
||||
if (imageURLInput) {
|
||||
imageURLInput.addEventListener('change', () => {
|
||||
const newURL = imageURLInput.value;
|
||||
displayImage.src = ''; // Clear previous image
|
||||
errorMessage.style.display = 'none';
|
||||
try {
|
||||
new URL(newURL);
|
||||
} catch (_) {
|
||||
errorMessage.textContent = 'Invalid URL. Please enter a valid URL, including "https://" or "http://".';
|
||||
errorMessage.style.display = 'block';
|
||||
return;
|
||||
}
|
||||
displayImage.onload = () => {
|
||||
// Image loaded. You might add a console log here, or update UI.
|
||||
console.log(`Image loaded from: ${newURL}`);
|
||||
};
|
||||
displayImage.onerror = () => {
|
||||
errorMessage.textContent = 'Error loading image from the provided URL.';
|
||||
errorMessage.style.display = 'block';
|
||||
displayImage.src = ''; // Clear the image on error
|
||||
};
|
||||
displayImage.src = newURL; // Load the image
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
const radioButtons = document.querySelectorAll('input[type="radio"]');
|
||||
radioButtons.forEach(radio => {
|
||||
radio.addEventListener('change', function () {
|
||||
if (this.value === 'account1') {
|
||||
populate1()
|
||||
} else if (this.value === 'account2') {
|
||||
populate2()
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
</html>
|
||||
272
_code-samples/nft-modular-tutorials/batch-minting.js
Normal file
272
_code-samples/nft-modular-tutorials/batch-minting.js
Normal file
@@ -0,0 +1,272 @@
|
||||
// *******************************************************
|
||||
// ****************** Batch Mint ***********************
|
||||
// *******************************************************
|
||||
|
||||
async function batchMintNFTs() {
|
||||
let client; // Declare client here so it's accessible in finally block
|
||||
try {
|
||||
//--------------------- Connect to the XRP Ledger and get the account wallet.
|
||||
let net = getNet();
|
||||
client = new xrpl.Client(net); // Assign client
|
||||
results = 'Connecting to ' + getNet() + '....';
|
||||
resultField.value = results;
|
||||
await client.connect();
|
||||
results += '\nConnected, finding wallet.';
|
||||
resultField.value = results;
|
||||
|
||||
let wallet;
|
||||
try {
|
||||
wallet = xrpl.Wallet.fromSeed(accountSeedField.value);
|
||||
} catch (error) {
|
||||
results += '\nError: Invalid account seed. Please check your seed.';
|
||||
resultField.value = results;
|
||||
return; // Stop execution if wallet cannot be derived
|
||||
}
|
||||
resultField.value = results;
|
||||
|
||||
//----------------- Get account information, particularly the Sequence number.
|
||||
let account_info;
|
||||
try {
|
||||
account_info = await client.request({
|
||||
"command": "account_info",
|
||||
"account": wallet.address
|
||||
});
|
||||
} catch (error) {
|
||||
results += `\nError retrieving account info for ${wallet.address}: ${error.message}`;
|
||||
resultField.value = results;
|
||||
return;
|
||||
}
|
||||
|
||||
let my_sequence = account_info.result.account_data.Sequence;
|
||||
results += "\n\nSequence Number: " + my_sequence + "\n\n";
|
||||
resultField.value = results;
|
||||
|
||||
/* ###################################
|
||||
Create ticket numbers for the batch
|
||||
|
||||
Without tickets, if one transaction fails, all others in the batch fail.
|
||||
With tickets, there can be failures, but the rest will continue, and you
|
||||
can investigate any problems afterward.
|
||||
*/
|
||||
|
||||
//---------------------- Parse the requested number from nftCountField.
|
||||
const nftCount = parseInt(nftCountField.value);
|
||||
if (isNaN(nftCount) || nftCount <= 0) {
|
||||
results += '\nError: Please enter a valid number of NFTs to mint.';
|
||||
resultField.value = results;
|
||||
return;
|
||||
}
|
||||
|
||||
//-------------------------------------------- Create the transaction hash.
|
||||
let ticketTransaction;
|
||||
try {
|
||||
ticketTransaction = await client.autofill({
|
||||
"TransactionType": "TicketCreate",
|
||||
"Account": wallet.address,
|
||||
"TicketCount": nftCount,
|
||||
"Sequence": my_sequence
|
||||
});
|
||||
} catch (error) {
|
||||
results += `\nError autofilling ticket creation transaction: ${error.message}`;
|
||||
resultField.value = results;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------------- Sign the transaction.
|
||||
const signedTransaction = wallet.sign(ticketTransaction);
|
||||
|
||||
//-------------------------- Submit the transaction and wait for the result.
|
||||
let tx;
|
||||
try {
|
||||
tx = await client.submitAndWait(signedTransaction.tx_blob);
|
||||
} catch (error) {
|
||||
results += `\nError submitting ticket creation transaction: ${error.message}`;
|
||||
resultField.value = results;
|
||||
return;
|
||||
}
|
||||
|
||||
if (tx.result.meta.TransactionResult !== 'tesSUCCESS') {
|
||||
results += `\nError creating tickets. Transaction failed with result: ${tx.result.meta.TransactionResult}`;
|
||||
resultField.value = results;
|
||||
return;
|
||||
}
|
||||
results += `\nTickets created successfully. Transaction result: ${tx.result.meta.TransactionResult}\n\n`;
|
||||
resultField.value = results;
|
||||
|
||||
let response;
|
||||
try {
|
||||
response = await client.request({
|
||||
"command": "account_objects",
|
||||
"account": wallet.address,
|
||||
"type": "ticket"
|
||||
});
|
||||
} catch (error) {
|
||||
results += `\nError retrieving account tickets: ${error.message}`;
|
||||
resultField.value = results;
|
||||
return;
|
||||
}
|
||||
|
||||
//------------------------------------ Populate the tickets array variable.
|
||||
let tickets = [];
|
||||
if (response.result.account_objects && response.result.account_objects.length > 0) {
|
||||
for (let i = 0; i < nftCount; i++) {
|
||||
if (response.result.account_objects[i]) {
|
||||
tickets[i] = response.result.account_objects[i].TicketSequence;
|
||||
} else {
|
||||
results += `\nWarning: Fewer tickets found than requested. Expected ${nftCount}, found ${response.result.account_objects.length}.`;
|
||||
resultField.value = results;
|
||||
break; // Exit loop if tickets run out
|
||||
}
|
||||
}
|
||||
} else {
|
||||
results += '\nError: No tickets found for the account.';
|
||||
resultField.value = results;
|
||||
return;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------- Report progress.
|
||||
results += "Tickets generated, minting NFTs.\n\n";
|
||||
resultField.value = results;
|
||||
|
||||
// ###################################
|
||||
// Mint NFTs
|
||||
|
||||
let mintedNFTsCount = 0;
|
||||
for (let i = 0; i < tickets.length; i++) {
|
||||
const transactionParams = {
|
||||
"TransactionType": "NFTokenMint",
|
||||
"Account": wallet.classicAddress,
|
||||
"URI": xrpl.convertStringToHex(nftURLfield.value),
|
||||
"Flags": parseInt(flagsField.value),
|
||||
"TransferFee": parseInt(transferFeeField.value),
|
||||
"Sequence": 0, // Sequence is 0 when using TicketSequence
|
||||
"TicketSequence": tickets[i],
|
||||
"LastLedgerSequence": null, // Optional, can be used for time limits
|
||||
"NFTokenTaxon": nftTaxonField.value,
|
||||
};
|
||||
|
||||
// Add optional fields
|
||||
if (amountField.value) {
|
||||
transactionParams.Amount = configureAmount(amountField.value);
|
||||
}
|
||||
|
||||
if (expirationField.value) {
|
||||
transactionParams.Expiration = configureExpiration(expirationField.value);
|
||||
}
|
||||
|
||||
if (destinationField.value) {
|
||||
transactionParams.Destination = destinationField.value;
|
||||
}
|
||||
|
||||
try {
|
||||
const mintTx = await client.submit(transactionParams, {
|
||||
wallet: wallet
|
||||
});
|
||||
results += `\nNFT ${i+1} minted successfully.`;
|
||||
mintedNFTsCount++;
|
||||
resultField.value = results;
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
}
|
||||
// Add a small delay to avoid hitting rate limits if many NFTs are being minted
|
||||
await new Promise(resolve => setTimeout(resolve, 500));
|
||||
}
|
||||
|
||||
results += `\n\nAttempted to mint ${nftCount} NFTs. Successfully minted ${mintedNFTsCount} NFTs.`;
|
||||
|
||||
results += "\n\nFetching minted NFTs...\n";
|
||||
let nfts;
|
||||
try {
|
||||
nfts = await client.request({
|
||||
method: "account_nfts",
|
||||
account: wallet.classicAddress,
|
||||
limit: 400
|
||||
});
|
||||
results += JSON.stringify(nfts, null, 2);
|
||||
|
||||
while (nfts.result.marker) {
|
||||
nfts = await client.request({
|
||||
method: "account_nfts",
|
||||
account: wallet.classicAddress,
|
||||
limit: 400,
|
||||
marker: nfts.result.marker
|
||||
});
|
||||
results += '\n' + JSON.stringify(nfts, null, 2);
|
||||
}
|
||||
} catch (error) {
|
||||
results += `\nError fetching account NFTs: ${error.message}`;
|
||||
}
|
||||
|
||||
try {
|
||||
xrpBalanceField.value = (await client.getXrpBalance(wallet.address));
|
||||
} catch (error) {
|
||||
results += `\nError fetching XRP balance: ${error.message}`;
|
||||
}
|
||||
|
||||
resultField.value = results;
|
||||
|
||||
} catch (error) {
|
||||
results += `\nAn unexpected error occurred during batch minting: ${error.message}`;
|
||||
resultField.value = results;
|
||||
} finally {
|
||||
if (client && client.isConnected()) {
|
||||
client.disconnect();
|
||||
results += '\nDisconnected from XRP Ledger.';
|
||||
resultField.value = results;
|
||||
}
|
||||
}
|
||||
} // End of batchMint()
|
||||
|
||||
|
||||
// *******************************************************
|
||||
// **************** Get Batch Tokens *********************
|
||||
// *******************************************************
|
||||
|
||||
async function getBatchNFTs() {
|
||||
let client; // Declare client here for finally block access
|
||||
try {
|
||||
const wallet = xrpl.Wallet.fromSeed(accountSeedField.value);
|
||||
let net = getNet();
|
||||
client = new xrpl.Client(net); // Assign client
|
||||
results = 'Connecting to ' + net + '...';
|
||||
resultField.value = results;
|
||||
await client.connect();
|
||||
results += '\nConnected. Getting NFTs...';
|
||||
resultField.value = results;
|
||||
|
||||
results += "\n\nNFTs:\n";
|
||||
let nfts;
|
||||
try {
|
||||
nfts = await client.request({
|
||||
method: "account_nfts",
|
||||
account: wallet.classicAddress,
|
||||
limit: 400
|
||||
});
|
||||
|
||||
results += JSON.stringify(nfts, null, 2);
|
||||
while (nfts.result.marker) {
|
||||
nfts = await client.request({
|
||||
method: "account_nfts",
|
||||
account: wallet.classicAddress,
|
||||
limit: 400,
|
||||
marker: nfts.result.marker
|
||||
});
|
||||
results += '\n' + JSON.stringify(nfts, null, 2);
|
||||
}
|
||||
} catch (error) {
|
||||
results += `\nError fetching account NFTs: ${error.message}`;
|
||||
}
|
||||
resultField.value = results;
|
||||
|
||||
} catch (error) {
|
||||
results += `\nAn unexpected error occurred while getting batch NFTs: ${error.message}`;
|
||||
resultField.value = results;
|
||||
} finally {
|
||||
if (client && client.isConnected()) {
|
||||
client.disconnect();
|
||||
results += '\nDisconnected from XRP Ledger.';
|
||||
resultField.value = results;
|
||||
}
|
||||
}
|
||||
} //End of getBatchNFTs()
|
||||
291
_code-samples/nft-modular-tutorials/broker-nfts.html
Normal file
291
_code-samples/nft-modular-tutorials/broker-nfts.html
Normal file
@@ -0,0 +1,291 @@
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<title>Broker NFTs</title>
|
||||
<link href='https://fonts.googleapis.com/css?family=Work Sans' rel='stylesheet'>
|
||||
<link href="modular-tutorials.css" rel="stylesheet">
|
||||
<script src='https://unpkg.com/xrpl@4.1.0/build/xrpl-latest.js'></script>
|
||||
<script src="account-support.js"></script>
|
||||
<script src="transaction-support.js"></script>
|
||||
<script src="mint-nfts.js"></script>
|
||||
<script src="transfer-nfts.js"></script>
|
||||
<script src="broker-nfts.js"></script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<h1>Broker NFTs</h1>
|
||||
<form id="theForm">
|
||||
<span class="tooltip" tooltip-data="Choose the XRPL host server for your account.">
|
||||
Choose your ledger instance:
|
||||
</span>
|
||||
|
||||
<input type="radio" id="dn" name="server" value="wss://s.devnet.rippletest.net:51233" checked>
|
||||
<label for="dn">Devnet</label>
|
||||
|
||||
<input type="radio" id="tn" name="server" value="wss://s.altnet.rippletest.net:51233">
|
||||
<label for="tn">Testnet</label>
|
||||
<br /><br />
|
||||
<table>
|
||||
<tr>
|
||||
<td>
|
||||
<button type="button" onClick="getNewAccount1()">Get New Account 1</button>
|
||||
</td>
|
||||
<td>
|
||||
<button type="button" onClick="getAccountFromSeed1()">Get Account 1 From Seed</button>
|
||||
</td>
|
||||
<td>
|
||||
<button type="button" onClick="getNewAccount2()">Get New Account 2</button>
|
||||
</td>
|
||||
<td>
|
||||
<button type="button" onClick="getAccountFromSeed2()">Get Account 2 From Seed</button>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<span class="tooltip" tooltip-data="Arbitrary human-readable name for the account."><label
|
||||
for="account1name">Account 1 Name</label>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="account1name" size="40"></input>
|
||||
</td>
|
||||
<td>
|
||||
<span class="tooltip" tooltip-data="Arbitrary human-readable name for the account.">
|
||||
<label for="account2name">Account 2 Name</label>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="account2name" size="40"></input>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<span class="tooltip" tooltip-data="Identifying address for the account.">
|
||||
<label for="account1address">Account 1 Address</label>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="account1address" size="40"></input>
|
||||
</td>
|
||||
<td>
|
||||
<span class="tooltip" tooltip-data="Identifying address for the account.">
|
||||
<label for="account2address">Account 2 Address</label>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="account2address" size="40"></input>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<span class="tooltip" tooltip-data="Seed for deriving public and private keys for the account.">
|
||||
<label for="account1seed">Account 1 Seed</label>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="account1seed" size="40"></input>
|
||||
</td>
|
||||
<td>
|
||||
<span class="tooltip" tooltip-data="Seed for deriving public and private keys for the account.">
|
||||
<label for="account2seed">Account 2 Seed</label>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="account2seed" size="40"></input>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<hr />
|
||||
<table>
|
||||
<tr valign="top">
|
||||
<td align="right">
|
||||
<span class="tooltip" tooltip-data="Name of the currently selected account.">
|
||||
<label for="accountNameField">Account Name</label>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="accountNameField" size="40" readonly></input>
|
||||
<input type="radio" id="account1" name="accounts" value="account1">
|
||||
<label for="account1">Account 1</label>
|
||||
</td>
|
||||
<td rowspan="4" align="center">
|
||||
<p>
|
||||
<img id="nftImage"
|
||||
src="https://ipfs.io/ipfs/bafybeigjro2d2tc43bgv7e4sxqg7f5jga7kjizbk7nnmmyhmq35dtz6deq"
|
||||
width="150" height="150">
|
||||
</td>
|
||||
</tr>
|
||||
<tr valign="top">
|
||||
<td align="right">
|
||||
<span class="tooltip" tooltip-data="Address of the currently selected account.">
|
||||
<label for="accountAddressField">Account Address</label>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="accountAddressField" size="40" readonly></input>
|
||||
<input type="radio" id="account2" name="accounts" value="account2">
|
||||
<label for="account2">Account 2</label>
|
||||
</td>
|
||||
</tr>
|
||||
<tr valign="top">
|
||||
<td align="right">
|
||||
<span class="tooltip" tooltip-data="Seed of the currently selected account.">
|
||||
<label for="accountSeedField">Account Seed</label>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="accountSeedField" size="40" readonly></input>
|
||||
<br>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="right">
|
||||
<span class="tooltip" tooltip-data="XRP balance for the currently selected account.">
|
||||
<label for="xrpBalanceField">XRP Balance</label>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="xrpBalanceField" size="40" readonly></input>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
</td>
|
||||
<td align="right">
|
||||
<span class="tooltip" tooltip-data="URL to the stored NFT.">
|
||||
<label for="nftURLfield">NFT URL</label>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="nftURLfield" size="40"
|
||||
placeholder="https://ipfs.io/ipfs/bafybeigjro2d2tc43bgv7e4sxqg7f5jga7kjizbk7nnmmyhmq35dtz6deq"></input>
|
||||
<br />
|
||||
<p id="error-message"></p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="right">
|
||||
<span class="tooltip" tooltip-data="NFT ID code, used to identify the token after it's minted.">
|
||||
<label for="nftIdField">NFT ID</label>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="nftIdField" size="40"></input>
|
||||
</td>
|
||||
|
||||
<td align="center" valign="top">
|
||||
<button type="button" onClick="getNFTs()">Get NFTs</button>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="right">
|
||||
<span class="tooltip" tooltip-data="Account address of the Owner of an NFT offered to sell or buy.">
|
||||
<label for="nftOwnerField">NFT Owner Address</label>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="nftOwnerField" size="40"></input>
|
||||
</td>
|
||||
<td colspan="2" align="center" valign="top">
|
||||
<button type="button" onClick="getOffers()" width="40">Get Offers</button>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="right">
|
||||
<span class="tooltip" tooltip-data="Index of the sell offer to broker.">
|
||||
<label for="nftSellOfferIndexField">Sell Offer Index</label>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="nftSellOfferIndexField" size="40"></input>
|
||||
<br>
|
||||
</td>
|
||||
<td align="middle" valign="top" colspan="2">
|
||||
<button type="button" onClick="brokerSale()">Broker Sale</button>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="right">
|
||||
<span class="tooltip" tooltip-data="Index of the buy offer to broker.">
|
||||
<label for="nftBuyOfferIndexField">Buy Offer Index</label>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="nftBuyOfferIndexField" size="40"></input>
|
||||
<br>
|
||||
</td>
|
||||
<td align="middle" valign="top" colspan="2">
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="right">
|
||||
<span class="tooltip" tooltip-data="Fee collected by the broker account when the brokered deal is complete.">
|
||||
<label for="brokerFeeField">Broker Fee</label>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="brokerFeeField" size="40"></input>
|
||||
</td>
|
||||
</tr>
|
||||
<tr valign="top">
|
||||
<td colspan="2">
|
||||
<p align="left">
|
||||
<textarea id="resultField" cols="75" rows="20"></textarea>
|
||||
</p>
|
||||
</td>
|
||||
<td align="left" valign="top">
|
||||
<button type="button" onClick="gatherAccountInfo()">Gather Account Info</button><br />
|
||||
<button type="button" onClick="distributeAccountInfo()">Distribute Account Info</button>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</form>
|
||||
</body>
|
||||
<script>
|
||||
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
const imageURLInput = document.getElementById('nftURLfield'); // Correct ID to nftURLfield
|
||||
const displayImage = document.getElementById('nftImage');
|
||||
const loadButton = document.getElementById('showNFTbutton');
|
||||
const errorMessage = document.getElementById('error-message');
|
||||
|
||||
if (imageURLInput) {
|
||||
imageURLInput.addEventListener('change', () => {
|
||||
const newURL = imageURLInput.value;
|
||||
displayImage.src = ''; // Clear previous image
|
||||
errorMessage.style.display = 'none';
|
||||
try {
|
||||
new URL(newURL);
|
||||
} catch (_) {
|
||||
errorMessage.textContent = 'Invalid URL. Please enter a valid URL, including "https://" or "http://".';
|
||||
errorMessage.style.display = 'block';
|
||||
return;
|
||||
}
|
||||
displayImage.onload = () => {
|
||||
// Image loaded. You might add a console log here, or update UI.
|
||||
console.log(`Image loaded from: ${newURL}`);
|
||||
};
|
||||
displayImage.onerror = () => {
|
||||
errorMessage.textContent = 'Error loading image from the provided URL.';
|
||||
errorMessage.style.display = 'block';
|
||||
displayImage.src = ''; // Clear the image on error
|
||||
};
|
||||
displayImage.src = newURL; // Load the image
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
const radioButtons = document.querySelectorAll('input[type="radio"]');
|
||||
radioButtons.forEach(radio => {
|
||||
radio.addEventListener('change', function () {
|
||||
if (this.value === 'account1') {
|
||||
populate1()
|
||||
} else if (this.value === 'account2') {
|
||||
populate2()
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
</html>
|
||||
44
_code-samples/nft-modular-tutorials/broker-nfts.js
Normal file
44
_code-samples/nft-modular-tutorials/broker-nfts.js
Normal file
@@ -0,0 +1,44 @@
|
||||
// *******************************************************
|
||||
// ******************* Broker Sale ***********************
|
||||
// *******************************************************
|
||||
|
||||
async function brokerSale() {
|
||||
const wallet = xrpl.Wallet.fromSeed(accountSeedField.value);
|
||||
const net = getNet();
|
||||
const client = new xrpl.Client(net);
|
||||
let results = `\n=== Connected. Brokering the sale. ===`;
|
||||
resultField.value = results;
|
||||
|
||||
try {
|
||||
await client.connect();
|
||||
|
||||
// Prepare transaction -------------------------------------------------------
|
||||
const brokerTx = {
|
||||
"TransactionType": "NFTokenAcceptOffer",
|
||||
"Account": wallet.classicAddress,
|
||||
"NFTokenSellOffer": nftSellOfferIndexField.value,
|
||||
"NFTokenBuyOffer": nftBuyOfferIndexField.value,
|
||||
"NFTokenBrokerFee": brokerFeeField.value
|
||||
}
|
||||
console.log(JSON.stringify(brokerTx, null, 2));
|
||||
// Submit transaction --------------------------------------------------------
|
||||
const tx = await client.submitAndWait(brokerTx, { wallet: wallet })
|
||||
|
||||
// Check transaction results -------------------------------------------------
|
||||
results += "\n\nTransaction result:\n" +
|
||||
JSON.stringify(tx.result.meta.TransactionResult, null, 2)
|
||||
results += "\nBalance changes:\n" +
|
||||
JSON.stringify(xrpl.getBalanceChanges(tx.result.meta), null, 2)
|
||||
xrpBalanceField.value = (await client.getXrpBalance(wallet.address))
|
||||
resultField.value += results
|
||||
} catch (error) {
|
||||
console.error("Error in broker sale:", error);
|
||||
results = `\n\n=== Error in broker sale: ${error.message} ===`; // User friendly
|
||||
resultField.value += results;
|
||||
}
|
||||
finally {
|
||||
if (client && client.isConnected()) {
|
||||
await client.disconnect();
|
||||
}
|
||||
}
|
||||
}// End of brokerSale()
|
||||
313
_code-samples/nft-modular-tutorials/mint-nfts.html
Normal file
313
_code-samples/nft-modular-tutorials/mint-nfts.html
Normal file
@@ -0,0 +1,313 @@
|
||||
<html>
|
||||
<head>
|
||||
<title>Mint NFTs</title>
|
||||
<link href='https://fonts.googleapis.com/css?family=Work Sans' rel='stylesheet'>
|
||||
<link href="modular-tutorials.css" rel="stylesheet">
|
||||
<script src='https://unpkg.com/xrpl@4.1.0/build/xrpl-latest.js'></script>
|
||||
<script src="account-support.js"></script>
|
||||
<script src='transaction-support.js'></script>
|
||||
<script src='mint-nfts.js'></script>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Mint NFTs</h1>
|
||||
<form id="theForm">
|
||||
<span class="tooltip" tooltip-data="Choose the XRPL host server for your account.">
|
||||
Choose your ledger instance:
|
||||
</span>
|
||||
|
||||
<input type="radio" id="dn" name="server" value="wss://s.devnet.rippletest.net:51233" checked>
|
||||
<label for="dn">Devnet</label>
|
||||
|
||||
<input type="radio" id="tn" name="server" value="wss://s.altnet.rippletest.net:51233">
|
||||
<label for="tn">Testnet</label>
|
||||
<br /><br />
|
||||
<table>
|
||||
<tr>
|
||||
<td>
|
||||
<button type="button" onClick="getNewAccount1()">Get New Account 1</button>
|
||||
</td>
|
||||
<td>
|
||||
<button type="button" onClick="getAccountFromSeed1()">Get Account 1 From Seed</button>
|
||||
</td>
|
||||
<td>
|
||||
<button type="button" onClick="getNewAccount2()">Get New Account 2</button>
|
||||
</td>
|
||||
<td>
|
||||
<button type="button" onClick="getAccountFromSeed2()">Get Account 2 From Seed</button>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<span class="tooltip" tooltip-data="Arbitrary human-readable name for the account."><label
|
||||
for="account1name">Account 1 Name</label>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="account1name" size="40"></input>
|
||||
</td>
|
||||
<td>
|
||||
<span class="tooltip" tooltip-data="Arbitrary human-readable name for the account.">
|
||||
<label for="account2name">Account 2 Name</label>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="account2name" size="40"></input>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<span class="tooltip" tooltip-data="Identifying address for the account.">
|
||||
<label for="account1address">Account 1 Address</label>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="account1address" size="40"></input>
|
||||
</td>
|
||||
<td>
|
||||
<span class="tooltip" tooltip-data="Identifying address for the account.">
|
||||
<label for="account2address">Account 2 Address</label>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="account2address" size="40"></input>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<span class="tooltip" tooltip-data="Seed for deriving public and private keys for the account.">
|
||||
<label for="account1seed">Account 1 Seed</label>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="account1seed" size="40"></input>
|
||||
</td>
|
||||
<td>
|
||||
<span class="tooltip" tooltip-data="Seed for deriving public and private keys for the account.">
|
||||
<label for="account2seed">Account 2 Seed</label>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="account2seed" size="40"></input>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<hr />
|
||||
<table>
|
||||
<tr valign="top">
|
||||
<td align="right">
|
||||
<span class="tooltip" tooltip-data="Name of the currently selected account.">
|
||||
<label for="accountNameField">Account Name</label>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="accountNameField" size="40" readonly></input>
|
||||
<input type="radio" id="account1" name="accounts" value="account1">
|
||||
<label for="account1">Account 1</label>
|
||||
</td>
|
||||
<td rowspan="4" align="center">
|
||||
<p>
|
||||
<img id="nftImage"
|
||||
src="https://ipfs.io/ipfs/bafybeigjro2d2tc43bgv7e4sxqg7f5jga7kjizbk7nnmmyhmq35dtz6deq"
|
||||
width="150" height="150">
|
||||
</td>
|
||||
<tr valign="top">
|
||||
<td align="right">
|
||||
<span class="tooltip" tooltip-data="Address of the currently selected account.">
|
||||
<label for="accountAddressField">Account Address</label>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="accountAddressField" size="40" readonly></input>
|
||||
<input type="radio" id="account2" name="accounts" value="account2">
|
||||
<label for="account2">Account 2</label>
|
||||
</td>
|
||||
</tr>
|
||||
<tr valign="top">
|
||||
<td align="right">
|
||||
<span class="tooltip" tooltip-data="Seed of the currently selected account.">
|
||||
<label for="accountSeedField">Account Seed</label>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="accountSeedField" size="40" readonly></input>
|
||||
<br>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="right">
|
||||
<span class="tooltip" tooltip-data="XRP balance for the currently selected account.">
|
||||
<label for="xrpBalanceField">XRP Balance</label>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="xrpBalanceField" size="40" readonly></input>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="right">
|
||||
<span class="tooltip" tooltip-data="NFT configuration flags.">
|
||||
<label for="flagsField">Flags</label>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="flagsField" size="40"></input>
|
||||
</td>
|
||||
<td align="right">
|
||||
<span class="tooltip" tooltip-data="URL to the stored NFT.">
|
||||
<label for="nftURLfield">NFT URL</label>
|
||||
</span>
|
||||
<input type="text" id="nftURLfield" size="30"
|
||||
value="https://ipfs.io/ipfs/bafybeigjro2d2tc43bgv7e4sxqg7f5jga7kjizbk7nnmmyhmq35dtz6deq"></input>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="right">
|
||||
<span class="tooltip" tooltip-data="Percentage of sale price collected by the issuer when the NFT is sold. Enter a value from 0 to 50000, where 1000=1%.">
|
||||
<label for="transferFeeField">Transfer Fee</label>
|
||||
</span>
|
||||
<p id="error-message"></p>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="transferFeeField" size="40"></input>
|
||||
</td>
|
||||
<td>
|
||||
<button type="button" onClick="mintNFT()">Mint NFT</button>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="right">
|
||||
<span class="tooltip" tooltip-data="NFT Taxon. Integer value used to identify NFTs minted in a series or collection. This value is required. Set it to 0 if you have no use for it.">
|
||||
<label for="nftTaxonField">NFT Taxon</label>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="nftTaxonField" size="40" value="0"></input>
|
||||
</td>
|
||||
<td>
|
||||
<button type="button" onClick="getNFTs()">Get NFTs</button>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="right">
|
||||
<span class="tooltip" tooltip-data="Currency for the offer.">
|
||||
<label for="currencyField">Currency</label>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="currencyField" size="40"></input>
|
||||
<br>
|
||||
</td>
|
||||
<td>
|
||||
<button type="button" onClick="burnNFT()">Burn NFT</button>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="right">
|
||||
<span class="tooltip" tooltip-data="Issuer of the currency used.">
|
||||
<label for="issuerField">Issuer</label>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="issuerField" size="40"></input>
|
||||
<br>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="right">
|
||||
<span class="tooltip" tooltip-data="Amount of currency to send. If XRP, you can enter 1 per XRP: the amount is converted to drops for you.">
|
||||
<label for="amountField">Amount</label>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="amountField" size="40"></input>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="right">
|
||||
<span class="tooltip" tooltip-data="Destination account address where XRP is sent.">
|
||||
<label for="destinationField">Destination</label>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="destinationField" size="40"></input>
|
||||
<br>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="right">
|
||||
<span class="tooltip" tooltip-data="Number of days the offer is valid.">
|
||||
<label for="expirationField">Expiration (days)</label>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="expirationField" size="40"></input>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="right">
|
||||
<span class="tooltip" tooltip-data="NFT ID, used to transfer or burn the NFT after it is created.">
|
||||
<label for="nftIdField">NFT ID</label>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="nftIdField" size="40"></input>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="2">
|
||||
<p align="left">
|
||||
<textarea id="resultField" cols="75" rows="20"></textarea>
|
||||
</p>
|
||||
</td>
|
||||
<td align="left" valign="top">
|
||||
<button type="button" onClick="gatherAccountInfo()">Gather Account Info</button><br />
|
||||
<button type="button" onClick="distributeAccountInfo()">Distribute Account Info</button>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</form>
|
||||
</body>
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
const imageURLInput = document.getElementById('nftURLfield'); // Correct ID to nftURLfield
|
||||
const displayImage = document.getElementById('nftImage');
|
||||
const errorMessage = document.getElementById('error-message');
|
||||
|
||||
if (imageURLInput) {
|
||||
imageURLInput.addEventListener('change', () => {
|
||||
const newURL = imageURLInput.value;
|
||||
displayImage.src = ''; // Clear previous image
|
||||
errorMessage.style.display = 'none';
|
||||
try {
|
||||
new URL(newURL);
|
||||
} catch (_) {
|
||||
errorMessage.textContent = 'Invalid URL. Please enter a valid URL, including "https://" or "http://".';
|
||||
errorMessage.style.display = 'block';
|
||||
return;
|
||||
}
|
||||
displayImage.onload = () => {
|
||||
// Image loaded. You might add a console log here, or update UI.
|
||||
console.log(`Image loaded from: ${newURL}`);
|
||||
};
|
||||
displayImage.onerror = () => {
|
||||
errorMessage.textContent = 'Error loading image from the provided URL.';
|
||||
errorMessage.style.display = 'block';
|
||||
displayImage.src = ''; // Clear the image on error
|
||||
};
|
||||
displayImage.src = newURL; // Load the image
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
const radioButtons = document.querySelectorAll('input[type="radio"]');
|
||||
radioButtons.forEach(radio => {
|
||||
radio.addEventListener('change', function () {
|
||||
if (this.value === 'account1') {
|
||||
populate1()
|
||||
} else if (this.value === 'account2') {
|
||||
populate2()
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
</html>
|
||||
141
_code-samples/nft-modular-tutorials/mint-nfts.js
Normal file
141
_code-samples/nft-modular-tutorials/mint-nfts.js
Normal file
@@ -0,0 +1,141 @@
|
||||
// *******************************************************
|
||||
// ********************** Mint NFT ***********************
|
||||
// *******************************************************
|
||||
|
||||
async function mintNFT() {
|
||||
const wallet = xrpl.Wallet.fromSeed(accountSeedField.value);
|
||||
const net = getNet();
|
||||
const client = new xrpl.Client(net);
|
||||
let results = `\n=== Connected. Minting NFT ===`;
|
||||
resultField.value = results;
|
||||
|
||||
try {
|
||||
await client.connect();
|
||||
|
||||
// Prepare transaction parameters
|
||||
const transactionParams = {
|
||||
TransactionType: "NFTokenMint",
|
||||
Account: wallet.classicAddress,
|
||||
URI: xrpl.convertStringToHex(nftURLfield.value),
|
||||
Flags: parseInt(flagsField.value, 10), // Parse to integer
|
||||
TransferFee: parseInt(transferFeeField.value, 10), // Parse to integer
|
||||
NFTokenTaxon: parseInt(nftTaxonField.value, 10), // Parse to integer
|
||||
};
|
||||
|
||||
// Add optional fields
|
||||
if (amountField.value) {
|
||||
transactionParams.Amount = configureAmount(amountField.value);
|
||||
}
|
||||
|
||||
if (expirationField.value) {
|
||||
transactionParams.Expiration = configureExpiration(expirationField.value);
|
||||
}
|
||||
|
||||
if (destinationField.value) {
|
||||
transactionParams.Destination = destinationField.value;
|
||||
}
|
||||
|
||||
console.log("Mint NFT Transaction Parameters:", transactionParams); // Log before submitting
|
||||
|
||||
// Submit transaction
|
||||
const tx = await client.submitAndWait(transactionParams, { wallet });
|
||||
|
||||
// Get minted NFTs
|
||||
const nfts = await client.request({
|
||||
method: "account_nfts",
|
||||
account: wallet.classicAddress,
|
||||
});
|
||||
|
||||
// Report results
|
||||
results += `\n\n=== Transaction result: ${tx.result.meta.TransactionResult} ===`;
|
||||
results += `\n\n=== NFTs: ${JSON.stringify(nfts, null, 2)} ===`;
|
||||
results += `\n\n=== XRP Balance: ${await client.getXrpBalance(wallet.address)} ===`; // Await here
|
||||
resultField.value = results;
|
||||
|
||||
} catch (error) {
|
||||
console.error("Error minting NFT:", error);
|
||||
results += `\n\n=== Error minting NFT: ${error.message} ===`; // Use error.message
|
||||
resultField.value = results;
|
||||
} finally {
|
||||
if (client && client.isConnected()) { // Check if connected before disconnecting
|
||||
await client.disconnect();
|
||||
}
|
||||
}
|
||||
} // End of mintToken()
|
||||
|
||||
// *******************************************************
|
||||
// ******************** Get NFTs *************************
|
||||
// *******************************************************
|
||||
|
||||
async function getNFTs() {
|
||||
const wallet = xrpl.Wallet.fromSeed(accountSeedField.value);
|
||||
const net = getNet();
|
||||
const client = new xrpl.Client(net);
|
||||
let results = '\n=== Connected. Getting NFTs. ===';
|
||||
resultField.value = results;
|
||||
try {
|
||||
await client.connect();
|
||||
|
||||
const nfts = await client.request({
|
||||
method: "account_nfts",
|
||||
account: wallet.classicAddress,
|
||||
});
|
||||
results = '\n=== NFTs:\n ' + JSON.stringify(nfts, null, 2) + ' ==='; // Consistent formatting
|
||||
resultField.value = results;
|
||||
} catch (error) {
|
||||
console.error("Error getting NFTs:", error);
|
||||
results += `\n\n=== Error getting NFTs: ${error.message} ===`; // User-friendly
|
||||
resultField.value = results;
|
||||
} finally {
|
||||
if (client && client.isConnected()) {
|
||||
await client.disconnect();
|
||||
}
|
||||
}
|
||||
} // End of getNFTs()
|
||||
|
||||
// *******************************************************
|
||||
// ********************** Burn NFT ***********************
|
||||
// *******************************************************
|
||||
|
||||
async function burnNFT() {
|
||||
const wallet = xrpl.Wallet.fromSeed(accountSeedField.value);
|
||||
const net = getNet();
|
||||
const client = new xrpl.Client(net);
|
||||
let results = '\n=== Connected. Burning NFT. ===';
|
||||
resultField.value = results;
|
||||
try {
|
||||
await client.connect();
|
||||
|
||||
// Prepare transaction
|
||||
const transactionBlob = {
|
||||
TransactionType: "NFTokenBurn",
|
||||
Account: wallet.classicAddress,
|
||||
NFTokenID: nftIdField.value,
|
||||
};
|
||||
|
||||
console.log("Burn NFT Transaction Parameters:", transactionBlob); // Log before submit
|
||||
|
||||
// Submit transaction and wait for the results
|
||||
const tx = await client.submitAndWait(transactionBlob, { wallet });
|
||||
const nfts = await client.request({ // Get nfts after burning.
|
||||
method: "account_nfts",
|
||||
account: wallet.classicAddress,
|
||||
});
|
||||
|
||||
results = `\n=== Transaction result: ${tx.result.meta.TransactionResult} ===`;
|
||||
results += '\n\n=== Balance changes: ' +
|
||||
JSON.stringify(xrpl.getBalanceChanges(tx.result.meta), null, 2) + ' ===';
|
||||
results += '\n\n=== NFTs: \n' + JSON.stringify(nfts, null, 2) + ' ===';
|
||||
resultField.value = results;
|
||||
xrpBalanceField.value = (await client.getXrpBalance(wallet.address)); // Await
|
||||
|
||||
} catch (error) {
|
||||
console.error("Error burning NFT:", error);
|
||||
results = `\n\n=== Error burning NFT: ${error.message} ===`; // User friendly
|
||||
resultField.value = results;
|
||||
} finally {
|
||||
if (client && client.isConnected()) {
|
||||
await client.disconnect();
|
||||
}
|
||||
}
|
||||
} // End of burnNFT()
|
||||
153
_code-samples/nft-modular-tutorials/modular-tutorials.css
Normal file
153
_code-samples/nft-modular-tutorials/modular-tutorials.css
Normal file
@@ -0,0 +1,153 @@
|
||||
body {
|
||||
font-family: "Inter", sans-serif;
|
||||
padding: 20px;
|
||||
background: #abe2ff;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
td {
|
||||
padding-left: 25px;
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
input,
|
||||
button {
|
||||
padding: 6px;
|
||||
margin-bottom: 8px;
|
||||
border: none
|
||||
}
|
||||
|
||||
input:read-only {
|
||||
background-color:rgb(11, 96, 132);
|
||||
color:white;
|
||||
border: 0;
|
||||
}
|
||||
|
||||
button {
|
||||
font-weight: bold;
|
||||
font-family: "Work Sans", sans-serif;
|
||||
background-color: #006aff;
|
||||
-webkit-text-fill-color: white;
|
||||
width: 144px;
|
||||
}
|
||||
|
||||
button:hover {
|
||||
background-color: #0555c5;
|
||||
cursor: pointer;
|
||||
}
|
||||
label {
|
||||
font-weight: bold;
|
||||
}
|
||||
td {
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
/* The switch - the box around the slider */
|
||||
.switch {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
width: 30px;
|
||||
height: 16px;
|
||||
}
|
||||
|
||||
/* Hide default HTML checkbox */
|
||||
.switch input {
|
||||
opacity: 0;
|
||||
width: 0;
|
||||
height: 0;
|
||||
}
|
||||
|
||||
/* The slider */
|
||||
.slider {
|
||||
position: absolute;
|
||||
cursor: pointer;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background-color: #ccc;
|
||||
-webkit-transition: .4s;
|
||||
transition: .4s;
|
||||
}
|
||||
|
||||
.slider:before {
|
||||
position: absolute;
|
||||
content: "";
|
||||
height: 13px;
|
||||
width: 13px;
|
||||
left: 4px;
|
||||
bottom: 2px;
|
||||
background-color: white;
|
||||
-webkit-transition: .4s;
|
||||
transition: .4s;
|
||||
}
|
||||
|
||||
input:checked+.slider {
|
||||
background-color: #2196F3;
|
||||
}
|
||||
|
||||
input:focus+.slider {
|
||||
box-shadow: 0 0 1px #2196F3;
|
||||
}
|
||||
|
||||
input:checked+.slider:before {
|
||||
-webkit-transform: translateX(13px);
|
||||
-ms-transform: translateX(13px);
|
||||
transform: translateX(13px);
|
||||
}
|
||||
|
||||
/* Rounded sliders */
|
||||
.slider.round {
|
||||
border-radius: 17px;
|
||||
}
|
||||
|
||||
.slider.round:before {
|
||||
border-radius: 50%;
|
||||
}
|
||||
.tooltip {
|
||||
position: relative;
|
||||
border-bottom: 1px dotted black;
|
||||
}
|
||||
|
||||
.tooltip:before {
|
||||
content: attr(tooltip-data);
|
||||
position: absolute;
|
||||
width: 250px;
|
||||
background-color: #006aff;
|
||||
color: #fff;
|
||||
text-align: center;
|
||||
padding: 15px;
|
||||
line-height: 1.1;
|
||||
border-radius: 5px;
|
||||
z-index: 1;
|
||||
opacity: 0;
|
||||
transition: opacity .5s;
|
||||
bottom: 125%;
|
||||
left: 50%;
|
||||
margin-left: -60px;
|
||||
font-size: 0.70em;
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
.tooltip:after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
bottom: 75%;
|
||||
left: 50%;
|
||||
margin-left: -5px;
|
||||
border-width: 5px;
|
||||
border-style: solid;
|
||||
opacity: 0;
|
||||
transition: opacity .5s;
|
||||
border-color: #000 transparent transparent transparent;
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
.tooltip:hover:before,
|
||||
.tooltip:hover:after {
|
||||
opacity: 1;
|
||||
visibility: visible;
|
||||
}
|
||||
BIN
_code-samples/nft-modular-tutorials/nft-modular-tutorials.zip
Normal file
BIN
_code-samples/nft-modular-tutorials/nft-modular-tutorials.zip
Normal file
Binary file not shown.
36
_code-samples/nft-modular-tutorials/transaction-support.js
Normal file
36
_code-samples/nft-modular-tutorials/transaction-support.js
Normal file
@@ -0,0 +1,36 @@
|
||||
// ****************************************
|
||||
// ********* Configure Amount *************
|
||||
// ****************************************
|
||||
|
||||
function configureAmount() {
|
||||
let amount = '';
|
||||
if (currencyField.value === "XRP" || currencyField.value === "") {
|
||||
if (amountField.value !== '') {
|
||||
amount = amountField.value; // XRP amount should be a string of drops
|
||||
} else {
|
||||
amount = undefined;
|
||||
}
|
||||
} else if (currencyField.value !== "") {
|
||||
amount = {
|
||||
currency: currencyField.value,
|
||||
issuer: issuerField.value,
|
||||
value: amountField.value,
|
||||
};
|
||||
} else {
|
||||
amount = undefined; // Or handle the case where no currency is provided
|
||||
}
|
||||
return amount;
|
||||
}
|
||||
|
||||
// ****************************************
|
||||
// ********* Configure Expiration *********
|
||||
// ****************************************
|
||||
|
||||
function configureExpiration() {
|
||||
let expiration = ""
|
||||
var days = expirationField.value
|
||||
let d = new Date()
|
||||
d.setDate(d.getDate() + parseInt(days))
|
||||
expiration = xrpl.isoTimeToRippleTime(d)
|
||||
return expiration
|
||||
} // End of configureExpiration()
|
||||
328
_code-samples/nft-modular-tutorials/transfer-nfts.html
Normal file
328
_code-samples/nft-modular-tutorials/transfer-nfts.html
Normal file
@@ -0,0 +1,328 @@
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<title>Transfer NFTs</title>
|
||||
<link href='https://fonts.googleapis.com/css?family=Work Sans' rel='stylesheet'>
|
||||
<link href="modular-tutorials.css" rel="stylesheet">
|
||||
<script src='https://unpkg.com/xrpl@4.1.0/build/xrpl-latest.js'></script>
|
||||
<script src="account-support.js"></script>
|
||||
<script src="transaction-support.js"></script>
|
||||
<!-- <script src='send-xrp.js'></script> -->
|
||||
<script src="transfer-nfts.js"></script>
|
||||
<script src="mint-nfts.js"></script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<h1>Transfer NFTs</h1>
|
||||
<form id="theForm">
|
||||
<span class="tooltip" tooltip-data="Choose the XRPL host server for your account.">
|
||||
Choose your ledger instance:
|
||||
</span>
|
||||
|
||||
<input type="radio" id="dn" name="server" value="wss://s.devnet.rippletest.net:51233" checked>
|
||||
<label for="dn">Devnet</label>
|
||||
|
||||
<input type="radio" id="tn" name="server" value="wss://s.altnet.rippletest.net:51233">
|
||||
<label for="tn">Testnet</label>
|
||||
<br /><br />
|
||||
<table>
|
||||
<tr>
|
||||
<td>
|
||||
<button type="button" onClick="getNewAccount1()">Get New Account 1</button>
|
||||
</td>
|
||||
<td>
|
||||
<button type="button" onClick="getAccountFromSeed1()">Get Account 1 From Seed</button>
|
||||
</td>
|
||||
<td>
|
||||
<button type="button" onClick="getNewAccount2()">Get New Account 2</button>
|
||||
</td>
|
||||
<td>
|
||||
<button type="button" onClick="getAccountFromSeed2()">Get Account 2 From Seed</button>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<span class="tooltip" tooltip-data="Arbitrary human-readable name for the account."><label
|
||||
for="account1name">Account 1 Name</label>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="account1name" size="40"></input>
|
||||
</td>
|
||||
<td>
|
||||
<span class="tooltip" tooltip-data="Arbitrary human-readable name for the account.">
|
||||
<label for="account2name">Account 2 Name</label>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="account2name" size="40"></input>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<span class="tooltip" tooltip-data="Identifying address for the account.">
|
||||
<label for="account1address">Account 1 Address</label>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="account1address" size="40"></input>
|
||||
</td>
|
||||
<td>
|
||||
<span class="tooltip" tooltip-data="Identifying address for the account.">
|
||||
<label for="account2address">Account 2 Address</label>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="account2address" size="40"></input>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<span class="tooltip" tooltip-data="Seed for deriving public and private keys for the account.">
|
||||
<label for="account1seed">Account 1 Seed</label>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="account1seed" size="40"></input>
|
||||
</td>
|
||||
<td>
|
||||
<span class="tooltip" tooltip-data="Seed for deriving public and private keys for the account.">
|
||||
<label for="account2seed">Account 2 Seed</label>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="account2seed" size="40"></input>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<hr />
|
||||
<table>
|
||||
<tr valign="top">
|
||||
<td align="right">
|
||||
<span class="tooltip" tooltip-data="Name of the currently selected account.">
|
||||
<label for="accountNameField">Account Name</label>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="accountNameField" size="40" readonly></input>
|
||||
<input type="radio" id="account1" name="accounts" value="account1">
|
||||
<label for="account1">Account 1</label>
|
||||
</td>
|
||||
<td rowspan="4" align="center">
|
||||
<p>
|
||||
<img id="nftImage"
|
||||
src="https://ipfs.io/ipfs/bafybeigjro2d2tc43bgv7e4sxqg7f5jga7kjizbk7nnmmyhmq35dtz6deq"
|
||||
width="150" height="150">
|
||||
</td>
|
||||
</tr>
|
||||
<tr valign="top">
|
||||
<td align="right">
|
||||
<span class="tooltip" tooltip-data="Address of the currently selected account.">
|
||||
<label for="accountAddressField">Account Address</label>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="accountAddressField" size="40" readonly></input>
|
||||
<input type="radio" id="account2" name="accounts" value="account2">
|
||||
<label for="account2">Account 2</label>
|
||||
</td>
|
||||
</tr>
|
||||
<tr valign="top">
|
||||
<td align="right">
|
||||
<span class="tooltip" tooltip-data="Seed of the currently selected account.">
|
||||
<label for="accountSeedField">Account Seed</label>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="accountSeedField" size="40" readonly></input>
|
||||
<br>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="right">
|
||||
<span class="tooltip" tooltip-data="XRP balance for the currently selected account.">
|
||||
<label for="xrpBalanceField">XRP Balance</label>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="xrpBalanceField" size="40" readonly></input>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
</td>
|
||||
<td>
|
||||
</td>
|
||||
<td>
|
||||
<span class="tooltip" tooltip-data="URL to the stored NFT.">
|
||||
<label for="nftURLfield">NFT URL</label>
|
||||
</span>
|
||||
<input type="text" id="nftURLfield" size="30"
|
||||
placeholder="https://ipfs.io/ipfs/bafybeigjro2d2tc43bgv7e4sxqg7f5jga7kjizbk7nnmmyhmq35dtz6deq"></input>
|
||||
<br />
|
||||
<p id="error-message"></p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="right" >
|
||||
<span class="tooltip" tooltip-data="Currency for the offer.">
|
||||
<label for="currencyField">Currency</label>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="currencyField" size="40"></input>
|
||||
<br>
|
||||
</td>
|
||||
<td align="center" valign="top">
|
||||
<button type="button" onClick="getNFTs()">Get NFTs</button>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="right">
|
||||
<span class="tooltip" tooltip-data="Issuer of the currency used.">
|
||||
<label for="issuerField">Issuer</label>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="issuerField" size="40"></input>
|
||||
<br>
|
||||
</td>
|
||||
<td>
|
||||
<button type="button" onClick="createSellOffer()">Create Sell Offer</button>
|
||||
|
||||
<button type="button" onClick="createBuyOffer()">Create Buy Offer</button>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="right">
|
||||
<span class="tooltip" tooltip-data="Amount of XRP to send.">
|
||||
<label for="amountField">Amount</label>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="amountField" size="40"></input>
|
||||
<br>
|
||||
</td>
|
||||
<td align="left" valign="top">
|
||||
<button type="button" onClick="acceptSellOffer()">Accept Sell Offer</button>
|
||||
|
||||
<button type="button" onClick="acceptBuyOffer()">Accept Buy Offer</button>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="right">
|
||||
<span class="tooltip" tooltip-data="Destination account address where XRP is sent.">
|
||||
<label for="destinationField">Destination</label>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="destinationField" size="40"></input>
|
||||
<br>
|
||||
</td>
|
||||
<td align="left" valign="top">
|
||||
<button type="button" onClick="getOffers()" width="40">Get Offers</button>
|
||||
<button type="button" onClick="cancelOffer()">Cancel Offer</button>
|
||||
</td>
|
||||
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="right">
|
||||
<span class="tooltip" tooltip-data="Number of days the offer is valid.">
|
||||
<label for="expirationField">Expiration (days)</label>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="expirationField" size="40"></input>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="right">
|
||||
<span class="tooltip" tooltip-data="NFT ID code, used to identify the token after it's minted.">
|
||||
<label for="nftIdField">NFT ID</label>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="nftIdField" size="40"></input>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="right">
|
||||
<span class="tooltip" tooltip-data="NFT Offer ID code, used to identify an offer to sell or buy an NFT.">
|
||||
<label for="nftOfferIdField">NFT Offer ID</label>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="nftOfferIdField" size="40"></input>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="right">
|
||||
<span class="tooltip" tooltip-data="Account address of the Owner of an NFT offered to sell or buy.">
|
||||
<label for="nftOwnerField">NFT Owner Address</label>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="nftOwnerField" size="40"></input>
|
||||
</td>
|
||||
</tr>
|
||||
<tr valign="top">
|
||||
<td colspan="2">
|
||||
<p align="left">
|
||||
<textarea id="resultField" cols="75" rows="20"></textarea>
|
||||
</p>
|
||||
</td>
|
||||
<td align="left" valign="top">
|
||||
<button type="button" onClick="gatherAccountInfo()">Gather Account Info</button><br />
|
||||
<button type="button" onClick="distributeAccountInfo()">Distribute Account Info</button>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</form>
|
||||
</body>
|
||||
<script>
|
||||
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
const imageURLInput = document.getElementById('nftURLfield'); // Correct ID to nftURLfield
|
||||
const displayImage = document.getElementById('nftImage');
|
||||
const loadButton = document.getElementById('showNFTbutton');
|
||||
const errorMessage = document.getElementById('error-message');
|
||||
|
||||
if (imageURLInput) {
|
||||
imageURLInput.addEventListener('change', () => {
|
||||
const newURL = imageURLInput.value;
|
||||
displayImage.src = ''; // Clear previous image
|
||||
errorMessage.style.display = 'none';
|
||||
try {
|
||||
new URL(newURL);
|
||||
} catch (_) {
|
||||
errorMessage.textContent = 'Invalid URL. Please enter a valid URL, including "https://" or "http://".';
|
||||
errorMessage.style.display = 'block';
|
||||
return;
|
||||
}
|
||||
displayImage.onload = () => {
|
||||
// Image loaded. You might add a console log here, or update UI.
|
||||
console.log(`Image loaded from: ${newURL}`);
|
||||
};
|
||||
displayImage.onerror = () => {
|
||||
errorMessage.textContent = 'Error loading image from the provided URL.';
|
||||
errorMessage.style.display = 'block';
|
||||
displayImage.src = ''; // Clear the image on error
|
||||
};
|
||||
displayImage.src = newURL; // Load the image
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
const radioButtons = document.querySelectorAll('input[type="radio"]');
|
||||
radioButtons.forEach(radio => {
|
||||
radio.addEventListener('change', function () {
|
||||
if (this.value === 'account1') {
|
||||
populate1()
|
||||
} else if (this.value === 'account2') {
|
||||
populate2()
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
</html>
|
||||
339
_code-samples/nft-modular-tutorials/transfer-nfts.js
Normal file
339
_code-samples/nft-modular-tutorials/transfer-nfts.js
Normal file
@@ -0,0 +1,339 @@
|
||||
|
||||
// *********************************************************
|
||||
// *************** Create Sell Offer ***********************
|
||||
// *********************************************************
|
||||
|
||||
async function createSellOffer() {
|
||||
const wallet = xrpl.Wallet.fromSeed(accountSeedField.value);
|
||||
let results = '\nCreating sell offer...';
|
||||
resultField.value = results;
|
||||
|
||||
try {
|
||||
const client = new xrpl.Client(getNet());
|
||||
await client.connect();
|
||||
try {
|
||||
const destination = destinationField.value || undefined;
|
||||
const expiration = expirationField.value ? configureExpiration() : undefined;
|
||||
|
||||
const transactionJson = {
|
||||
TransactionType: "NFTokenCreateOffer",
|
||||
Account: wallet.classicAddress,
|
||||
NFTokenID: nftIdField.value,
|
||||
Flags: 1,
|
||||
};
|
||||
|
||||
const amount = configureAmount();
|
||||
if (amount) { // Only add Amount if it's defined
|
||||
transactionJson.Amount = amount;
|
||||
} else {
|
||||
console.warn("Amount is undefined. Sell offer might be invalid.");
|
||||
results += "\nWarning: Amount is undefined. Sell offer might be invalid, unless you plan to give away the NFT.";
|
||||
resultField.value = results;
|
||||
}
|
||||
|
||||
if (expiration) {
|
||||
transactionJson.Expiration = expiration;
|
||||
}
|
||||
if (destination) {
|
||||
transactionJson.Destination = destination;
|
||||
}
|
||||
|
||||
const tx = await client.submitAndWait(transactionJson, { wallet });
|
||||
results += `\nSell offer created successfully!\nTransaction Hash: ${tx.result.hash}\nEngine Result: ${tx.result.engine_result}`;
|
||||
resultField.value = results;
|
||||
|
||||
} finally {
|
||||
client.disconnect();
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error creating sell offer:", error);
|
||||
results = `\nError: ${error.message || error}`;
|
||||
resultField.value = results;
|
||||
}
|
||||
}// End of createSellOffer()
|
||||
|
||||
// *******************************************************
|
||||
// ***************** Create Buy Offer ********************
|
||||
// *******************************************************
|
||||
|
||||
async function createBuyOffer() {
|
||||
const wallet = xrpl.Wallet.fromSeed(accountSeedField.value);
|
||||
let net = getNet();
|
||||
const client = new xrpl.Client(net);
|
||||
await client.connect();
|
||||
let results = '\n=== Connected. Creating buy offer. ===';
|
||||
resultField.value = results;
|
||||
|
||||
try {
|
||||
// Use the external configureAmount() function
|
||||
let amount = configureAmount();
|
||||
// Use the external configureExpiration() function
|
||||
let expiration = configureExpiration(); // This will return a number or an empty string from the original logic
|
||||
|
||||
let transactionJson = {
|
||||
"TransactionType": "NFTokenCreateOffer",
|
||||
"Account": wallet.classicAddress,
|
||||
"Owner": nftOwnerField.value,
|
||||
"NFTokenID": nftIdField.value,
|
||||
"Flags": 0, // Ensure no tfSellNFToken flag for a buy offer
|
||||
};
|
||||
|
||||
// Only add Amount if it's defined (not undefined or an empty string)
|
||||
if (amount !== undefined && amount !== '') {
|
||||
transactionJson.Amount = amount;
|
||||
} else {
|
||||
results += "\nError: Amount field is required for a buy offer.";
|
||||
resultField.value = results;
|
||||
client.disconnect();
|
||||
return;
|
||||
}
|
||||
|
||||
if (destinationField.value !== '') {
|
||||
transactionJson.Destination = destinationField.value;
|
||||
}
|
||||
|
||||
// Only add Expiration if it's not an empty string
|
||||
if (expiration > 0) {
|
||||
transactionJson.Expiration = expiration;
|
||||
}
|
||||
|
||||
const tx = await client.submitAndWait(transactionJson, { wallet: wallet });
|
||||
|
||||
results += "\n\n=== Sell Offers ===\n";
|
||||
let nftSellOffers;
|
||||
try {
|
||||
nftSellOffers = await client.request({
|
||||
method: "nft_sell_offers",
|
||||
nft_id: nftIdField.value
|
||||
});
|
||||
} catch (err) {
|
||||
nftSellOffers = "=== No sell offers. ===";
|
||||
}
|
||||
results += JSON.stringify(nftSellOffers, null, 2);
|
||||
results += "\n\n=== Buy Offers ===\n";
|
||||
let nftBuyOffers;
|
||||
try {
|
||||
nftBuyOffers = await client.request({
|
||||
method: "nft_buy_offers",
|
||||
nft_id: nftIdField.value
|
||||
});
|
||||
results += JSON.stringify(nftBuyOffers, null, 2);
|
||||
} catch (err) {
|
||||
results += "=== No buy offers. ===";
|
||||
}
|
||||
|
||||
// Check transaction results -------------------------------------------------
|
||||
results += "\n\n=== Transaction result:\n" +
|
||||
JSON.stringify(tx.result.meta.TransactionResult, null, 2);
|
||||
results += "\n\n=== Balance changes:\n" +
|
||||
JSON.stringify(xrpl.getBalanceChanges(tx.result.meta), null, 2);
|
||||
resultField.value = results;
|
||||
|
||||
} catch (error) {
|
||||
console.error('Error creating buy offer:', error);
|
||||
results += "\n\n=== Error: " + error;
|
||||
resultField.value = results;
|
||||
} finally {
|
||||
client.disconnect();
|
||||
}
|
||||
}// End of createBuyOffer()
|
||||
|
||||
// *******************************************************
|
||||
// ******************** Cancel Offer *********************
|
||||
// *******************************************************
|
||||
|
||||
async function cancelOffer() {
|
||||
const wallet = xrpl.Wallet.fromSeed(accountSeedField.value)
|
||||
let net = getNet()
|
||||
const client = new xrpl.Client(net)
|
||||
await client.connect()
|
||||
let results = "\n=== Connected. Cancelling offer. ==="
|
||||
resultField.value = results
|
||||
|
||||
const tokenOfferIDs = [nftOfferIdField.value]
|
||||
|
||||
// Prepare transaction -------------------------------------------------------
|
||||
const transactionJson = {
|
||||
"TransactionType": "NFTokenCancelOffer",
|
||||
"Account": wallet.classicAddress,
|
||||
"NFTokenOffers": tokenOfferIDs
|
||||
}
|
||||
// Submit transaction --------------------------------------------------------
|
||||
const tx = await client.submitAndWait(transactionJson, { wallet })
|
||||
|
||||
results = "\n\n=== Sell Offers===\n"
|
||||
let nftSellOffers
|
||||
try {
|
||||
nftSellOffers = await client.request({
|
||||
method: "nft_sell_offers",
|
||||
nft_id: nftIdField.value
|
||||
})
|
||||
} catch (err) {
|
||||
nftSellOffers = '=== No sell offers. ===\n'
|
||||
}
|
||||
results += JSON.stringify(nftSellOffers, null, 2)
|
||||
results += "\n\n=== Buy Offers ===\n"
|
||||
let nftBuyOffers
|
||||
try {
|
||||
nftBuyOffers = await client.request({
|
||||
method: "nft_buy_offers",
|
||||
nft_id: nftIdField.value
|
||||
})
|
||||
|
||||
} catch (err) {
|
||||
nftBuyOffers = '=== No buy offers. ==='
|
||||
}
|
||||
results += JSON.stringify(nftBuyOffers, null, 2)
|
||||
resultField.value += results
|
||||
|
||||
// Check transaction results -------------------------------------------------
|
||||
|
||||
results = "\n=== Transaction result:\n" +
|
||||
JSON.stringify(tx.result.meta.TransactionResult, null, 2)
|
||||
results += "\n\n=== Balance changes:\n" +
|
||||
JSON.stringify(xrpl.getBalanceChanges(tx.result.meta), null, 2)
|
||||
resultField.value += results
|
||||
|
||||
client.disconnect() // End of cancelOffer()
|
||||
}
|
||||
|
||||
// *******************************************************
|
||||
// ******************** Get Offers ***********************
|
||||
// *******************************************************
|
||||
|
||||
async function getOffers() {
|
||||
const wallet = xrpl.Wallet.fromSeed(accountSeedField.value)
|
||||
let net = getNet()
|
||||
const client = new xrpl.Client(net)
|
||||
await client.connect()
|
||||
|
||||
let results = '\nConnected. Getting offers...'
|
||||
resultField.value = results
|
||||
|
||||
// --- Sell Offers ---
|
||||
results += '\n\n=== Sell Offers ===\n'
|
||||
let nftSellOffers
|
||||
try {
|
||||
nftSellOffers = await client.request({
|
||||
method: "nft_sell_offers",
|
||||
nft_id: nftIdField.value
|
||||
})
|
||||
} catch (err) {
|
||||
nftSellOffers = 'No sell offers found for this NFT ID.'
|
||||
}
|
||||
results += JSON.stringify(nftSellOffers, null, 2)
|
||||
resultField.value = results
|
||||
|
||||
// --- Buy Offers ---
|
||||
results = '\n\n=== Buy Offers ===\n'
|
||||
let nftBuyOffers
|
||||
try {
|
||||
nftBuyOffers = await client.request({
|
||||
method: "nft_buy_offers",
|
||||
nft_id: nftIdField.value
|
||||
})
|
||||
} catch (err) {
|
||||
// Log the actual error for debugging
|
||||
nftBuyOffers = 'No buy offers found for this NFT ID.' // More descriptive
|
||||
}
|
||||
results += JSON.stringify(nftBuyOffers, null, 2) // Append the JSON string
|
||||
resultField.value += results // Update the display with buy offers
|
||||
|
||||
client.disconnect()
|
||||
}// End of getOffers()
|
||||
|
||||
// *******************************************************
|
||||
// ****************** Accept Sell Offer ******************
|
||||
// *******************************************************
|
||||
|
||||
async function acceptSellOffer() {
|
||||
const wallet = xrpl.Wallet.fromSeed(accountSeedField.value)
|
||||
let net = getNet()
|
||||
const client = new xrpl.Client(net)
|
||||
try {
|
||||
await client.connect()
|
||||
let results = '\n=== Connected. Accepting sell offer. ===\n\n'
|
||||
resultField.value = results
|
||||
|
||||
// Prepare transaction -------------------------------------------------------
|
||||
const transactionJson = {
|
||||
"TransactionType": "NFTokenAcceptOffer",
|
||||
"Account": wallet.classicAddress,
|
||||
"NFTokenSellOffer": nftOfferIdField.value,
|
||||
}
|
||||
// Submit transaction --------------------------------------------------------
|
||||
const tx = await client.submitAndWait(transactionJson, { wallet: wallet })
|
||||
const nfts = await client.request({
|
||||
method: "account_nfts",
|
||||
account: wallet.classicAddress
|
||||
})
|
||||
|
||||
// Check transaction results -------------------------------------------------
|
||||
|
||||
xrpBalanceField.value = (await client.getXrpBalance(wallet.address))
|
||||
|
||||
|
||||
results += '=== Transaction result:\n'
|
||||
results += JSON.stringify(tx.result.meta.TransactionResult, null, 2)
|
||||
results += '\n=== Balance changes:'
|
||||
results += JSON.stringify(xrpl.getBalanceChanges(tx.result.meta), null, 2)
|
||||
results += JSON.stringify(nfts, null, 2)
|
||||
resultField.value += results
|
||||
} catch (error) {
|
||||
console.error('Error accepting sell offer:', error)
|
||||
resultField.value = `Error: ${error.message || error}`
|
||||
} finally {
|
||||
client.disconnect()
|
||||
}
|
||||
}// End of acceptSellOffer()
|
||||
|
||||
// *******************************************************
|
||||
// ******************* Accept Buy Offer ******************
|
||||
// *******************************************************
|
||||
|
||||
async function acceptBuyOffer() {
|
||||
const wallet = xrpl.Wallet.fromSeed(accountSeedField.value);
|
||||
let net = getNet();
|
||||
const client = new xrpl.Client(net);
|
||||
let results = '\n=== Connected. Accepting buy offer. ==='; // Declare results locally
|
||||
|
||||
try {
|
||||
await client.connect();
|
||||
resultField.value = results; // Update UI after connection
|
||||
|
||||
// Prepare transaction -------------------------------------------------------
|
||||
const transactionJson = {
|
||||
"TransactionType": "NFTokenAcceptOffer",
|
||||
"Account": wallet.classicAddress,
|
||||
"NFTokenBuyOffer": nftOfferIdField.value
|
||||
};
|
||||
|
||||
// Submit transaction --------------------------------------------------------
|
||||
const tx = await client.submitAndWait(transactionJson, { wallet: wallet });
|
||||
|
||||
const nfts = await client.request({
|
||||
method: "account_nfts",
|
||||
account: wallet.classicAddress
|
||||
});
|
||||
|
||||
results += JSON.stringify(nfts, null, 2);
|
||||
resultField.value = results;
|
||||
|
||||
// Check transaction results -------------------------------------------------
|
||||
results += "\n\nTransaction result:\n" +
|
||||
JSON.stringify(tx.result.meta.TransactionResult, null, 2);
|
||||
results += "\nBalance changes:\n" +
|
||||
JSON.stringify(xrpl.getBalanceChanges(tx.result.meta), null, 2);
|
||||
xrpBalanceField.value = (await client.getXrpBalance(wallet.address));
|
||||
resultField.value = results;
|
||||
|
||||
} catch (error) {
|
||||
console.error('Error in acceptBuyOffer:', error); // Log the full error
|
||||
results = `\n=== Error accepting buy offer: ${error.message || 'Unknown error'} ===`;
|
||||
resultField.value = results;
|
||||
} finally {
|
||||
if (client && client.isConnected()) {
|
||||
client.disconnect();
|
||||
}
|
||||
}
|
||||
} // End of acceptBuyOffer()
|
||||
@@ -27,8 +27,8 @@ async function mintToken() {
|
||||
// ----------------------------------------------------- Submit signed blob
|
||||
const tx = await client.submitAndWait(transactionJson, { wallet: standby_wallet} )
|
||||
const nfts = await client.request({
|
||||
method: "account_nfts",
|
||||
account: standby_wallet.classicAddress
|
||||
"method": "account_nfts",
|
||||
"account": standby_wallet.classicAddress
|
||||
})
|
||||
|
||||
// ------------------------------------------------------- Report results
|
||||
|
||||
@@ -37,7 +37,11 @@ const args = parseArgs(process.argv.slice(2), {
|
||||
|
||||
function _pretty(message, color) {
|
||||
if (!args.raw) {
|
||||
console.log(color, message)
|
||||
if (color) {
|
||||
console.log(color,message)
|
||||
} else {
|
||||
console.log(message)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -60,4 +64,4 @@ if (args.json) {
|
||||
} else {
|
||||
rawJson = fs.readFileSync(args.filename, 'utf8')
|
||||
main(rawJson, args.verbose)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,10 +7,9 @@
|
||||
"big-integer": "^1.6.52",
|
||||
"buffer": "^6.0.3",
|
||||
"decimal.js": "^10.4.3",
|
||||
"fs": "^0.0.1-security",
|
||||
"minimist": "^1.2.7",
|
||||
"ripple-address-codec": "^5.0.0",
|
||||
"xrpl": "^4.0.0"
|
||||
"xrpl": "^4.2.5"
|
||||
},
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
|
||||
@@ -6,7 +6,7 @@ you can use to verify the behavior of the transaction serialization code.
|
||||
For example (starting from the `tx-serialization/js/` dir above this one):
|
||||
|
||||
```bash
|
||||
$ node index.js -f test-cases/tx2.json | \
|
||||
$ node index.js -rf test-cases/tx2.json | \
|
||||
diff - test-cases/tx2-binary.txt
|
||||
```
|
||||
|
||||
@@ -46,7 +46,7 @@ CDC63E1DEE7FE3744630440220143759437C04F7B61F012563AFE90D8DAFC46E86035E1D965A9CED
|
||||
For a friendlier display, you could pipe the output of the serializer to a file and use a visual tool like [Meld](http://meldmerge.org/) that shows intra-line differences:
|
||||
|
||||
```bash
|
||||
$ cat test-cases/tx1.json | sed -e 's/"Fee": "10"/"Fee": "100"/' | node index.js --stdin > /tmp/tx1-modified.txt && meld /tmp/tx1-modified.txt test-cases/tx1-binary.txt
|
||||
$ cat test-cases/tx1.json | sed -e 's/"Fee": "10"/"Fee": "100"/' | node index.js --raw --stdin > /tmp/tx1-modified.txt && meld /tmp/tx1-modified.txt test-cases/tx1-binary.txt
|
||||
```
|
||||
|
||||

|
||||
|
||||
@@ -92,7 +92,7 @@ class TxSerializer {
|
||||
_decodeAddress(address) {
|
||||
const decoded = codec.decodeChecked(address)
|
||||
if (decoded[0] === 0 && decoded.length === 21) {
|
||||
return decoded.slice(1)
|
||||
return Buffer.from(decoded.slice(1))
|
||||
}
|
||||
|
||||
throw new Error("Not an AccountID!")
|
||||
@@ -161,7 +161,7 @@ class TxSerializer {
|
||||
const byte2 = this.uint8ToBytes(typeCode)
|
||||
const byte3 = this.uint8ToBytes(fieldCode)
|
||||
|
||||
return "" + byte1 + byte2 + byte3 //TODO: bytes is python function
|
||||
return "" + byte1 + byte2 + byte3
|
||||
}
|
||||
}
|
||||
|
||||
@@ -681,9 +681,8 @@ class TxSerializer {
|
||||
fieldsAsBytes.push(fieldBytes)
|
||||
}
|
||||
}
|
||||
|
||||
return fieldsAsBytes.join('')
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = TxSerializer
|
||||
module.exports = TxSerializer
|
||||
|
||||
@@ -11,9 +11,9 @@ author: Rome Reginelli
|
||||
---
|
||||
# Dev Portal Adds rippled APIs
|
||||
|
||||
Today, the [Ripple Dev Portal](https://developers.ripple.com/) gets a big boost of content and usability. The new additions to our development portal include thorough and tested documentation of all the public API methods for our core server software, ‘rippled’, alongside a host of improvements in styling and formatting, as well as new introductory material to give you direction in navigating the sea of Ripple technology.
|
||||
Today, the Ripple Dev Portal gets a big boost of content and usability. The new additions to our development portal include thorough and tested documentation of all the public API methods for our core server software, ‘rippled’, alongside a host of improvements in styling and formatting, as well as new introductory material to give you direction in navigating the sea of Ripple technology.
|
||||
|
||||
This update brings very crucial content into the fold of documentation that's thorough, complete, and software-tested. Today, you can access [full specs and usage information for all 20+ public methods in the rippled WebSocket API](https://developers.ripple.com/rippled-api.html).
|
||||
This update brings very crucial content into the fold of documentation that's thorough, complete, and software-tested. Today, you can access [full specs and usage information for all 20+ public methods in the rippled WebSocket API](/docs/references/http-websocket-apis/public-api-methods).
|
||||
|
||||
<!-- BREAK -->
|
||||
|
||||
|
||||
@@ -8,8 +8,10 @@ markdown:
|
||||
---
|
||||
# Do You Have What It Takes to Be a Gateway?
|
||||
|
||||
We're proud to announce the first release of [our new Gateway Guide](https://developers.ripple.com/become-an-xrp-ledger-gateway.html), a comprehensive manual to operating a gateway in the Ripple network. Whether you're trying to understand [how a gateway makes revenue](https://developers.ripple.com/become-an-xrp-ledger-gateway.html#fees-and-revenue-sources), or how to use the [authorized accounts](https://developers.ripple.com/become-an-xrp-ledger-gateway.html#authorized-trust-lines) feature, or even just [what a warm wallet is](https://developers.ripple.com/issuing-and-operational-addresses.html), the gateway guide has you covered.
|
||||
We're proud to announce the first release of our new Gateway Guide, a comprehensive manual to operating a gateway in the Ripple network. Whether you're trying to understand how a gateway makes revenue, or how to use the authorized accounts feature, or even just what a warm wallet is, the gateway guide has you covered.
|
||||
|
||||
The guide comes with step-by-step, diagrammed explanations of typical gateway operations, a hefty [list of precautions](https://developers.ripple.com/become-an-xrp-ledger-gateway.html#precautions) to make your gateway safer, and concrete examples of all the API calls you need to perform in order to get your gateway accounts set up and secure.
|
||||
The guide comes with step-by-step, diagrammed explanations of typical gateway operations, a hefty list of precautions to make your gateway safer, and concrete examples of all the API calls you need to perform in order to get your gateway accounts set up and secure.
|
||||
|
||||
We're proud of all the work we've done to make the business of running a gateway easier, but there's still more work to do. If you have any questions, comments, or ideas, please send feedback to <developers@ripple.com> - or post it on our forums. We'd love to hear from you!
|
||||
|
||||
> _Editor's note, 2025: This guide is now obsolete and removed. For the nearest modern equivalent, see the [Stablecoin Issuer use case](/docs/use-cases/tokenization/stablecoin-issuer)._
|
||||
|
||||
@@ -20,7 +20,7 @@ The Data API also includes a lot of new capabilities, including:
|
||||
- a new endpoint to show account balance changes
|
||||
- new metrics in transaction stats
|
||||
|
||||
We are making these changes quickly and are focusing our resources on building out and testing new endpoints. Documentation for the Data API will soon be available on [ripple.com/build](http://ripple.com/build). The API will live at [data.ripple.com](http://data.ripple.com). In the meantime, you can look through the [Data API in GitHub](https://github.com/ripple/rippled-historical-database/blob/develop/README.md).
|
||||
We are making these changes quickly and are focusing our resources on building out and testing new endpoints. Documentation for the Data API will soon be available on `ripple.com/build`. The API will live at `data.ripple.com`. In the meantime, you can look through the [Data API in GitHub](https://github.com/ripple/rippled-historical-database/blob/develop/README.md).
|
||||
|
||||
Because we are pulling all of the data endpoints under one API, we are shutting down some of our underutilized endpoints that are relying on infrastructure we are not moving forward with. The first shutdown will be CouchDB on August 19th, which we used early on for Ripple Charts. We are replacing some of the endpoints that hit CouchDB in the Data API, but other, less frequently used calls are being removed. In the next few months, we will also be shutting down the Ripple Charts API and replacing aspects of that by expanding the Data API. The Historical Database API – version one – will live in parallel to the Data API as we make this transition. It will be deprecated by the end of the year.
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ markdown:
|
||||
|
||||
At Ripple Labs, our goal is to expand the size and diversity of the Ripple consensus network by enabling people to easily run rippled validators and understand how those validators perform. We aim to create a network where validating participants are well known and respected by gathering and publicizing identity information of validators in addition to performance statistics.
|
||||
|
||||
Today, we are excited to announce the launch of the Ripple Validator Registry at [xrpcharts.ripple.com/#/validators](https://xrpcharts.ripple.com/#/validators). The Validator Registry gathers and publishes data for all network validators, enabling rippled operators to determine which validators to trust. An [http-based API](https://data.ripple.com/v2/network/validators) is also available for dynamically constructing rippled configurations.
|
||||
Today, we are excited to announce the launch of the Ripple Validator Registry at `xrpcharts.ripple.com/#/validators`. The Validator Registry gathers and publishes data for all network validators, enabling rippled operators to determine which validators to trust. An http-based API is also available for dynamically constructing rippled configurations. _[2025 Update: See <https://livenet.xrpl.org/network/validators> for the modern equivalent of the validator registry.]_
|
||||
|
||||
|
||||
## Build a UNL
|
||||
@@ -25,6 +25,6 @@ The Validator Registry provides several metrics for each validator based on upti
|
||||
- disagreement - the percentage of ledgers validated by the validator that did not pass consensus
|
||||
|
||||
### Identity
|
||||
Network participants are unlikely to trust validators without knowing who is operating them. To address this concern, validator operators can associate their validator with a web domain that they operate by following the steps on the [Ripple Dev Portal](https://ripple.com/build/rippled-apis/rippled-setup/#domain-verification). The Validator Registry verifies these domains and lists them with the validators.
|
||||
Network participants are unlikely to trust validators without knowing who is operating them. To address this concern, validator operators can associate their validator with a web domain that they operate by following the steps for [Domain Verification](https://xrpl.org/docs/references/xrp-ledger-toml#domain-verification). The Validator Registry verifies these domains and lists them with the validators.
|
||||
|
||||
As the consensus network continues to grow, we hope the Validator Registry plays a key role in decentralizing and strengthening the network through open data.
|
||||
|
||||
@@ -12,14 +12,14 @@ markdown:
|
||||
|
||||
The Data team is proud to announce the release of the [Ripple Data API v2.2](https://github.com/ripple/rippled-historical-database/releases/tag/v2.2.0)! This release includes lots of new features, including a total of 15 new methods, improvements in data quality, and documentation.
|
||||
|
||||
One of the biggest changes in the new version is the incorporation of data relating to the Ripple network itself. This includes expanded information on [validator reports](https://ripple.com/build/data-api-v2/#get-daily-validator-reports), [network topology](https://ripple.com/build/data-api-v2/#get-topology), and the [XRP transaction costs](https://ripple.com/build/data-api-v2/#get-transaction-costs) currently being paid to the network. You can interact with all of the new methods using our [Data API Tool](https://ripple.com/build/data-api-tool/).
|
||||
One of the biggest changes in the new version is the incorporation of data relating to the Ripple network itself. This includes expanded information on validator reports, network topology, and the XRP transaction costs currently being paid to the network. You can interact with all of the new methods using our Data API Tool.
|
||||
|
||||
Also part of the new release is a method to calculate the [distribution of XRP](https://ripple.com/build/data-api-v2/#get-xrp-distribution) from Ripple (the company) to others, along with the total amount of XRP in existence. The [XRP Portal](https://ripple.com/xrp-portal/) is already using the new method to report the most recent totals automatically.
|
||||
Also part of the new release is a method to calculate the distribution of XRP from Ripple (the company) to others, along with the total amount of XRP in existence. The XRP Portal is already using the new method to report the most recent totals automatically.
|
||||
|
||||
For more information, check out the following resources:
|
||||
|
||||
* [Data API Docs in the Ripple Developer Center](https://ripple.com/build/data-api-v2/)
|
||||
* [Data API source code](https://github.com/ripple/rippled-historical-database)
|
||||
* [Data visualizations on Ripple Charts](https://xrpcharts.ripple.com/)
|
||||
|
||||
_\[Update: Data API docs and Data visualizations on Ripple Charts are no longer available. The links have been removed.\]_
|
||||
|
||||
We look forward to seeing what you developers can do with all this data!
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user