From 2032749af0c0169ea59bade0cadc878654c1370f Mon Sep 17 00:00:00 2001 From: mDuo13 Date: Thu, 14 Dec 2023 16:37:04 -0800 Subject: [PATCH 01/25] Update AMM discounted trading fee --- .../tokens/decentralized-exchange/automated-market-makers.md | 2 +- .../public-api-methods/path-and-order-book-methods/amm_info.md | 2 +- .../references/protocol/ledger-data/ledger-entry-types/amm.md | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/content/concepts/tokens/decentralized-exchange/automated-market-makers.md b/content/concepts/tokens/decentralized-exchange/automated-market-makers.md index ca5fdc7bed..472ebd3491 100644 --- a/content/concepts/tokens/decentralized-exchange/automated-market-makers.md +++ b/content/concepts/tokens/decentralized-exchange/automated-market-makers.md @@ -70,7 +70,7 @@ To vote, a liquidity provider sends an [AMMVote transaction][]. Whenever anyone ### Auction Slot -Unlike any previous Automated Market Makers, the XRP Ledger's AMM design has an _auction slot_ that a liquidity provider can bid on to get a discount on the trading fee for a 24-hour period. The bid must be paid in LP Tokens, which are returned to the AMM. No more than one account can hold the auction slot at a time, but the bidder can name up to 4 more accounts to also receive the discount. There is no minimum bid, but if the slot is currently occupied then you must outbid the current slot holder to displace them. If someone displaces you, you get part of your bid back depending on how much time remains. As long as you hold an active auction slot, you pay a discounted trading fee of 0% when making trades against that AMM. +Unlike any previous Automated Market Makers, the XRP Ledger's AMM design has an _auction slot_ that a liquidity provider can bid on to get a discount on the trading fee for a 24-hour period. The bid must be paid in LP Tokens, which are returned to the AMM. No more than one account can hold the auction slot at a time, but the bidder can name up to 4 more accounts to also receive the discount. There is no minimum bid, but if the slot is currently occupied then you must outbid the current slot holder to displace them. If someone displaces you, you get part of your bid back depending on how much time remains. As long as you hold an active auction slot, you pay a discounted trading fee equal to 1/10 (one tenth) of the normal trading fee when making trades against that AMM. With any AMM, when the price of its assets shifts significantly in external markets, traders can use arbitrage to profit off the AMM, which results in a loss for liquidity providers. The auction mechanism is intended to return more of that value to liquidity providers and more quickly bring the AMM's prices back into balance with external markets. diff --git a/content/references/http-websocket-apis/public-api-methods/path-and-order-book-methods/amm_info.md b/content/references/http-websocket-apis/public-api-methods/path-and-order-book-methods/amm_info.md index 4f569cfb59..00042ff47c 100644 --- a/content/references/http-websocket-apis/public-api-methods/path-and-order-book-methods/amm_info.md +++ b/content/references/http-websocket-apis/public-api-methods/path-and-order-book-methods/amm_info.md @@ -226,7 +226,7 @@ The `auction_slot` field of the `amm` object describes the current auction slot |------------------|---------------------|-------------| | `account` | String | The [Address][] of the account that owns the auction slot. | | `auth_accounts` | Array | A list of additional accounts that the auction slot holder has designated as being eligible of the discounted trading fee. Each member of this array is an object with one field, `account`, containing the address of the designated account. | -| `discounted_fee` | Number | The discounted trading fee that applies to the auction slot holder, and any eligible accounts, when trading against this AMM. This is always 0. | +| `discounted_fee` | Number | The discounted trading fee that applies to the auction slot holder, and any eligible accounts, when trading against this AMM. This is 1/10 of the AMM's normal trading fee. | | `expiration` | String | The ISO 8601 UTC timestamp after which this auction slot expires. After expired, the auction slot does not apply (but the data can remain in the ledger until another transaction replaces it or cleans it up). | | `price` | [Currency Amount][] | The amount, in LP Tokens, that the auction slot holder paid to win the auction slot. This affects the price to outbid the current slot holder. | | `time_interval` | Number | The current 72-minute time interval this auction slot is in, from 0 to 19. The auction slot expires after 24 hours (20 intervals of 72 minutes) and affects the cost to outbid the current holder and how much the current holder is refunded if someone outbids them. | diff --git a/content/references/protocol/ledger-data/ledger-entry-types/amm.md b/content/references/protocol/ledger-data/ledger-entry-types/amm.md index f8743cb65b..6f7a599a06 100644 --- a/content/references/protocol/ledger-data/ledger-entry-types/amm.md +++ b/content/references/protocol/ledger-data/ledger-entry-types/amm.md @@ -89,7 +89,7 @@ The `AuctionSlot` field contains an object with the following nested fields: |:----------------|:--------------------|:------------------|:----------|:--| | `Account` | String - Address | AccountID | Yes | The current owner of this auction slot. | | `AuthAccounts` | Array | STArray | No | A list of at most 4 additional accounts that are authorized to trade at the discounted fee for this AMM instance. | -| `DiscountedFee` | String | UInt32 | Yes | The trading fee to be charged to the auction owner, in the same format as `TradingFee`. By default this is 0, meaning that the auction owner can trade at no fee instead of the standard fee for this AMM. | +| `DiscountedFee` | String | UInt32 | Yes | The trading fee to be charged to the auction owner, in the same format as `TradingFee`. Normally, this is 1/10 of the normal fee for this AMM. | | `Price` | [Currency Amount][] | Amount | Yes | The amount the auction owner paid to win this slot, in LP Tokens. | | `Expiration` | String | UInt32 | Yes | The time when this slot expires, in [seconds since the Ripple Epoch][]. | From 9b55f56adbc254cc05b83429b3b61e391da05b95 Mon Sep 17 00:00:00 2001 From: Oliver Eggert Date: Fri, 15 Dec 2023 15:16:26 -0800 Subject: [PATCH 02/25] migrating commits to clean branch --- content/_snippets/rippled-api-links.md | 1 + .../networks-and-servers/parallel-networks.md | 1 + .../xrpl-sidechains/cross-chain-bridges.md | 45 ++++ .../xrpl-sidechains/witness-servers.md | 152 ++++++++++++ .../xrpl-sidechains/xrpl-sidechains.md | 73 ++++++ ...onnect-your-rippled-to-the-xrp-test-net.md | 25 ++ content/references/protocol/binary-format.md | 1 + .../ledger-data/ledger-entry-types/bridge.md | 74 ++++++ .../ledger-entry-types/xchainownedclaimid.md | 109 ++++++++ .../xchainownedcreateaccountclaimid.md | 95 +++++++ .../types/xchainaccountcreatecommit.md | 66 +++++ .../xchainaddaccountcreateattestation.md | 83 +++++++ .../types/xchainaddclaimattestation.md | 103 ++++++++ .../transactions/types/xchainclaim.md | 66 +++++ .../transactions/types/xchaincommit.md | 62 +++++ .../transactions/types/xchaincreatebridge.md | 67 +++++ .../transactions/types/xchaincreateclaimid.md | 65 +++++ .../transactions/types/xchainmodifybridge.md | 75 ++++++ content/resources/known-amendments.md | 25 +- .../tutorials/get-started/public-servers.md | 1 + .../tasks/use-xrpl-sidechains/index.md | 8 + .../set-up-iou-iou-bridge.md | 168 +++++++++++++ .../set-up-xrp-xrp-bridge.md | 234 ++++++++++++++++++ .../submit-cross-chain-transaction.md | 136 ++++++++++ dactyl-config.yml | 95 +++++++ template/page-websocket-api-tool.html.jinja | 7 + 26 files changed, 1834 insertions(+), 3 deletions(-) create mode 100644 content/concepts/xrpl-sidechains/cross-chain-bridges.md create mode 100644 content/concepts/xrpl-sidechains/witness-servers.md create mode 100644 content/concepts/xrpl-sidechains/xrpl-sidechains.md create mode 100644 content/references/protocol/ledger-data/ledger-entry-types/bridge.md create mode 100644 content/references/protocol/ledger-data/ledger-entry-types/xchainownedclaimid.md create mode 100644 content/references/protocol/ledger-data/ledger-entry-types/xchainownedcreateaccountclaimid.md create mode 100644 content/references/protocol/transactions/types/xchainaccountcreatecommit.md create mode 100644 content/references/protocol/transactions/types/xchainaddaccountcreateattestation.md create mode 100644 content/references/protocol/transactions/types/xchainaddclaimattestation.md create mode 100644 content/references/protocol/transactions/types/xchainclaim.md create mode 100644 content/references/protocol/transactions/types/xchaincommit.md create mode 100644 content/references/protocol/transactions/types/xchaincreatebridge.md create mode 100644 content/references/protocol/transactions/types/xchaincreateclaimid.md create mode 100644 content/references/protocol/transactions/types/xchainmodifybridge.md create mode 100644 content/tutorials/tasks/use-xrpl-sidechains/index.md create mode 100644 content/tutorials/tasks/use-xrpl-sidechains/set-up-iou-iou-bridge.md create mode 100644 content/tutorials/tasks/use-xrpl-sidechains/set-up-xrp-xrp-bridge.md create mode 100644 content/tutorials/tasks/use-xrpl-sidechains/submit-cross-chain-transaction.md diff --git a/content/_snippets/rippled-api-links.md b/content/_snippets/rippled-api-links.md index d1534e4331..61d8c6cd5a 100644 --- a/content/_snippets/rippled-api-links.md +++ b/content/_snippets/rippled-api-links.md @@ -252,6 +252,7 @@ "Tickets", "TickSize", "TrustSetAuth", + "XChainBridge", "XRPFees" ] %} diff --git a/content/concepts/networks-and-servers/parallel-networks.md b/content/concepts/networks-and-servers/parallel-networks.md index 48f29c803e..2f5d571e3f 100644 --- a/content/concepts/networks-and-servers/parallel-networks.md +++ b/content/concepts/networks-and-servers/parallel-networks.md @@ -17,6 +17,7 @@ To help members of the XRP Ledger community interact with XRP Ledger technology | Testnet | Stable releases | An "alternate universe" network that acts as a testing ground for software built on the XRP Ledger, without impacting production XRP Ledger users and without risking real money. The [amendment status](known-amendments.html) of the Testnet is intended to closely mirror the Mainnet, although slight variations in timing may occur due to the unpredictable nature of decentralized systems. | | Devnet | Beta releases | A preview of coming attractions, where unstable changes to the core XRP Ledger software may be tested out. Developers can use this altnet to interact with and learn about planned new XRP Ledger features and amendments that are not yet enabled on the Mainnet. | | [Hooks V3 Testnet](https://hooks-testnet-v3.xrpl-labs.com/) | [Hooks server](https://github.com/XRPL-Labs/xrpld-hooks) | A preview of on-chain smart contract functionality using [hooks](https://xrpl-hooks.readme.io/). | +| Sidechain-Devnet | Beta releases | A sidechain to test cross-chain bridge features. Devnet is treated as the locking chain and this sidechain is the issuing chain.
Library support:
- [xrpl.js 2.7.0-beta.3](https://www.npmjs.com/package/xrpl/v/2.7.0-beta.3)
- [xrpl-py 1.8.0b2](https://pypi.org/project/xrpl-py/1.8.0b2/)
**Note**: You can also use the [`xbridge-cli`](https://github.com/XRPLF/xbridge-cli) commandline tool to set up a cross-chain bridge on your local machine. | Each altnet has its own separate supply of test XRP, which is [given away for free](xrp-testnet-faucet.html) to parties interested in experimenting with the XRP Ledger and developing applications and integrations. Test XRP does not have real-world value and is lost when the network is reset. diff --git a/content/concepts/xrpl-sidechains/cross-chain-bridges.md b/content/concepts/xrpl-sidechains/cross-chain-bridges.md new file mode 100644 index 0000000000..d5e04dd484 --- /dev/null +++ b/content/concepts/xrpl-sidechains/cross-chain-bridges.md @@ -0,0 +1,45 @@ +--- +html: cross-chain-bridges.html +parent: xrpl-sidechains.html +blurb: Cross-chain bridges for the XRP Ledger enable value in the form of XRP and other tokens (IOUs) to move efficiently between blockchains. +status: not_enabled +labels: + - Blockchain + - Interoperability +--- +# Cross-Chain Bridges + +_(Requires the [XChainBridge amendment][] :not_enabled:)_ + +Cross-chain bridges enable you to move XRP and tokens between the XRP Ledger and other blockchains. When referring to the blockchains connected by a bridge, one is the locking chain and the other the issuing chain. + +A locking chain is where the digital asset originates from. These assets are locked in a trust when sent across a bridge to an issuing chain. + +An issuing chain is an independent ledger with its own consensus algorithm and transaction types and rules. A wrapped version of the digital asset is minted and burned, depending on if an asset is received or sent from the locking chain. + +**Note:** Bridges utilize special _door accounts_ when moving assets cross-chain. The door account on a locking chain is used to put assets into trust, and the door account on an issuing chain used to issue wrapped assets. + +Both the locking and issuing chains operate as parallel networks with independent nodes and validators. They rely on independent [witness servers](witness-servers.html) to watch transactions between the two chains and attest that assets have moved into specifically designated accounts. + + +## How Do Bridges Work? + +At a high-level, bridges enable cross-chain transactions through these steps: + +1. Create a cross-chain claim ID on the issuing chain. A cross-chain claim ID represents one transfer of value between blockchains. +2. Submit a commit transaction on the locking chain, putting the assets in a trust. The transaction includes the cross-chain claim ID and reward for witness servers. + + **Note:** Witness servers monitor transactions on both chains. They provide attestations, or signed messages, to verify a transaction occurred. There are attestations for `XChainCommit` and `XChainAccountCreateCommit` transactions. + +3. Witness servers provide attestations to the issuing chain, saying the assets were locked on the locking chain. +4. When there are enough signatures to reach quorum, the assets are released on the issuing chain to the destination account. + + **Note:** In some cases, such as deposit authorization being enabled or, you'll need to submit a transaction claim for the transferred assets on the issuing chain. + +5. Rewards are distributed to the witness servers' accounts on the issuing chain. + + + +{% include '_snippets/rippled-api-links.md' %} +{% include '_snippets/tx-type-links.md' %} +{% include '_snippets/rippled_versions.md' %} \ No newline at end of file diff --git a/content/concepts/xrpl-sidechains/witness-servers.md b/content/concepts/xrpl-sidechains/witness-servers.md new file mode 100644 index 0000000000..e579746591 --- /dev/null +++ b/content/concepts/xrpl-sidechains/witness-servers.md @@ -0,0 +1,152 @@ +--- +html: witness-servers.html +parent: xrpl-sidechains.html +blurb: A witness server is a light-weight server that witnesses and signs transactions between the XRP Ledger and another chain. +status: not_enabled +labels: + - Blockchain + - Interoperability +--- +# Witness Servers + +_(Requires the [XChainBridge amendment][] :not_enabled:)_ + +**TODO**: Add link to sourcefiles after it's moved to XRPL repo. + +A _witness server_ acts as a neutral witness for transactions between a locking chain and an issuing chain. It listens to the door accounts on both sides of a bridge and signs attestations that confirm a transaction occurred. They are essentially acting as an oracle to “prove” that value was locked or burned on a source account, which allows the recipient to then claim (via minting or unlocking) the equivalent funds on the destination account. + +The bridge between the locking chain and the issuing chain includes the following information in its configuration: + +* Witness servers that monitor transactions on the bridge. You can choose one or more witness servers. +* Fee for witness servers for their service. + +Anyone can run a witness server. However, the burden is on the participants of the issuing chain to evaluate the reliability of witness servers. If you run a witness server, you must also run a `rippled` node and sync it to the chain the witness server needs access to. + +**Note:** Issuing chains may choose to configure a bridge with only one witness server initially and run the witness server itself. This strategy is helpful in the initial period, when the issuing chain hasn't established itself yet in the marketplace. + + +## Witness Server Configuration + +The witness server takes a JSON configuration file, specified using the `--conf` command-line argument. + + +### Example Configuration JSON + +```json +{ + "LockingChain": { + "Endpoint": { + "Host": "127.0.0.1", + "Port": 6005 + }, + "TxnSubmit": { + "ShouldSubmit": true, + "SigningKeySeed": "shUe3eSgGK4e6xMFuCakZnxsMN1uk", + "SigningKeyType": "ed25519", + "SubmittingAccount": "rpFp36UHW6FpEcZjZqq5jSJWY6UCj3k4Es" + }, + "RewardAccount": "rpFp36UHW6FpEcZjZqq5jSJWY6UCj3k4Es" + }, + "IssuingChain": { + "Endpoint": { + "Host": "127.0.0.1", + "Port": 6007 + }, + "TxnSubmit": { + "ShouldSubmit": true, + "SigningKeySeed": "shUe3eSgGK4e6xMFuCakZnxsMN1uk", + "SigningKeyType": "ed25519", + "SubmittingAccount": "rpFp36UHW6FpEcZjZqq5jSJWY6UCj3k4Es" + }, + "RewardAccount": "rpFp36UHW6FpEcZjZqq5jSJWY6UCj3k4Es" + }, + "RPCEndpoint": { + "Host": "127.0.0.1", + "Port": 6010 + }, + "DBDir": "/var/lib/witness/witness01/db", + "LogFile": "/var/log/witness/witness01.log", + "SigningKeySeed": "spkHEwDKeChm8PAFApLkF1E2sDs6t", + "SigningKeyType": "ed25519", + "XChainBridge": { + "LockingChainDoor": "r3nCVTbZGGYoWvZ58BcxDmiMUU7ChMa1eC", + "LockingChainIssue": { + "currency": "XRP" + }, + "IssuingChainDoor": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh", + "IssuingChainIssue": { + "currency": "XRP" + } + }, + "Admin": { + "Username": "username01", + "Password": "password01" + } +} +``` + + +### Configuration Fields + +| Field Name | JSON Type | Required? | Description | +|------------------|----------------|-----------|-------------| +| `Admin` | `object` | No | The `Username` and `Password` fields (as strings) for privileged requests to the witness server. **Note:** Both or none of the admin fields must be set. | +| `IssuingChain` | `object` | Yes | The parameters for interacting with the issuing chain. | +| `LockingChain` | `object` | Yes | The parameters for interacting with the locking chain. | +| `RPCEndpoint` | `object` | Yes | The endpoint for RPC requests to the witness server. | +| `LogFile` | `string` | Yes | The location of the log file. | +| `LogLevel` | `string` | Yes | The level of logs to store in the log file. The options are ["All", "Trace", "Debug", "Info", "Warning", "Error", "Fatal", "Disabled","None"]. | +| `DBDir` | `string` | Yes | The location of the directory where the databases are stored. | +| `SigningKeySeed` | `string` | Yes | The seed that the witness server should use to sign its attestations. | +| `SigningKeyType` | `string` | Yes | The algorithm used to encode the `SigningKeySeed`. The options are `secp256k1` and `ed25519`. | +| `XChainBridge` | `XChainBridge` | Yes | The bridge that the witness server is monitoring. | + + +#### IssuingChain and LockingChain Fields + +| Field Name | JSON Type | Required? | Description | +|-----------------|-----------|-----------|-------------| +| `Endpoint` | `object` | Yes | The websocket endpoint of a `rippled` node synced with the chain. **Note:** This must be a node you run. | +| `TxnSubmit` | `object` | Yes | The parameters for transaction submission on the chain. | +| `RewardAccount` | `string` | Yes | The account that should receive the witness's share of the `SignatureReward` on the chain. | + + +#### Endpoint Fields + +| Field Name | JSON Type | Required? | Description | +|------------|-----------|-----------|-------------| +| `Host` | `string` | Yes | The IP address of the `rippled` node. **Note:** This doesn't accept URLs | +| `Port` | `string` | Yes | The port used for the websocket endpoint. | + + +#### RPCEndpoint Fields + +| Field Name | JSON Type | Required? | Description | +|------------|-----------|-----------|-------------| +| `Host` | `string` | Yes | The IP address of the witness server for RPC requests. **Note:** This doesn't accept URLs | +| `Port` | `string` | Yes | The port used for the websocket endpoint. | + + +#### TxnSubmit Fields + +| Field Name | JSON Type | Required? | Description | +|---------------------|-----------|-----------|-------------| +| `ShouldSubmit` | `boolean` | Yes | A boolean indicating whether or not the witness server should submit transactions on the locking chain. | +| `SigningKeySeed` | `string` | No | The seed that the witness server should use to sign its transactions on the locking chain. This is required if `ShouldSubmit` is `true`. | +| `SigningKeyType` | `string` | No | The algorithm used to encode the `SigningKeySeed`. The options are `secp256k1` and `ed25519`. This is required if `ShouldSubmit` is `true`. | +| `SubmittingAccount` | `string` | No | The account from which the `XChainAddClaimAttestation` and `XChainAddAccountCreateAttestation` transactions should be sent. This is required if `ShouldSubmit` is `true`. | + + +#### XChainBridge Fields + +| Field | JSON Type | [Internal Type][] | Required? | Description | +|:--------------------|:----------|:------------------|:----------|:----------------| +| `IssuingChainDoor` | `string` | `ACCOUNT` | Yes | The door account on the issuing chain. For an XRP-XRP bridge, this must be the genesis account (the account that is created when the network is first started, which contains all of the XRP). | +| `IssuingChainIssue` | `Issue` | `ISSUE` | Yes | The asset that is minted and burned on the issuing chain. For an IOU-IOU bridge, the issuer of the asset must be the door account on the issuing chain, to avoid supply issues. | +| `LockingChainDoor` | `string` | `ACCOUNT` | Yes | The door account on the locking chain. | +| `LockingChainIssue` | `Issue` | `ISSUE` | Yes | The asset that is locked and unlocked on the locking chain. | + + +{% include '_snippets/rippled-api-links.md' %} +{% include '_snippets/tx-type-links.md' %} +{% include '_snippets/rippled_versions.md' %} \ No newline at end of file diff --git a/content/concepts/xrpl-sidechains/xrpl-sidechains.md b/content/concepts/xrpl-sidechains/xrpl-sidechains.md new file mode 100644 index 0000000000..03f8e3cdf3 --- /dev/null +++ b/content/concepts/xrpl-sidechains/xrpl-sidechains.md @@ -0,0 +1,73 @@ +--- +html: xrpl-sidechains.html +parent: concepts.html +blurb: An XRPL sidechain is an independent ledger with its own consensus algorithm, transaction types, and rules. +labels: + - Blockchain + - Interoperability +--- +# XRPL Sidechains + +_(Requires the [XChainBridge amendment][] :not_enabled:)_ + +A sidechain is an independent ledger with its own consensus algorithm, transaction types, rules, and nodes. It acts as its own blockchain, running parallel to the mainchain (XRP Ledger), enabling value to move between the two without compromising the speed, efficiency, and throughput of the mainchain. + +Sidechains can customize the XRP Ledger protocol to the needs of a specific use case or project and run it as its own blockchain. Some examples include: + +* Adding a smart contract layer, powered by an engine compatible with the Ethereum Virtual Machine (EVM), web assembly, or a Move VM. For an example, see: [Hooks](https://hooks-testnet.xrpl-labs.com/). +* Building your own algorithmic stable coin with customised ledger types and transaction rules. +* Building permissioned or nearly permissionless, centralized or largely decentralized ledgers whose assets can be traded on the Mainnet [decentralized exchange](decentralized-exchange.html). + + +**Notes:** + + - Sidechains use their own validators and require a separate UNL from the mainchain `rippled` UNL. + - Nodes on the mainchain and sidechain have no knowledge of each other. + + +## Legal FAQs + +### What is a Sidechain? + +A sidechain is a separate blockchain that links the XRPL Mainnet chain (the “Mainchain”) to a sidechain (each a “Sidechain”), allowing for cross-chain exchanges of assets and information. + + +### What are Witness Servers? + +“Witness Servers” validate transfers between “door wallets” that connect the Mainchain to each Sidechain. A series of decentralized entities and individuals will operate Witness Servers. + + +### Are there risks associated with operating a Witness Server? + +There are certain risks associated with operating a Witness Server for a Sidechain, including the following: + +_Regulatory Considerations_: Operating a Witness Server carries some regulatory risk. A few risks are identified below, some of which pertain to regulatory regimes that only apply to projects that serve those located in the U.S. U.S. regimes are identified here because they are commonly considered some of the strictest regulatory regimes in the world. + +The regulatory regime in the U.S. concerning the operation of a “money transmitting business” requiring federal registration as a money service business (“MSB”) and state money transmitter licenses (“MTLs”) is unclear as it pertains to operating Witness Servers. The Witness Servers are intended to be operated by a series of decentralized entities and persons. Despite this intention, if a regulator determined that there was “centralized” control of the Witness Servers by a particular entity or coordinated group, it may deem such activity to be money transmission. The U.S. Treasury Department recently issued a report identifying a series of factors it would consider when determining whether a particular project is “decentralized.” See [2023 DeFi Illicit Finance Risk Assessment](https://home.treasury.gov/news/press-releases/jy1391). This recent regulatory guidance is important because it indicates that the U.S. Treasury recognizes that certain projects may be “decentralized” and if the operation of the Witness Servers is “decentralized” it may not be considered a “money transmitting business.” + +While U.S. crypto regulations have consistently remained among the most stringent and aggressively enforced, other jurisdictions also have regulation and laws relating to the transfer of “money” and other value. For example, in March of 2022, U.K. regulatory authorities published a series of documentary guidance regarding crypto and decentralized finance. See [Financial Stability in Focus: Cryptoassets and Decentralized Finance](https://www.bankofengland.co.uk/financial-stability-in-focus/2022/march-2022). More recently, in June of 2023, the E.U. formally adopted a regulatory framework which in part imposes codified rules and regulations pertaining to decentralized crypto platforms. See [Markets in Crypto-Assets Regulation](https://www.esma.europa.eu/esmas-activities/digital-finance-and-innovation/markets-crypto-assets-regulation-mica). For those considering operating a Witness Server, it is critical to stay informed and compliant with the specific requirements of each jurisdiction involved to effectively manage associated risks. + +_Technology and Network Security_: Those intending to run a Witness Server should be familiar with the technical and security aspects of doing so. Before agreeing to run a Witness Server, one should fully understand the functionality, potential vulnerabilities, and necessary technological and security measures involved. + +_Civil Liability_: Operating a Witness Server, like participating in any blockchain project, carries an unspecified level of civil liability risk. There has been an influx of plaintiffs’ lawsuits in the U.S. and other jurisdictions, and it is difficult to evaluate what theories a particular plaintiffs’ attorney may implement in a civil lawsuit. Regardless of any real or perceived civil liability risk, it should be noted that even a frivolous lawsuit could take time and money to respond. + + +### Should I seek independent advice before agreeing to operate a Witness Server? + +Yes. Any party considering running a Witness Server should seek independent legal and tax advice from experienced professionals. Please note, that as the Witness Servers must mutually attest to confirm cross-chain transfers, they may be understood to operate as a common enterprise - as it is defined by US regulators. In a common enterprise, joint and several liability may apply, meaning that each Witness Server could be held individually responsible for all liability or damages incurred. Given the evolving regulatory landscape, it’s critical to consult with a legal professional who can help navigate the complex and changing global regulatory landscape associated with the expectations and obligations of running a Witness Server. As with any blockchain project, please do your own research. These FAQs are just general guidance and are not legal or tax advice. + + +### Who should not run a Witness Server? + +You should not run a Witness Server if you are not experienced (or do not have access to experienced support) in blockchain, MSB and MTL regulations, and other applicable regulations and laws. You should also not operate a Witness Server if you are not an experienced person or entity with technical and compliance expertise. Few individuals are qualified and experienced enough to operate Witness Servers on their own. You should also not operate a Witness Server if you have not sought and obtained independent legal and tax advice. + + +### Are these FAQs comprehensive and conclusive advice? + +No. These FAQs are intended to provide general guidance and do not constitute technical, financial, or legal advice. These FAQs should not be used as a substitute for professional advice tailored to one’s specific circumstances. The blockchain and digital asset landscape is complex and constantly changing, which necessitates staying updated and seeking expert advice. It is recommended that those engaging with a Sidechain regularly check official resources such as governmental and regulatory body websites. Nonetheless, consulting with legal professionals who specialize in blockchain, and cryptocurrency is the most reliable way to get accurate and personalized advice. + + + +{% include '_snippets/rippled-api-links.md' %} +{% include '_snippets/tx-type-links.md' %} +{% include '_snippets/rippled_versions.md' %} \ No newline at end of file diff --git a/content/infrastructure/configuration/connect-your-rippled-to-the-xrp-test-net.md b/content/infrastructure/configuration/connect-your-rippled-to-the-xrp-test-net.md index 360317c364..957442a554 100644 --- a/content/infrastructure/configuration/connect-your-rippled-to-the-xrp-test-net.md +++ b/content/infrastructure/configuration/connect-your-rippled-to-the-xrp-test-net.md @@ -42,6 +42,11 @@ Edit your `rippled.cfg` file. # No [ips] stanza. Use the default hubs to connect to Mainnet. + *Sidechain-Devnet* + + [ips] + sidechain-net2.devnet.rippletest.net 51235 + 2. Comment out the previous `[ips]` stanza, if there is one: @@ -70,6 +75,11 @@ Edit your `rippled.cfg` file. [network_id] main + *Sidechain-Devnet* + + [network_id] + 262 + For custom networks, everyone who connects to the network should use a value unique to that network. When creating a new network, choose a network ID at random from the integers 11 to 4,294,967,295. @@ -109,6 +119,14 @@ Edit your `validators.txt` file. This file is located in the same folder as your [validator_list_keys] ED2677ABFFD1B33AC6FBC3062B71F1E8397C1505E1C42C64D11AD1B28FF73F4734 + *Sidechain-Devnet* + + [validator_list_sites] + https://vlsidechain-net2.devnet.rippletest.net + + [validator_list_keys] + EDA5504C7133743FADA46342229B4E9CBBE1CF9BCA19D16633574F7CBB72F79569 + **Tip:** Preview packages might come with the necessary stanzas pre-configured, but check them just in case. @@ -160,6 +178,13 @@ _Mainnet_ # Delete or comment out. Don't force-enable features on Mainnet. ``` +_Sidechain-Devnet_ + +``` +[features] +XChainBridge +``` + **Warning:** Do not use the `[features]` stanza when connecting to Mainnet or Testnet. Forcefully enabling different features than the rest of the network could cause your server to diverge from the network. diff --git a/content/references/protocol/binary-format.md b/content/references/protocol/binary-format.md index ec42addf8c..374ba498f5 100644 --- a/content/references/protocol/binary-format.md +++ b/content/references/protocol/binary-format.md @@ -189,6 +189,7 @@ Transaction instructions may contain fields of any of the following types: | [UInt8][] | 16 | 8 | No | An 8-bit unsigned integer. | | [UInt16][] | 1 | 16 | No | A 16-bit unsigned integer. The `TransactionType` is a special case of this type, with specific strings mapping to integer values. | | [UInt32][] | 2 | 32 | No | A 32-bit unsigned integer. The `Flags` and `Sequence` fields on all transactions are examples of this type. | +| XCHAIN_BRIDGE | 25 | Variable | No | A bridge between two blockchains, identified by the door accounts and issued assets on the locking chain and issuing chain. `XCHAIN_BRIDGE` is serialized in this order: locking chain door, locking chain issue, issuing chain door, issuing chain issue. | [Length-prefixed]: #length-prefixing diff --git a/content/references/protocol/ledger-data/ledger-entry-types/bridge.md b/content/references/protocol/ledger-data/ledger-entry-types/bridge.md new file mode 100644 index 0000000000..28bcf8f0e8 --- /dev/null +++ b/content/references/protocol/ledger-data/ledger-entry-types/bridge.md @@ -0,0 +1,74 @@ +--- +html: bridge.html +parent: ledger-entry-types.html +blurb: A `bridge` object represents a single cross-chain bridge that connects and enables value to move efficiently between two blockchains. +labels: + - Interoperability +status: not_enabled +--- +# Bridge +_(Requires the [XChainBridge amendment][] :not_enabled:)_ + +[[Source]](https://github.com/XRPLF/rippled/blob/master/src/ripple/protocol/impl/LedgerFormats.cpp#L286-L300 "Source") + +The `Bridge` ledger entry represents a single cross-chain bridge that connects the XRP Ledger with another blockchain, such as its sidechain, and enables value in the form of XRP and other tokens (IOUs) to move efficiently between the two blockchains. + + +## Example Bridge JSON + +```json +{ + "Account": "r3nCVTbZGGYoWvZ58BcxDmiMUU7ChMa1eC", + "Flags": 0, + "LedgerEntryType": "Bridge", + "MinAccountCreateAmount": "2000000000", + "OwnerNode": "0", + "PreviousTxnID": "67A8A1B36C1B97BE3AAB6B19CB3A3069034877DE917FD1A71919EAE7548E5636", + "PreviousTxnLgrSeq": 102, + "SignatureReward": "204", + "XChainAccountClaimCount": "0", + "XChainAccountCreateCount": "0", + "XChainBridge": { + "IssuingChainDoor": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh", + "IssuingChainIssue": { + "currency": "XRP" + }, + "LockingChainDoor": "r3nCVTbZGGYoWvZ58BcxDmiMUU7ChMa1eC", + "LockingChainIssue": { + "currency": "XRP" + } + }, + "XChainClaimID": "1", + "index": "9F2C9E23343852036AFD323025A8506018ABF9D4DBAA746D61BF1CFB5C297D10" +} +``` + + +## Bridge Fields + +| Field | JSON Type | Internal Type | Required? | Description | +|:---------------------------|:------------------|:------------------|:----------|:------------| +| `Account` | `string` | `ACCOUNT` | Yes | The account that owns this object. | +| `LedgerIndex` | `string` | `HASH256` | Yes | The ledger index is a hash of a unique prefix for a bridge object, and the fields in `XChainBridge`. | +| `MinAccountCreateAmount` | `Currency Amount` | `AMOUNT` | No | The minimum amount, in XRP, required for an `XChainAccountCreateCommit` transaction. If this isn't present, the `XChainAccountCreateCommit` transaction will fail. This field can only be present on XRP-XRP bridges. | +| `SignatureReward` | `Currency Amount` | `AMOUNT` | Yes | The total amount, in XRP, to be rewarded for providing a signature for cross-chain transfer or for signing for the cross-chain reward. This amount will be split among the signers. | +| `XChainAccountClaimCount` | `number` | `UINT64` | Yes | A counter used to order the execution of account create transactions. It is incremented every time a `XChainAccountCreateCommit` transaction is "claimed" on the destination chain. When the "claim" transaction is run on the destination chain, the `XChainAccountClaimCount` must match the value that the `XChainAccountCreateCount` had at the time the `XChainAccountClaimCount` was run on the source chain. This orders the claims so that they run in the same order that the `XChainAccountCreateCommit` transactions ran on the source chain, to prevent transaction replay. | +| `XChainAccountCreateCount` | `number` | `UINT64` | Yes | A counter used to order the execution of account create transactions. It is incremented every time a successful `XChainAccountCreateCommit` transaction is run for the source chain. | +| `XChainBridge` | `XChainBridge` | `XCHAIN_BRIDGE` | Yes | The door accounts and assets of the bridge this object correlates to. | +| `XChainClaimID` | `number` | `UINT64` | Yes | The value of the next `XChainClaimID` to be created. | + + +### XChainBridge Fields + +| Field | JSON Type | Internal Type | Required? | Description | +|:--------------------|:----------|:------------------|:----------|:----------------| +| `IssuingChainDoor` | `string` | `ACCOUNT` | Yes | The door account on the issuing chain. For an XRP-XRP bridge, this must be the genesis account (the account that is created when the network is first started, which contains all of the XRP). | +| `IssuingChainIssue` | `Issue` | `ISSUE` | Yes | The asset that is minted and burned on the issuing chain. For an IOU-IOU bridge, the issuer of the asset must be the door account on the issuing chain, to avoid supply issues. | +| `LockingChainDoor` | `string` | `ACCOUNT` | Yes | The door account on the locking chain. | +| `LockingChainIssue` | `Issue` | `ISSUE` | Yes | The asset that is locked and unlocked on the locking chain. | + + + +{% include '_snippets/rippled-api-links.md' %} +{% include '_snippets/tx-type-links.md' %} +{% include '_snippets/rippled_versions.md' %} \ No newline at end of file diff --git a/content/references/protocol/ledger-data/ledger-entry-types/xchainownedclaimid.md b/content/references/protocol/ledger-data/ledger-entry-types/xchainownedclaimid.md new file mode 100644 index 0000000000..1bd23a6c9c --- /dev/null +++ b/content/references/protocol/ledger-data/ledger-entry-types/xchainownedclaimid.md @@ -0,0 +1,109 @@ +--- +html: xchainownedclaimid.html +parent: ledger-entry-types.html +blurb: An `XChainOwnedClaimID` object represents *one* cross-chain transfer of value. +labels: + - Interoperability +status: not_enabled +--- +# XChainOwnedClaimID +_(Requires the [XChainBridge amendment][] :not_enabled:)_ + +[[Source]](https://github.com/seelabs/rippled/blob/xbridge/src/ripple/protocol/impl/LedgerFormats.cpp#L281-L293 "Source") + +An `XChainOwnedClaimID` object represents *one* cross-chain transfer of value and includes information of the account on the source chain that locks or burns the funds on the source chain. + +The `XChainOwnedClaimID` object must be acquired on the destination chain before submitting a `XChainCommit` on the source chain. Its purpose is to prevent transaction replay attacks and is also used as a place to collect attestations from witness servers. + +An `XChainCreateClaimID` transaction is used to create a new `XChainOwnedClaimID`. The ledger object is destroyed when the funds are successfully claimed on the destination chain. + + +## Example XChainOwnedClaimID JSON + +```json +{ + "Account": "rBW1U7J9mEhEdk6dMHEFUjqQ7HW7WpaEMi", + "Flags": 0, + "OtherChainSource": "r9oXrvBX5aDoyMGkoYvzazxDhYoWFUjz8p", + "OwnerNode": "0", + "PreviousTxnID": "1CFD80E9CF232B8EED62A52857DE97438D12230C06496932A81DEFA6E66070A6", + "PreviousTxnLgrSeq": 58673, + "SignatureReward": "100", + "XChainBridge": { + "IssuingChainDoor": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh", + "IssuingChainIssue": { + "currency": "XRP" + }, + "LockingChainDoor": "rMAXACCrp3Y8PpswXcg3bKggHX76V3F8M4", + "LockingChainIssue": { + "currency": "XRP" + } + }, + "XChainClaimAttestations": [ + { + "XChainClaimProofSig": { + "Amount": "1000000", + "AttestationRewardAccount": "rfgjrgEJGDxfUY2U8VEDs7BnB1jiH3ofu6", + "AttestationSignerAccount": "rfsxNxZ6xB1nTPhTMwQajNnkCxWG8B714n", + "Destination": "rBW1U7J9mEhEdk6dMHEFUjqQ7HW7WpaEMi", + "PublicKey": "025CA526EF20567A50FEC504589F949E0E3401C13EF76DD5FD1CC2850FA485BD7B", + "WasLockingChainSend": 1 + } + }, + { + "XChainClaimProofSig": { + "Amount": "1000000", + "AttestationRewardAccount": "rUUL1tP523M8KimERqVS7sxb1tLLmpndyv", + "AttestationSignerAccount": "rEg5sHxZVTNwRL3BAdMwJatkmWDzHMmzDF", + "Destination": "rBW1U7J9mEhEdk6dMHEFUjqQ7HW7WpaEMi", + "PublicKey": "03D40434A6843638681E2F215310EBC4131AFB12EA85985DA073183B732525F7C9", + "WasLockingChainSend": 1 + }, + } + ], + "XChainClaimID": "b5", + "LedgerEntryType": "XChainOwnedClaimID", + "LedgerIndex": "20B136D7BF6D2E3D610E28E3E6BE09F5C8F4F0241BBF6E2D072AE1BACB1388F5" +} +``` + + +## XChainOwnedClaimID Fields + +| Field | JSON Type | Internal Type | Required? | Description | +|:--------------------------|:------------------|:------------------|:----------|:----------------| +| `Account` | `string` | `ACCOUNT` | Yes | The account that owns this object. | +| `LedgerIndex` | `string` | `HASH256` | Yes | The ledger index is a hash of a unique prefix for `XChainOwnedClaimID`s, the actual `XChainClaimID` value, and the fields in `XChainBridge`. | +| `OtherChainSource` | `string` | `ACCOUNT` | Yes | The account that must send the corresponding `XChainCommit` on the source chain. The destination may be specified in the `XChainCommit` transaction, which means that if the `OtherChainSource` isn't specified, another account can try to specify a different destination and steal the funds. This also allows tracking only a single set of signatures, since we know which account will send the `XChainCommit` transaction. | +| `SignatureReward` | `Currency Amount` | `AMOUNT` | Yes | The total amount to pay the witness servers for their signatures. It must be at least the value of `SignatureReward` in the `Bridge` ledger object. | +| `XChainBridge` | `XChainBridge` | `XCHAIN_BRIDGE` | Yes | The door accounts and assets of the bridge this object correlates to. | +| `XChainClaimAttestations` | `array` | `ARRAY` | Yes | Attestations collected from the witness servers. This includes the parameters needed to recreate the message that was signed, including the amount, which chain (locking or issuing), optional destination, and reward account for that signature. | +| `XChainClaimID` | `string` | `UINT64` | Yes | The unique sequence number for a cross-chain transfer. | + + +### XChainClaimAttestations Fields + +| Field | JSON Type | Internal Type | Required | Description | +|-------------------------------|-------------------|---------------|----------|-------------| +| `XChainClaimProofSig` | `array` | `OBJECT` | Yes | An attestation from one witness server. | +| `Amount` | `Currency Amount` | `AMOUNT` | Yes | The amount to claim in the `XChainCommit` transaction on the destination chain. | +| `AttestationRewardAccount` | `string` | `ACCOUNT` | Yes | The account that should receive this signer's share of the `SignatureReward`. | +| `AttestationSignerAccount` | `string` | `ACCOUNT` | Yes | The account on the door account's signer list that is signing the transaction. | +| `Destination` | `string` | `ACCOUNT` | No | The destination account for the funds on the destination chain. | +| `PublicKey` | `string` | `BLOB` | Yes | The public key used to verify the signature. | +| `WasLockingChainSend` | `number` | `UINT8` | Yes | A boolean representing the chain where the event occurred. | + + +### XChainBridge Fields + +| Field | JSON Type | Internal Type | Required? | Description | +|:--------------------|:----------|:------------------|:----------|:----------------| +| `IssuingChainDoor` | `string` | `ACCOUNT` | Yes | The door account on the issuing chain. For an XRP-XRP bridge, this must be the genesis account (the account that is created when the network is first started, which contains all of the XRP). | +| `IssuingChainIssue` | `Issue` | `ISSUE` | Yes | The asset that is minted and burned on the issuing chain. For an IOU-IOU bridge, the issuer of the asset must be the door account on the issuing chain, to avoid supply issues. | +| `LockingChainDoor` | `string` | `ACCOUNT` | Yes | The door account on the locking chain. | +| `LockingChainIssue` | `Issue` | `ISSUE` | Yes | The asset that is locked and unlocked on the locking chain. | + + +{% include '_snippets/rippled-api-links.md' %} +{% include '_snippets/tx-type-links.md' %} +{% include '_snippets/rippled_versions.md' %} \ No newline at end of file diff --git a/content/references/protocol/ledger-data/ledger-entry-types/xchainownedcreateaccountclaimid.md b/content/references/protocol/ledger-data/ledger-entry-types/xchainownedcreateaccountclaimid.md new file mode 100644 index 0000000000..5b83371bd0 --- /dev/null +++ b/content/references/protocol/ledger-data/ledger-entry-types/xchainownedcreateaccountclaimid.md @@ -0,0 +1,95 @@ +--- +html: xchainownedcreateaccountclaimid.html +parent: ledger-entry-types.html +blurb: The `XChainOwnedCreateAccountClaimID` ledger object is used to collect attestations for creating an account via a cross-chain transfer. +labels: + - Interoperability +status: not_enabled +--- +# XChainOwnedCreateAccountClaimID +_(Requires the [XChainBridge amendment][] :not_enabled:)_ + +[[Source]](https://github.com/seelabs/rippled/blob/xbridge/src/ripple/protocol/impl/LedgerFormats.cpp#L296-L306 "Source") + +The `XChainOwnedCreateAccountClaimID` ledger object is used to collect attestations for creating an account via a cross-chain transfer. + +It is created when an `XChainAddAccountCreateAttestation` transaction adds a signature attesting to a `XChainAccountCreateCommit` transaction and the `XChainAccountCreateCount` is greater than or equal to the current `XChainAccountClaimCount` on the `Bridge` ledger object. + +The ledger object is destroyed when all the attestations have been received and the funds have transferred to the new account. + + +## Example XChainOwnedCreateAccountClaimID JSON + +```json +{ + "LedgerEntryType": "XChainOwnedCreateAccountClaimID", + "LedgerIndex": "5A92F6ED33FDA68FB4B9FD140EA38C056CD2BA9673ECA5B4CEF40F2166BB6F0C", + "NewFields": { + "Account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh", + "XChainAccountCreateCount": "66", + "XChainBridge": { + "IssuingChainDoor": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh", + "IssuingChainIssue": { + "currency": "XRP" + }, + "LockingChainDoor": "rMAXACCrp3Y8PpswXcg3bKggHX76V3F8M4", + "LockingChainIssue": { + "currency": "XRP" + } + }, + "XChainCreateAccountAttestations": [ + { + "XChainCreateAccountProofSig": { + "Amount": "20000000", + "AttestationRewardAccount": "rMtYb1vNdeMDpD9tA5qSFm8WXEBdEoKKVw", + "AttestationSignerAccount": "rL8qTrAvZ8Q1o1H9H9Ahpj3xjgmRvFLvJ3", + "Destination": "rBW1U7J9mEhEdk6dMHEFUjqQ7HW7WpaEMi", + "PublicKey": "021F7CC4033EFBE5E8214B04D1BAAEC14808DC6C02F4ACE930A8EF0F5909B0C438", + "SignatureReward": "100", + "WasLockingChainSend": 1 + } + } + ] + } +} +``` + + +## XChainOwnedCreateAccountClaimID Fields + +| Field | JSON Type | Internal Type | Required? | Description | +|:----------------------------------|:---------------|:------------------|:----------|:------------| +| `Account` | `string` | `ACCOUNT` | Yes | The account that owns this object. | +| `LedgerIndex` | `string` | `HASH256` | Yes | The ledger index is a hash of a unique prefix for `XChainOwnedClaimID`s, the actual `XChainClaimID` value, and the fields in `XChainBridge`. | +| `XChainAccountCreateCount` | `number` | `UINT64` | Yes | An integer that determines the order that accounts created through cross-chain transfers must be performed. Smaller numbers must execute before larger numbers. | +| `XChainBridge` | `XChainBridge` | `XCHAIN_BRIDGE` | Yes | The door accounts and assets of the bridge this object correlates to. | +| `XChainCreateAccountAttestations` | `array` | `ARRAY` | Yes | Attestations collected from the witness servers. This includes the parameters needed to recreate the message that was signed, including the amount, destination, signature reward amount, and reward account for that signature. With the exception of the reward account, all signatures must sign the message created with common parameters. | + + +### XChainCreateAccountAttestations Fields + +| Field | JSON Type | Internal Type | Required | Description | +|-------------------------------|-------------------|---------------|----------|-------------| +| `XChainCreateAccountProofSig` | `array` | `OBJECT` | Yes | An attestation from one witness server. | +| `Amount` | `Currency Amount` | `AMOUNT` | Yes | The amount committed by the `XChainAccountCreateCommit` transaction on the source chain. | +| `AttestationRewardAccount` | `string` | `ACCOUNT` | Yes | The account that should receive this signer's share of the `SignatureReward`. | +| `AttestationSignerAccount` | `string` | `ACCOUNT` | Yes | The account on the door account's signer list that is signing the transaction. | +| `Destination` | `string` | `ACCOUNT` | Yes | The destination account for the funds on the destination chain. | +| `PublicKey` | `string` | `BLOB` | Yes | The public key used to verify the signature. | +| `WasLockingChainSend` | `number` | `UINT8` | Yes | A boolean representing the chain where the event occurred. | + + +### XChainBridge Fields + +| Field | JSON Type | Internal Type | Required? | Description | +|:--------------------|:----------|:------------------|:----------|:----------------| +| `IssuingChainDoor` | `string` | `ACCOUNT` | Yes | The door account on the issuing chain. For an XRP-XRP bridge, this must be the genesis account (the account that is created when the network is first started, which contains all of the XRP). | +| `IssuingChainIssue` | `Issue` | `ISSUE` | Yes | The asset that is minted and burned on the issuing chain. For an IOU-IOU bridge, the issuer of the asset must be the door account on the issuing chain, to avoid supply issues. | +| `LockingChainDoor` | `string` | `ACCOUNT` | Yes | The door account on the locking chain. | +| `LockingChainIssue` | `Issue` | `ISSUE` | Yes | The asset that is locked and unlocked on the locking chain. | + + + +{% include '_snippets/rippled-api-links.md' %} +{% include '_snippets/tx-type-links.md' %} +{% include '_snippets/rippled_versions.md' %} \ No newline at end of file diff --git a/content/references/protocol/transactions/types/xchainaccountcreatecommit.md b/content/references/protocol/transactions/types/xchainaccountcreatecommit.md new file mode 100644 index 0000000000..2f12e36c09 --- /dev/null +++ b/content/references/protocol/transactions/types/xchainaccountcreatecommit.md @@ -0,0 +1,66 @@ +--- +html: xchainaccountcreatecommit.html +parent: transaction-types.html +blurb: Create an account on one of the chains that the bridge connects. This account serves as the bridge entrance for that chain. +labels: + - Interoperability +status: not_enabled +--- +# XChainAccountCreateCommit +[[Source]](https://github.com/XRPLF/rippled/blob/master/src/ripple/protocol/impl/TxFormats.cpp#L466-L474 "Source") + +_(Requires the [XChainBridge amendment][] :not_enabled:)_ + +This transaction can only be used for XRP-XRP bridges. + +The `XChainAccountCreateCommit` transaction creates a new account for a witness server to submit transactions on an issuing chain. + +**Warning:** This transaction should only be executed if the witness attestations will be reliably delivered to the destination chain. If the signatures aren't delivered, then account creation will be blocked until attestations are received. This can be used maliciously; to disable this transaction on XRP-XRP bridges, omit the bridge's `MinAccountCreateAmount` field. + + +## Example XChainAccountCreateCommit JSON + +```json +{ + "Account": "rwEqJ2UaQHe7jihxGqmx6J4xdbGiiyMaGa", + "Destination": "rD323VyRjgzzhY4bFpo44rmyh2neB5d8Mo", + "TransactionType": "XChainAccountCreateCommit", + "Amount": "20000000", + "SignatureReward": "100", + "XChainBridge": { + "LockingChainDoor": "rMAXACCrp3Y8PpswXcg3bKggHX76V3F8M4", + "LockingChainIssue": { + "currency": "XRP" + }, + "IssuingChainDoor": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh", + "IssuingChainIssue": { + "currency": "XRP" + } + } +} +``` + + +## XChainAccountCreateCommit Fields + +| Field | JSON Type | Internal Type | Required? | Description | +|:------------------|:------------------|:------------------|:----------| :-----------| +| `Amount` | `Currency Amount` | `AMOUNT` | Yes | The amount, in XRP, to use for account creation. This must be greater than or equal to the `MinAccountCreateAmount` specified in the `Bridge` ledger object. | +| `Destination` | `string` | `ACCOUNT` | Yes | The destination account on the destination chain. | +| `SignatureReward` | `Currency Amount` | `AMOUNT` | No | The amount, in XRP, to be used to reward the witness servers for providing signatures. This must match the amount on the `Bridge` ledger object. | +| `XChainBridge` | `XChainBridge` | `XCHAIN_BRIDGE` | Yes | The bridge to create accounts for. | + + +### XChainBridge Fields + +| Field | JSON Type | Internal Type | Required? | Description | +|:--------------------|:----------|:------------------|:----------|:----------------| +| `IssuingChainDoor` | `string` | `ACCOUNT` | Yes | The door account on the issuing chain. For an XRP-XRP bridge, this must be the genesis account (the account that is created when the network is first started, which contains all of the XRP). | +| `IssuingChainIssue` | `Issue` | `ISSUE` | Yes | The asset that is minted and burned on the issuing chain. For an IOU-IOU bridge, the issuer of the asset must be the door account on the issuing chain, to avoid supply issues. | +| `LockingChainDoor` | `string` | `ACCOUNT` | Yes | The door account on the locking chain. | +| `LockingChainIssue` | `Issue` | `ISSUE` | Yes | The asset that is locked and unlocked on the locking chain. | + + +{% include '_snippets/rippled-api-links.md' %} +{% include '_snippets/tx-type-links.md' %} +{% include '_snippets/rippled_versions.md' %} \ No newline at end of file diff --git a/content/references/protocol/transactions/types/xchainaddaccountcreateattestation.md b/content/references/protocol/transactions/types/xchainaddaccountcreateattestation.md new file mode 100644 index 0000000000..b3a534849a --- /dev/null +++ b/content/references/protocol/transactions/types/xchainaddaccountcreateattestation.md @@ -0,0 +1,83 @@ +--- +html: xchainaddaccountcreateattestation.html +parent: transaction-types.html +blurb: The `XChainAddAccountCreateAttestation` transaction provides an attestation from a witness server that a `XChainAccountCreateCommit` transaction occurred on the other chain. +labels: + - Interoperability +status: not_enabled +--- +# XChainAddAccountCreateAttestation +[[Source]](https://github.com/XRPLF/rippled/blob/master/src/ripple/protocol/impl/TxFormats.cpp#L447-L464 "Source") + +_(Requires the [XChainBridge amendment][] :not_enabled:)_ + +The `XChainAddAccountCreateAttestation` transaction provides an attestation from a witness server that an `XChainAccountCreateCommit` transaction occurred on the other chain. + +The signature must be from one of the keys on the door's signer list at the time the signature was provided. If the signature list changes between the time the signature was submitted and the quorum is reached, the new signature set is used and some of the currently collected signatures may be removed. + +Any account can submit signatures. + +**Note:** The reward is only sent to accounts that have keys on the current list. A quorum of signers need to agree on the `SignatureReward`, the same way they need to agree on the other data. A single witness server can't provide an incorrect value for this in an attempt to collect a larger reward. + + +## Example XChainAddAccountCreateAttestation JSON + +```json +{ + "Account": "rDr5okqGKmMpn44Bbhe5WAfDQx8e9XquEv", + "TransactionType": "XChainAddAccountCreateAttestation", + "OtherChainSource": "rUzB7yg1LcFa7m3q1hfrjr5w53vcWzNh3U", + "Destination": "rJMfWNVbyjcCtds8kpoEjEbYQ41J5B6MUd", + "Amount": "2000000000", + "PublicKey": "EDF7C3F9C80C102AF6D241752B37356E91ED454F26A35C567CF6F8477960F66614", + "Signature": "F95675BA8FDA21030DE1B687937A79E8491CE51832D6BEEBC071484FA5AF5B8A0E9AFF11A4AA46F09ECFFB04C6A8DAE8284AF3ED8128C7D0046D842448478500", + "WasLockingChainSend": 1, + "AttestationRewardAccount": "rpFp36UHW6FpEcZjZqq5jSJWY6UCj3k4Es", + "AttestationSignerAccount": "rpWLegmW9WrFBzHUj7brhQNZzrxgLj9oxw", + "XChainAccountCreateCount": "2", + "SignatureReward": "204", + "XChainBridge": { + "LockingChainDoor": "r3nCVTbZGGYoWvZ58BcxDmiMUU7ChMa1eC", + "LockingChainIssue": { + "currency": "XRP" + }, + "IssuingChainDoor": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh", + "IssuingChainIssue": { + "currency": "XRP" + } + }, + "Fee": "20" +} +``` + + +## XChainAddAccountCreateAttestation Fields + +| Field | JSON Type | Internal Type | Required? | Description | +|:---------------------------|:------------------|:------------------|:----------|:------------| +| `Amount` | `Currency Amount` | `AMOUNT` | Yes | The amount committed by the `XChainAccountCreateCommit` transaction on the source chain. | +| `AttestationRewardAccount` | `string` | `ACCOUNT` | Yes | The account that should receive this signer's share of the `SignatureReward`. | +| `AttestationSignerAccount` | `string` | `ACCOUNT` | Yes | The account on the door account's signer list that is signing the transaction. | +| `Destination` | `string` | `ACCOUNT` | Yes | The destination account for the funds on the destination chain. | +| `OtherChainSource` | `string` | `ACCOUNT` | Yes | The account on the source chain that submitted the `XChainAccountCreateCommit` transaction that triggered the event associated with the attestation. | +| `PublicKey` | `string` | `BLOB` | Yes | The public key used to verify the signature. | +| `Signature` | `string` | `BLOB` | Yes | The signature attesting to the event on the other chain. | +| `SignatureReward` | `Currency Amount` | `AMOUNT` | Yes | The signature reward paid in the `XChainAccountCreateCommit` transaction. | +| `WasLockingChainSend` | `number` | `UINT8` | Yes | A boolean representing the chain where the event occurred. | +| `XChainAccountCreateCount` | `string` | `UINT64` | Yes | The counter that represents the order that the claims must be processed in. | +| `XChainBridge` | `XChainBridge` | `XCHAIN_BRIDGE` | Yes | The bridge associated with the attestation. | + + +### XChainBridge Fields + +| Field | JSON Type | Internal Type | Required? | Description | +|:--------------------|:----------|:------------------|:----------|:----------------| +| `IssuingChainDoor` | `string` | `ACCOUNT` | Yes | The door account on the issuing chain. For an XRP-XRP bridge, this must be the genesis account (the account that is created when the network is first started, which contains all of the XRP). | +| `IssuingChainIssue` | `Issue` | `ISSUE` | Yes | The asset that is minted and burned on the issuing chain. For an IOU-IOU bridge, the issuer of the asset must be the door account on the issuing chain, to avoid supply issues. | +| `LockingChainDoor` | `string` | `ACCOUNT` | Yes | The door account on the locking chain. | +| `LockingChainIssue` | `Issue` | `ISSUE` | Yes | The asset that is locked and unlocked on the locking chain. | + + +{% include '_snippets/rippled-api-links.md' %} +{% include '_snippets/tx-type-links.md' %} +{% include '_snippets/rippled_versions.md' %} \ No newline at end of file diff --git a/content/references/protocol/transactions/types/xchainaddclaimattestation.md b/content/references/protocol/transactions/types/xchainaddclaimattestation.md new file mode 100644 index 0000000000..e6e65fa77e --- /dev/null +++ b/content/references/protocol/transactions/types/xchainaddclaimattestation.md @@ -0,0 +1,103 @@ +--- +html: xchainaddclaimattestation.html +parent: transaction-types.html +blurb: Submit proof (attestation) to the destination chain that an event that happened on the source chain. +labels: + - Interoperability +status: not_enabled +--- +# XChainAddClaimAttestation +[[Source]](https://github.com/XRPLF/rippled/blob/master/src/ripple/protocol/impl/TxFormats.cpp#L429-L445 "Source") + +_(Requires the [XChainBridge amendment][] :not_enabled:)_ + +The `XChainAddClaimAttestation` transaction provides proof from a witness server, attesting to an `XChainCommit` transaction. + +The signature must be from one of the keys on the door's signer list at the time the signature was provided. However, if the signature list changes between the time the signature was submitted and the quorum is reached, the new signature set is used and some of the currently collected signatures may be removed. + +Any account can submit signatures. + +**Note:** The reward is only sent to accounts that have keys on the current list. A quorum of signers need to agree on the `SignatureReward`, the same way they need to agree on the other data. A single witness server can't provide an incorrect value for this in an attempt to collect a larger reward. + + +## Example XChainAddClaimAttestation JSON + +```json +{ + "TransactionType": "XChainAddClaimAttestation", + "Account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh", + "XChainAttestationBatch": { + "XChainBridge": { + "IssuingChainDoor": "rKeSSvHvaMZJp9ykaxutVwkhZgWuWMLnQt", + "IssuingChainIssue": { + "currency": "XRP" + }, + "LockingChainDoor": "rJvExveLEL4jNDEeLKCVdxaSCN9cEBnEQC", + "LockingChainIssue": { + "currency": "XRP" + } + }, + "XChainClaimAttestationBatch" : [ + { + "XChainClaimAttestationBatchElement" : { + "Account" : "rnJmYAiqEVngtnb5ckRroXLtCbWC7CRUBx", + "Amount" : "100000000", + "AttestationSignerAccount" : "rnJmYAiqEVngtnb5ckRroXLtCbWC7CRUBx", + "Destination" : "r9A8UyNpW3X46FUc6P7JZqgn6WgAPjBwPg", + "PublicKey" : "03DAB289CA36FF377F3F4304C7A7203FDE5EDCBFC209F430F6A4355361425526D0", + "Signature" : "616263", + "WasLockingChainSend" : 1, + "XChainClaimID" : "0000000000000000" + } + } + ], + "XChainCreateAccountAttestationBatch": [ + { + "XChainCreateAccountAttestationBatchElement": { + "Account": "rnJmYAiqEVngtnb5ckRroXLtCbWC7CRUBx", + "Amount": "1000000000", + "AttestationSignerAccount": "rEziJZmeZzsJvGVUmpUTey7qxQLKYxaK9f", + "Destination": "rKT9gDkaedAosiHyHZTjyZs2HvXpzuiGmC", + "PublicKey": "03ADB44CA8E56F78A0096825E5667C450ABD5C24C34E027BC1AAF7E5BD114CB5B5", + "Signature": "3044022036C8B90F85E8073C465F00625248A72D4714600F98EBBADBAD3B7ED226109A3A02204C5A0AE12D169CF790F66541F3DB59C289E0D9CA7511FDFE352BB601F667A26", + "SignatureReward": "1000000", + "WasLockingChainSend": 1, + "XChainAccountCreateCount": "0000000000000001" + } + } + ] + } +} +``` + + +## XChainAddClaimAttestation Fields + +| Field | JSON Type | Internal Type | Required? | Description | +|:---------------------------|:------------------|:------------------|:----------|-------------| +| `Amount` | `Currency Amount` | `AMOUNT` | Yes | The amount committed by the `XChainCommit` transaction on the source chain. | +| `AttestationRewardAccount` | `string` | `ACCOUNT` | Yes | The account that should receive this signer's share of the `SignatureReward`. | +| `AttestationSignerAccount` | `string` | `ACCOUNT` | Yes | The account on the door account's signer list that is signing the transaction. | +| `Destination` | `string` | `ACCOUNT` | No | The destination account for the funds on the destination chain (taken from the `XChainCommit` transaction). +| `OtherChainSource` | `string` | `ACCOUNT` | Yes | The account on the source chain that submitted the `XChainCommit` transaction that triggered the event associated with the attestation. +| `PublicKey` | `string` | `BLOB` | Yes | The public key used to verify the attestation signature. | +| `Signature` | `string` | `BLOB` | Yes | The signature attesting to the event on the other chain. | +| `WasLockingChainSend` | `number` | `UINT8` | Yes | A boolean representing the chain where the event occurred. | +| `XChainBridge` | `XChainBridge` | `XCHAIN_BRIDGE` | Yes | The bridge to use to transfer funds. | +| `XChainClaimID` | `string` | `UINT64` | Yes | The `XChainClaimID` associated with the transfer, which was included in the `XChainCommit` transaction. | + + +### XChainBridge Fields + +| Field | JSON Type | Internal Type | Required? | Description | +|:--------------------|:----------|:------------------|:----------|:----------------| +| `IssuingChainDoor` | `string` | `ACCOUNT` | Yes | The door account on the issuing chain. For an XRP-XRP bridge, this must be the genesis account (the account that is created when the network is first started, which contains all of the XRP). | +| `IssuingChainIssue` | `Issue` | `ISSUE` | Yes | The asset that is minted and burned on the issuing chain. For an IOU-IOU bridge, the issuer of the asset must be the door account on the issuing chain, to avoid supply issues. | +| `LockingChainDoor` | `string` | `ACCOUNT` | Yes | The door account on the locking chain. | +| `LockingChainIssue` | `Issue` | `ISSUE` | Yes | The asset that is locked and unlocked on the locking chain. | + + + +{% include '_snippets/rippled-api-links.md' %} +{% include '_snippets/tx-type-links.md' %} +{% include '_snippets/rippled_versions.md' %} \ No newline at end of file diff --git a/content/references/protocol/transactions/types/xchainclaim.md b/content/references/protocol/transactions/types/xchainclaim.md new file mode 100644 index 0000000000..28b0e0e269 --- /dev/null +++ b/content/references/protocol/transactions/types/xchainclaim.md @@ -0,0 +1,66 @@ +--- +html: xchainclaim.html +parent: transaction-types.html +blurb: Complete a cross-chain transfer of value by claiming the value on the destination chain. +labels: + - Interoperability +status: not_enabled +--- +# XChainClaim +[[Source]](https://github.com/XRPLF/rippled/blob/master/src/ripple/protocol/impl/TxFormats.cpp#L418-L427 "Source") + +_(Requires the [XChainBridge amendment][] :not_enabled:)_ + +The `XChainClaim` transaction completes a cross-chain transfer of value. It allows a user to claim the value on the destination chain - the equivalent of the value locked on the source chain. A user can only claim the value if they own the cross-chain claim ID associated with the value locked on the source chain (the `Account` field). The user can send the funds to anyone (the `Destination` field). This transaction is only needed if an `OtherChainDestination` isn't specified in the `XChainCommit` transaction, or if something goes wrong with the automatic transfer of funds. + +If the transaction succeeds in moving funds, the referenced `XChainOwnedClaimID` ledger object will be destroyed. This prevents transaction replay. If the transaction fails, the `XChainOwnedClaimID` won't be destroyed and the transaction can be re-run with different parameters. + + +## Example XChainClaim JSON + +```json +{ + "Account": "rahDmoXrtPdh7sUdrPjini3gcnTVYjbjjw", + "Amount": "10000", + "TransactionType": "XChainClaim", + "XChainClaimID": "13f", + "Destination": "rahDmoXrtPdh7sUdrPjini3gcnTVYjbjjw", + "XChainBridge": { + "LockingChainDoor": "rMAXACCrp3Y8PpswXcg3bKggHX76V3F8M4", + "LockingChainIssue": { + "currency": "XRP" + }, + "IssuingChainDoor": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh", + "IssuingChainIssue": { + "currency": "XRP" + } + } +} +``` + + +## XChainClaim Fields + +| Field | JSON Type | Internal Type | Required? | Description | +|:------------------------|:------------------|:------------------|:----------|-------------| +| `Amount` | `Currency Amount` | `AMOUNT` | Yes | The amount to claim on the destination chain. This must match the amount attested to on the attestations associated with this `XChainClaimID`. | +| `Destination` | `string` | `ACCOUNT` | Yes | The destination account on the destination chain. It must exist or the transaction will fail. However, if the transaction fails in this case, the sequence number and collected signatures won't be destroyed, and the transaction can be rerun with a different destination. | +| `DestinationTag` | `int` | `UINT32` | No | An integer destination tag. | +| `XChainBridge` | `XChainBridge` | `XCHAIN_BRIDGE` | Yes | The bridge to use for the transfer. | +| `XChainClaimID` | `string` | `UINT64` | Yes | The unique integer ID for the cross-chain transfer that was referenced in the corresponding `XChainCommit` transaction. | + + +### XChainBridge Fields + +| Field | JSON Type | Internal Type | Required? | Description | +|:--------------------|:----------|:------------------|:----------|:----------------| +| `IssuingChainDoor` | `string` | `ACCOUNT` | Yes | The door account on the issuing chain. For an XRP-XRP bridge, this must be the genesis account (the account that is created when the network is first started, which contains all of the XRP). | +| `IssuingChainIssue` | `Issue` | `ISSUE` | Yes | The asset that is minted and burned on the issuing chain. For an IOU-IOU bridge, the issuer of the asset must be the door account on the issuing chain, to avoid supply issues. | +| `LockingChainDoor` | `string` | `ACCOUNT` | Yes | The door account on the locking chain. | +| `LockingChainIssue` | `Issue` | `ISSUE` | Yes | The asset that is locked and unlocked on the locking chain. | + + + +{% include '_snippets/rippled-api-links.md' %} +{% include '_snippets/tx-type-links.md' %} +{% include '_snippets/rippled_versions.md' %} \ No newline at end of file diff --git a/content/references/protocol/transactions/types/xchaincommit.md b/content/references/protocol/transactions/types/xchaincommit.md new file mode 100644 index 0000000000..cfd47c9f1c --- /dev/null +++ b/content/references/protocol/transactions/types/xchaincommit.md @@ -0,0 +1,62 @@ +--- +html: xchaincommit.html +parent: transaction-types.html +blurb: Initiate a cross-chain transfer of value. +labels: + - Interoperability +status: not_enabled +--- +# XChainCommit +[[Source]](https://github.com/XRPLF/rippled/blob/master/src/ripple/protocol/impl/TxFormats.cpp#L408-L416 "Source") + +_(Requires the [XChainBridge amendment][] :not_enabled:)_ + +The `XChainCommit` is the second step in a cross-chain transfer. It puts assets into trust on the locking chain so that they can be wrapped on the issuing chain, or burns wrapped assets on the issuing chain so that they can be returned on the locking chain. + + +## Example XChainCommit JSON + +```json +{ + "Account": "rMTi57fNy2UkUb4RcdoUeJm7gjxVQvxzUo", + "TransactionType": "XChainCommit", + "XChainBridge": { + "LockingChainDoor": "rMAXACCrp3Y8PpswXcg3bKggHX76V3F8M4", + "LockingChainIssue": { + "currency": "XRP" + }, + "IssuingChainDoor": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh", + "IssuingChainIssue": { + "currency": "XRP" + } + }, + "Amount": "10000", + "XChainClaimID": "13f" +} +``` + + +## XChainCommit Fields + +| Field | JSON Type | Internal Type | Required? | Description | +|:------------------------|:------------------|:------------------|:----------|-------------| +| `Amount` | `Currency Amount` | `AMOUNT` | Yes | The asset to commit, and the quantity. This must match the door account's `LockingChainIssue` (if on the locking chain) or the door account's `IssuingChainIssue` (if on the issuing chain). | +| `OtherChainDestination` | `string` | `ACCOUNT` | No | The destination account on the destination chain. If this is not specified, the account that submitted the `XChainCreateClaimID` transaction on the destination chain will need to submit a `XChainClaim` transaction to claim the funds. | +| `XChainBridge` | `XChainBridge` | `XCHAIN_BRIDGE` | Yes | The bridge to use to transfer funds. | +| `XChainClaimID` | `string` | `UINT64` | Yes | The unique integer ID for a cross-chain transfer. This must be acquired on the destination chain (via a `XChainCreateClaimID` transaction) and checked from a validated ledger before submitting this transaction. If an incorrect sequence number is specified, the funds will be lost. | + + +### XChainBridge Fields + +| Field | JSON Type | Internal Type | Required? | Description | +|:--------------------|:----------|:------------------|:----------|:----------------| +| `IssuingChainDoor` | `string` | `ACCOUNT` | Yes | The door account on the issuing chain. For an XRP-XRP bridge, this must be the genesis account (the account that is created when the network is first started, which contains all of the XRP). | +| `IssuingChainIssue` | `Issue` | `ISSUE` | Yes | The asset that is minted and burned on the issuing chain. For an IOU-IOU bridge, the issuer of the asset must be the door account on the issuing chain, to avoid supply issues. | +| `LockingChainDoor` | `string` | `ACCOUNT` | Yes | The door account on the locking chain. | +| `LockingChainIssue` | `Issue` | `ISSUE` | Yes | The asset that is locked and unlocked on the locking chain. | + + + +{% include '_snippets/rippled-api-links.md' %} +{% include '_snippets/tx-type-links.md' %} +{% include '_snippets/rippled_versions.md' %} \ No newline at end of file diff --git a/content/references/protocol/transactions/types/xchaincreatebridge.md b/content/references/protocol/transactions/types/xchaincreatebridge.md new file mode 100644 index 0000000000..f59f17dd94 --- /dev/null +++ b/content/references/protocol/transactions/types/xchaincreatebridge.md @@ -0,0 +1,67 @@ +--- +html: xchaincreatebridge.html +parent: transaction-types.html +blurb: Create a bridge between two chains. +labels: + - Interoperability +status: not_enabled +--- +# XChainCreateBridge +[[Source]](https://github.com/XRPLF/rippled/blob/master/src/ripple/protocol/impl/TxFormats.cpp#L381-L388 "Source") + +_(Requires the [XChainBridge amendment][] :not_enabled:)_ + +The `XChainCreateBridge` transaction creates a new `Bridge` ledger object and defines a new cross-chain bridge entrance on the chain that the transaction is submitted on. It includes information about door accounts and assets for the bridge. + +The transaction must be submitted first by the locking chain door account. To set up a valid bridge, door accounts on both chains must submit this transaction, in addition to setting up witness servers. + +The complete production-grade setup would also include a `SignerListSet` transaction on the two door accounts for the witnesses’ signing keys, as well as disabling the door accounts’ master key. This ensures that the witness servers are truly in control of the funds. + +**Note:** Each door account can only have one bridge. This prevents the creation of duplicate bridges for the same asset, which can cause asset imbalances on either chain. + + +## Example XChainCreateBridge JSON + +```json +{ + "TransactionType": "XChainCreateBridge", + "Account": "rhWQzvdmhf5vFS35vtKUSUwNZHGT53qQsg", + "XChainBridge": { + "LockingChainDoor": "rhWQzvdmhf5vFS35vtKUSUwNZHGT53qQsg", + "LockingChainIssue": { + "currency": "XRP" + }, + "IssuingChainDoor": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh", + "IssuingChainIssue": { + "currency": "XRP" + } + }, + "SignatureReward": 200, + "MinAccountCreateAmount": 1000000 +} +``` + + +## XChainCreateBridge Fields + +| Field | JSON Type | Internal Type | Required? | Description | +|:-------------------------|:------------------|:------------------|:----------------|:------| +| `MinAccountCreateAmount` | `Currency Amount` | `AMOUNT` | No | The minimum amount, in XRP, required for a `XChainAccountCreateCommit` transaction. If this isn't present, the `XChainAccountCreateCommit` transaction will fail. This field can only be present on XRP-XRP bridges. | +| `SignatureReward` | `Currency Amount` | `AMOUNT` | Yes | The total amount to pay the witness servers for their signatures. This amount will be split among the signers. | +| `XChainBridge` | `XChainBridge` | `XCHAIN_BRIDGE` | Yes | The bridge (door accounts and assets) to create. | + + +### XChainBridge Fields + +| Field | JSON Type | Internal Type | Required? | Description | +|:--------------------|:----------|:------------------|:----------|:----------------| +| `IssuingChainDoor` | `string` | `ACCOUNT` | Yes | The door account on the issuing chain. For an XRP-XRP bridge, this must be the genesis account (the account that is created when the network is first started, which contains all of the XRP). | +| `IssuingChainIssue` | `Issue` | `ISSUE` | Yes | The asset that is minted and burned on the issuing chain. For an IOU-IOU bridge, the issuer of the asset must be the door account on the issuing chain, to avoid supply issues. | +| `LockingChainDoor` | `string` | `ACCOUNT` | Yes | The door account on the locking chain. | +| `LockingChainIssue` | `Issue` | `ISSUE` | Yes | The asset that is locked and unlocked on the locking chain. | + + + +{% include '_snippets/rippled-api-links.md' %} +{% include '_snippets/tx-type-links.md' %} +{% include '_snippets/rippled_versions.md' %} \ No newline at end of file diff --git a/content/references/protocol/transactions/types/xchaincreateclaimid.md b/content/references/protocol/transactions/types/xchaincreateclaimid.md new file mode 100644 index 0000000000..b68d574a25 --- /dev/null +++ b/content/references/protocol/transactions/types/xchaincreateclaimid.md @@ -0,0 +1,65 @@ +--- +html: xchaincreateclaimid.html +parent: transaction-types.html +blurb: Create a cross-chain claim ID that is used for a cross-chain transfer. +labels: + - Interoperability +status: not_enabled +--- +# XChainCreateClaimID +[[Source]](https://github.com/XRPLF/rippled/blob/master/src/ripple/protocol/impl/TxFormats.cpp#L399-L406 "Source") + +_(Requires the [XChainBridge amendment][] :not_enabled:)_ + +The `XChainCreateClaimID` transaction creates a new cross-chain claim ID that is used for a cross-chain transfer. A cross-chain claim ID represents *one* cross-chain transfer of value. + +This transaction is the first step of a cross-chain transfer of value and is submitted on the destination chain, not the source chain. + +It also includes the account on the source chain that locks or burns the funds on the source chain. + + +## Example XChainCreateClaimID JSON + +```json +{ + "Account": "rahDmoXrtPdh7sUdrPjini3gcnTVYjbjjw", + "OtherChainSource": "rMTi57fNy2UkUb4RcdoUeJm7gjxVQvxzUo", + "TransactionType": "XChainCreateClaimID", + "SignatureReward": "100", + "XChainBridge": { + "LockingChainDoor": "rMAXACCrp3Y8PpswXcg3bKggHX76V3F8M4", + "LockingChainIssue": { + "currency": "XRP" + }, + "IssuingChainDoor": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh", + "IssuingChainIssue": { + "currency": "XRP" + } + } +} +``` + + +## XChainCreateClaimID Fields + +| Field | JSON Type | Internal Type | Required? | Description | +|:-------------------|:------------------|:------------------|:----------|-------------| +| `OtherChainSource` | `string` | `ACCOUNT` | Yes | The account that must send the `XChainCommit` transaction on the source chain. | +| `SignatureReward` | `string` | `ACCOUNT` | Yes | The amount, in XRP, to reward the witness servers for providing signatures. This must match the amount on the `Bridge` ledger object. | +| `XChainBridge` | `XChainBridge` | `XCHAIN_BRIDGE` | Yes | The bridge to create the claim ID for. | + + +### XChainBridge Fields + +| Field | JSON Type | Internal Type | Required? | Description | +|:--------------------|:----------|:------------------|:----------|:----------------| +| `IssuingChainDoor` | `string` | `ACCOUNT` | Yes | The door account on the issuing chain. For an XRP-XRP bridge, this must be the genesis account (the account that is created when the network is first started, which contains all of the XRP). | +| `IssuingChainIssue` | `Issue` | `ISSUE` | Yes | The asset that is minted and burned on the issuing chain. For an IOU-IOU bridge, the issuer of the asset must be the door account on the issuing chain, to avoid supply issues. | +| `LockingChainDoor` | `string` | `ACCOUNT` | Yes | The door account on the locking chain. | +| `LockingChainIssue` | `Issue` | `ISSUE` | Yes | The asset that is locked and unlocked on the locking chain. | + + + +{% include '_snippets/rippled-api-links.md' %} +{% include '_snippets/tx-type-links.md' %} +{% include '_snippets/rippled_versions.md' %} \ No newline at end of file diff --git a/content/references/protocol/transactions/types/xchainmodifybridge.md b/content/references/protocol/transactions/types/xchainmodifybridge.md new file mode 100644 index 0000000000..e09a477204 --- /dev/null +++ b/content/references/protocol/transactions/types/xchainmodifybridge.md @@ -0,0 +1,75 @@ +--- +html: xchainmodifybridge.html +parent: transaction-types.html +blurb: Modify the parameters of a bridge. +labels: + - Interoperability +status: not_enabled +--- +# XChainModifyBridge +[[Source]](https://github.com/XRPLF/rippled/blob/develop/src/ripple/protocol/impl/TxFormats.cpp#L390-L397 "Source") + +_(Requires the [XChainBridge amendment][] :not_enabled:)_ + +The `XChainModifyBridge` transaction allows bridge managers to modify the parameters of the bridge. They can only change the `SignatureReward` and the `MinAccountCreateAmount`. + +This transaction must be sent by the door account and requires the entities that control the witness servers to coordinate and provide the signatures for this transaction. This coordination happens outside the ledger. + +**Note:** You can't modify the signer list for the bridge with this transaction. The signer list is on the door account itself and is changed in the same way signer lists are changed on accounts (via a `SignerListSet` transaction). + + +## Example XChainModifyBridge JSON + +```json +{ + "TransactionType": "XChainModifyBridge", + "Account": "rhWQzvdmhf5vFS35vtKUSUwNZHGT53qQsg", + "XChainBridge": { + "LockingChainDoor": "rhWQzvdmhf5vFS35vtKUSUwNZHGT53qQsg", + "LockingChainIssue": { + "currency": "XRP" + }, + "IssuingChainDoor": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh", + "IssuingChainIssue": { + "currency": "XRP" + } + }, + "SignatureReward": 200, + "MinAccountCreateAmount": 1000000 +} +``` + + +## XChainModifyBridge Fields + +| Field | JSON Type | Internal Type | Required? | Description | +|:-------------------------|:------------------|:------------------|:----------|-------------| +| `Flags` | `number` | `UINT32` | Yes | Specifies the flags for this transaction. | +| `MinAccountCreateAmount` | `Currency Amount` | `AMOUNT` | No | The minimum amount, in XRP, required for a `XChainAccountCreateCommit` transaction. If this is not present, the `XChainAccountCreateCommit` transaction will fail. This field can only be present on XRP-XRP bridges. | +| `SignatureReward` | `Currency Amount` | `AMOUNT` | No | The signature reward split between the witnesses for submitting attestations. | +| `XChainBridge` | `XChainBridge` | `XCHAIN_BRIDGE` | Yes | The bridge to modify. | + + +### XChainBridge Fields + +| Field | JSON Type | Internal Type | Required? | Description | +|:--------------------|:----------|:------------------|:----------|:----------------| +| `IssuingChainDoor` | `string` | `ACCOUNT` | Yes | The door account on the issuing chain. For an XRP-XRP bridge, this must be the genesis account (the account that is created when the network is first started, which contains all of the XRP). | +| `IssuingChainIssue` | `Issue` | `ISSUE` | Yes | The asset that is minted and burned on the issuing chain. For an IOU-IOU bridge, the issuer of the asset must be the door account on the issuing chain, to avoid supply issues. | +| `LockingChainDoor` | `string` | `ACCOUNT` | Yes | The door account on the locking chain. | +| `LockingChainIssue` | `Issue` | `ISSUE` | Yes | The asset that is locked and unlocked on the locking chain. | + + +## Transaction Flags + +In addition to the universal transaction flags that are applicable to all transactions, you can specify this flag: + +| Flag Name | Flag Value | Description | +|------------------------------|--------------|-------------| +| `tfClearAccountCreateAmount` | `0x00010000` | Clears the `MinAccountCreateAmount` of the bridge. | + + + +{% include '_snippets/rippled-api-links.md' %} +{% include '_snippets/tx-type-links.md' %} +{% include '_snippets/rippled_versions.md' %} \ No newline at end of file diff --git a/content/resources/known-amendments.md b/content/resources/known-amendments.md index d7cd7f2182..90a73b16c0 100644 --- a/content/resources/known-amendments.md +++ b/content/resources/known-amendments.md @@ -16,6 +16,7 @@ The following is a comprehensive list of all known [amendments](amendments.html) | Name | Introduced | Status | |:----------------------------------|:-----------|:------------------------------| +| [XChainBridge][] | v2.0.0 | [Open for Voting: 2023-12-04](https://xrpl.org/blog/2023/rippled-2.0.0.html "BADGE_80d0e0") | | [AMM][] | v1.12.0 | [Open for Voting: 2023-09-06](https://xrpl.org/blog/2023/rippled-1.12.0.html "BADGE_80d0e0") | | [Clawback][] | v1.12.0 | [Open for Voting: 2023-09-06](https://xrpl.org/blog/2023/rippled-1.12.0.html "BADGE_80d0e0") | | [XRPFees][] | v1.10.0 | [Open for Voting: 2023-03-14](https://xrpl.org/blog/2023/rippled-1.10.0.html "BADGE_80d0e0") | @@ -82,7 +83,6 @@ The following is a list of [amendments](amendments.html) that are being develope | Name | Status | Additional Information | |:----------------------------------|:------------------------------------------|:-------------------------------| | [Hooks][] | [In Development: TBD]( "BADGE_LIGHTGREY") | [XRPL Hooks](https://hooks.xrpl.org/) | -| [XChainBridge][] | [In Development: TBD]( "BADGE_LIGHTGREY") | [XLS-38d](https://github.com/XRPLF/XRPL-Standards/blob/master/XLS-38d-XChainBridge/README.md) [Documentation](https://opensource.ripple.com/docs/xls-38d-cross-chain-bridge/cross-chain-bridges/) | | [OwnerPaysFee][] | [In Development: TBD]( "BADGE_LIGHTGREY") | | **Tip:** This list is updated manually. If you're working on an amendment and have a private network to test the changes, you can edit this page to add your in-development amendment to this list. For more information on contributing to the XRP Ledger, see [Contribute Code to the XRP Ledger](contribute-code-flow.html). @@ -193,11 +193,30 @@ See [Clawback](https://opensource.ripple.com/docs/clawback/clawback-of-issued-cu | Amendment | XChainBridge | |:-------------|:-----------------| | Amendment ID | C98D98EE9616ACD36E81FDEB8D41D349BF5F1B41DD64A0ABC1FE9AA5EA267E9C | -| Status | In Development | +| Status | Open for Voting | | Default Vote (Latest stable release) | No | | Pre-amendment functionality retired? | No | -Adds "cross-chain bridges" for synchronizing assets between different networks, such as Mainnet and a sidechain. Standards draft: [XLS-38d Cross-Chain Bridge](https://github.com/XRPLF/XRPL-Standards/blob/master/XLS-38d-XChainBridge/README.md). +Adds cross-chain bridges, enabling the transfer of digital assets between networks, such as Mainnet and a sidechain. + +Adds new transactions: + +- XChainAccountCreateCommit - Create a new account for a witness server to submit transactions on an issuing chain.. +- XChainAddAccountCreateAttestation - Provide an attestation that an account was created for a witness server to use. +- XChainAddClaimAttestation - Provide an attestation that assets were locked on a locking chain. +- XChainClaim - Claim assets on the destination chain. +- XChainCommit - Locks assets on the locking chain. +- XChainCreateBridge - Create a bridge ledger object. +- XChainCreateClaimID - Create a new cross-chain claim ID that is used for a cross-chain transfer. +- XChainModifyBridge - Modify the parameters of a bridge. + +Adds new ledger entry types: + +- Bridge - A single cross-chain bridge that connects the XRP Ledger with another blockchain. +- XChainOwnedClaimID - A cross-chain transfer of value that includes information of the account on the source chain that locks or burns the funds on the source chain. +- XChainOwnedCreateAccountClaimID - Collects attestations for creating an account via a cross-chain transfer. + +Adds several new transaction result codes. ### CryptoConditions diff --git a/content/tutorials/get-started/public-servers.md b/content/tutorials/get-started/public-servers.md index 31c378f14f..b9b5af9336 100644 --- a/content/tutorials/get-started/public-servers.md +++ b/content/tutorials/get-started/public-servers.md @@ -17,6 +17,7 @@ If you don't [run your own `rippled` server](install-rippled.html), you can use | Ripple[¹][] | Testnet | `https://s.altnet.rippletest.net:51234/` | `wss://s.altnet.rippletest.net:51233/` | Testnet public server | | XRPL Labs | Testnet | `https://testnet.xrpl-labs.com/` | `wss://testnet.xrpl-labs.com/` | Testnet public server with CORS support | | Ripple[¹][] | Devnet | `https://s.devnet.rippletest.net:51234/` | `wss://s.devnet.rippletest.net:51233/` | Devnet public server | +| Ripple[¹][] | Sidechain-Devnet | `https://sidechain-net2.devnet.rippletest.net:51234/` | `wss://sidechain-net2.devnet.rippletest.net:51233/` | Sidechain Devnet to test cross-chain bridge features. Devnet serves as the locking chain while this sidechain serves as the issuing chain. | | XRPL Labs | Xahau Testnet | `https://xahau-test.net/` | `wss://xahau-test.net/` | [Hooks-enabled](https://hooks.xrpl.org/) Xahau Testnet | [Network]: parallel-networks.html diff --git a/content/tutorials/tasks/use-xrpl-sidechains/index.md b/content/tutorials/tasks/use-xrpl-sidechains/index.md new file mode 100644 index 0000000000..b178d4e7a2 --- /dev/null +++ b/content/tutorials/tasks/use-xrpl-sidechains/index.md @@ -0,0 +1,8 @@ +--- +html: use-xrpl-sidechains.html +parent: tasks.html +template: pagetype-category.html.jinja +--- +# Use XRPL Sidechains + +Bridge XRP and tokens from _Mainnet_ to XRPL sidechains. \ No newline at end of file diff --git a/content/tutorials/tasks/use-xrpl-sidechains/set-up-iou-iou-bridge.md b/content/tutorials/tasks/use-xrpl-sidechains/set-up-iou-iou-bridge.md new file mode 100644 index 0000000000..973fc1e247 --- /dev/null +++ b/content/tutorials/tasks/use-xrpl-sidechains/set-up-iou-iou-bridge.md @@ -0,0 +1,168 @@ +--- +html: set-up-iou-iou-bridge.html +parent: use-xrpl-sidechains.html +blurb: Steps to set up an IOU-IOU bridge. +labels: + - Interoperability +--- +# Set Up an IOU-IOU Bridge + +_(Requires the [XChainBridge amendment][] :not_enabled:)_ + +Setting up an IOU-IOU bridge enables you to move tokens between chains. + +**Note**: The code samples on this page illustrate how to bridge a hypotethical "TST" token from *Devnet* to *Sidechain-Devnet*, using a supported [client library](client-libraries.html) to query and submit transactions. + +## Prerequisites + +- An XRP-XRP bridge must be set up between the locking and issuing chain. +- Ensure the witnesses' transaction submission accounts are funded on the locking and issuing chains. +- Set up an issuer on the issuing chain to mint and burn a wrapped version of the token you want to bridge. See: [Issue a Fungible Token](issue-a-fungible-token.html) + +## Steps + +### 1. Connect to the locking chain (Devnet) and issuing chain (Sidechain-Devnet). + +```javascript +const xrpl = require('xrpl') + +const WS_URL_lockingchain = 'wss://s.devnet.rippletest.net:51233/' // Locking chain +const WS_URL_issuingchain = 'wss://sidechain-net2.devnet.rippletest.net:51233/' // Issuing chain + +// Define the XChainBridge, using the "TST" token. +const xchainbridge = { + "LockingChainDoor": "rn895gh1MHnnAgL4hR9q464PJSFiYwQYcV", + "LockingChainIssue": { + "currency": "TST", + "issuer": "rP9jPyP5kyvFRb6ZiRghAGw5u8SGAmU4bd" + }, + "IssuingChainDoor": "ra1MsW5s6Qg4NXUAJVKw8f21ZghSYG1DQw", // Use the account issuing the wrapped token + "IssuingChainIssue": { + "currency": "TST", + "issuer": "ra1MsW5s6Qg4NXUAJVKw8f21ZghSYG1DQw" + } +} + +async function main() { + // Define the network clients. + const client_lockingchain = new xrpl.Client(WS_URL_lockingchain) + await client_lockingchain.connect() + + const client_issuingchain = new xrpl.Client(WS_URL_issuingchain) + await client_issuingchain.connect() + + // ... custom code goes here + + // Disconnect when done (If you omit this, Node.js won't end the process) + await client_lockingchain.disconnect() + await client_issuingchain.disconnect() +} + +main() +``` + +### 2. Submit an `XChainCreateBridge` transaction from the door account on the locking chain. + +Don't include a `MinAccountCreateAmount` value. + +```javascript + const wallet_lockingchain = xrpl.Wallet.fromSeed('s████████████████████████████') // Locking chain door account + const xchaincreatebridge_lockingchain = await client_lockingchain.submitAndWait({ + "TransactionType": "XChainCreateBridge", + "Account": wallet_lockingchain.address, + "XChainBridge": xchainbridge, + "SignatureReward": 200 + }, {autofill: true, wallet: wallet_lockingchain}) +``` + +### 3. Submit a `SignerListSet` transaction from the door account on the locking chain. + +```javascript + const signerlistset_lockingchain = await client_lockingchain.submitAndWait({ + "TransactionType": "SignerListSet", + "Account": wallet_lockingchain.address, + "Fee": "12", + "SignerQuorum": 2, + // Use the witness servers' submitting accounts on the locking chain. + "SignerEntries": [ + { + "SignerEntry": { + "Account": "rsA2LpzuawewSBQXkiju3YQTMzW13pAAdW", + "SignerWeight": 1 + } + }, + { + "SignerEntry": { + "Account": "rUpy3eEg8rqjqfUoLeBnZkscbKbFsKXC3v", + "SignerWeight": 1 + } + } + ] + }, {autofill: true, wallet: wallet_lockingchain}) +``` + +### 4. Disable the master key on the locking chain's door account with an `AccountSet` transaction. + +```javascript +const disablekey_lockingchain = await client_lockingchain.submitAndWait({ + "TransactionType": "AccountSet", + "Account": wallet_lockingchain.address, + "SetFlag": 4 + }, {autofill: true, wallet: wallet_lockingchain}) +``` + +### 5. Submit an `XChainCreateBridge` transaction from the door account on the issuing chain. + +Don't include a `MinAccountCreateAmount` value. + +```javascript + const wallet_issuingchain = xrpl.Wallet.fromSeed('s████████████████████████████') // The account issuing the wrapped token + const xchaincreatebridge_issuingchain = await client_issuingchain.submitAndWait({ + "TransactionType": "XChainCreateBridge", + "Account": wallet_issuingchain.address, + "XChainBridge": xchainbridge, + "SignatureReward": 200 + }, {autofill: true, wallet: wallet_issuingchain}) +``` + +### 6. Submit a `SignerListSet` transaction from the door account on the issuing chain. + +```javascript + const signerlistset_issuingchain = await client_issuingchain.submitAndWait({ + "TransactionType": "SignerListSet", + "Account": wallet_issuingchain.address, + "Fee": "12", + "SignerQuorum": 2, + // Use the witness servers' submitting accounts on the issuing chain. + "SignerEntries": [ + { + "SignerEntry": { + "Account": "rD323VyRjgzzhY4bFpo44rmyh2neB5d8Mo", + "SignerWeight": 1 + } + }, + { + "SignerEntry": { + "Account": "rJMfWNVbyjcCtds8kpoEjEbYQ41J5B6MUd", + "SignerWeight": 1 + } + } + ] + }, {autofill: true, wallet: wallet_issuingchain}) +``` + +### 7. Disable the master key on the issuing chain's door account with an `AccountSet` transaction. + +```javascript +const disablekey_issuingchain = await client_issuingchain.submitAndWait({ + "TransactionType": "AccountSet", + "Account": wallet_issuingchain.address, + "SetFlag": 4 + }, {autofill: true, wallet: wallet_issuingchain}) +``` + + + +{% include '_snippets/rippled-api-links.md' %} +{% include '_snippets/tx-type-links.md' %} +{% include '_snippets/rippled_versions.md' %} \ No newline at end of file diff --git a/content/tutorials/tasks/use-xrpl-sidechains/set-up-xrp-xrp-bridge.md b/content/tutorials/tasks/use-xrpl-sidechains/set-up-xrp-xrp-bridge.md new file mode 100644 index 0000000000..b67071e5da --- /dev/null +++ b/content/tutorials/tasks/use-xrpl-sidechains/set-up-xrp-xrp-bridge.md @@ -0,0 +1,234 @@ +--- +html: set-up-xrp-xrp-bridge.html +parent: use-xrpl-sidechains.html +blurb: Steps to create an XRP-XRP bridge with a new sidechain. +labels: + - Interoperability +--- +# Set Up an XRP-XRP Bridge + +_(Requires the [XChainBridge amendment][] :not_enabled:)_ + +Setting up an XRP-XRP bridge enables you to move XRP between chains. The set up requires using the genesis account on the issuing chain as a door account to submit attestations and create transaction submission accounts for witnesses. + +**Note**: The code samples on this page illustrate how a bridge was set up between *Devnet* and *Sidechain-Devnet*, using a supported [client library](client-libraries.html) to query and submit transactions. This bridge is already created, so the process can't be reproduced on these networks. + + +## Prerequisites + +- The issuing chain is set up and active. Validators must be running and successfully closing ledgers. +- The witnesses' accounts on the locking chain are funded, so they can submit transactions. +- A door account for the bridge exists on the locking chain. + + +## Steps + +### 1. Connect to the locking chain (Devnet) and issuing chain (Sidechain-Devnet). + +```javascript +const xrpl = require('xrpl') + +const WS_URL_lockingchain = 'wss://s.devnet.rippletest.net:51233/' // Locking chain +const WS_URL_issuingchain = 'wss://sidechain-net2.devnet.rippletest.net:51233/' // Issuing chain + +// Define the XChainBridge +const xchainbridge = { + "LockingChainDoor": "rnQAXXWoFNN6PEqwqsdTngCtFPCrmfuqFJ", // Locking chain door account + "LockingChainIssue": { + "currency": "XRP" + }, + "IssuingChainDoor": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh", // Use the genesis address hardcoded in rippled + "IssuingChainIssue": { + "currency": "XRP" + } +} + +async function main() { + // Define the network clients. + const client_lockingchain = new xrpl.Client(WS_URL_lockingchain) + await client_lockingchain.connect() + + const client_issuingchain = new xrpl.Client(WS_URL_issuingchain) + await client_issuingchain.connect() + + // ... custom code goes here + + // Disconnect when done (If you omit this, Node.js won't end the process) + await client_lockingchain.disconnect() + await client_issuingchain.disconnect() +} + +main() +``` + +### 2. Submit an `XChainCreateBridge` transaction from the door account on the locking chain. + +```javascript + const wallet_lockingchain = xrpl.Wallet.fromSeed('s████████████████████████████') // Locking chain door account + const xchaincreatebridge_lockingchain = await client_lockingchain.submitAndWait({ + "TransactionType": "XChainCreateBridge", + "Account": wallet_lockingchain.address, + "XChainBridge": xchainbridge, + "SignatureReward": 200, + "MinAccountCreateAmount": 1000000 // This value should at least be equal to the account reserve on the issuing chain. + }, {autofill: true, wallet: wallet_lockingchain}) +``` + +### 3. Submit a `SignerListSet` transaction from the door account on the locking chain. + +```javascript + const signerlistset_lockingchain = await client_lockingchain.submitAndWait({ + "TransactionType": "SignerListSet", + "Account": wallet_lockingchain.address, + "Fee": "12", + "SignerQuorum": 2, + // Use the witness servers' submitting accounts on the locking chain. + "SignerEntries": [ + { + "SignerEntry": { + "Account": "rsA2LpzuawewSBQXkiju3YQTMzW13pAAdW", + "SignerWeight": 1 + } + }, + { + "SignerEntry": { + "Account": "rUpy3eEg8rqjqfUoLeBnZkscbKbFsKXC3v", + "SignerWeight": 1 + } + } + ] + }, {autofill: true, wallet: wallet_lockingchain}) +``` + +### 4. Disable the master key on the locking chain's door account with an `AccountSet` transaction. + +```javascript +const disablekey_lockingchain = await client_lockingchain.submitAndWait({ + "TransactionType": "AccountSet", + "Account": wallet_lockingchain.address, + "SetFlag": 4 + }, {autofill: true, wallet: wallet_lockingchain}) +``` + +### 5. Submit an `XChainCreateBridge` transaction from the genesis account on the issuing chain. + +```javascript + const wallet_issuingchain = xrpl.Wallet.fromSeed('snoPBrXtMeMyMHUVTgbuqAfg1SUTb') // Use the genesis secret hardcoded in rippled. + const xchaincreatebridge_issuingchain = await client_issuingchain.submitAndWait({ + "TransactionType": "XChainCreateBridge", + "Account": wallet_issuingchain.address, + "XChainBridge": xchainbridge, + "SignatureReward": 200, + "MinAccountCreateAmount": 1000000 + }, {autofill: true, wallet: wallet_issuingchain}) +``` + +### 6. Submit `XChainAccountCreateCommit` transactions from the witnesses' locking chain accounts to create corresponding accounts on the issuing chain. + +```javascript + const wallet_witness_1 = xrpl.Wallet.fromSeed('s████████████████████████████') // Witness server 1 from `SignerListSet`: rsA2LpzuawewSBQXkiju3YQTMzW13pAAdW + const wallet_witness_2 = xrpl.Wallet.fromSeed('s████████████████████████████') // Witness server 2 from `SignerListSet`: rUpy3eEg8rqjqfUoLeBnZkscbKbFsKXC3v + + const xchainaccountcreatecommit_witness_1 = await client_lockingchain.submitAndWait({ + "TransactionType": "XChainAccountCreateCommit", + "Account": wallet_witness_1.address, + "Destination": "rD323VyRjgzzhY4bFpo44rmyh2neB5d8Mo", // The account to create and fund for witness 1 on the issuing chain. + "TransactionType": "XChainAccountCreateCommit", + "Amount": "20000000", + "SignatureReward": "100", + "XChainBridge": xchainbridge + }, {autofill: true, wallet: wallet_witness_1}) + + const xchainaccountcreatecommit_witness_2 = await client_lockingchain.submitAndWait({ + "TransactionType": "XChainAccountCreateCommit", + "Account": wallet_witness_2.address, + "Destination": "rJMfWNVbyjcCtds8kpoEjEbYQ41J5B6MUd", // The account to create and fund for witness 2 on the issuing chain. + "TransactionType": "XChainAccountCreateCommit", + "Amount": "20000000", + "SignatureReward": "100", + "XChainBridge": xchainbridged + }, {autofill: true, wallet: wallet_witness_1}) +``` + +### 7. Submit attestations for each `XChainAccountCreateCommit` transaction. + +Use the `XChainAddAccountCreateAttestation` transaction to submit each attestation on the issuing chain. Sign these transactions with the genesis account on the issuing chain. + +```javascript + // Witness 1 attestation + const xchainaddaccountcreateattestation_witness_1 = await client_issuingchain.submitAndWait({ + "TransactionType": "XChainAddAccountCreateAttestation", + "Account": wallet_issuingchain.address, + "OtherChainSource": wallet_witness_1.address, + "Destination": "rD323VyRjgzzhY4bFpo44rmyh2neB5d8Mo", + "Amount": "2000000000", + "PublicKey": wallet_witness_1.publicKey, + "Signature": xchainaccountcreatecommit_witness_1.result.TxnSignature, + "WasLockingChainSend": 1, + "AttestationRewardAccount": "rD323VyRjgzzhY4bFpo44rmyh2neB5d8Mo", + "AttestationSignerAccount": wallet_witness_1.address, + "XChainAccountCreateCount": "1", + "SignatureReward": "204", + "XChainBridge": xchainbridge, + "Fee": "20" + }, {autofill: true, wallet: wallet_issuingchain}) + + // Witness 2 attestation + const xchainaddaccountcreateattestation_witness_2 = await client_issuingchain.submitAndWait({ + "TransactionType": "XChainAddAccountCreateAttestation", + "Account": wallet_issuingchain.address, + "OtherChainSource": wallet_witness_2.address, + "Destination": "rJMfWNVbyjcCtds8kpoEjEbYQ41J5B6MUd", + "Amount": "2000000000", + "PublicKey": wallet_witness_2.publicKey, + "Signature": xchainaccountcreatecommit_witness_2.result.TxnSignature, + "WasLockingChainSend": 1, + "AttestationRewardAccount": "rJMfWNVbyjcCtds8kpoEjEbYQ41J5B6MUd", + "AttestationSignerAccount": wallet_witness_2.address, + "XChainAccountCreateCount": "1", + "SignatureReward": "204", + "XChainBridge": xchainbridge, + "Fee": "20" + }, {autofill: true, wallet: wallet_issuingchain}) +``` + +### 8. Submit a `SignerListSet` transaction from the genesis account on the issuing chain. + +```javascript + const signerlistset_issuingchain = await client_issuingchain.submitAndWait({ + "TransactionType": "SignerListSet", + "Account": wallet_issuingchain.address, + "Fee": "12", + "SignerQuorum": 2, + // Use the witness servers' submitting accounts on the issuing chain created in step 7 + "SignerEntries": [ + { + "SignerEntry": { + "Account": "rD323VyRjgzzhY4bFpo44rmyh2neB5d8Mo", + "SignerWeight": 1 + } + }, + { + "SignerEntry": { + "Account": "rJMfWNVbyjcCtds8kpoEjEbYQ41J5B6MUd", + "SignerWeight": 1 + } + } + ] + }, {autofill: true, wallet: wallet_issuingchain}) +``` + +### 9. Disable the master key on the issuing chain's genesis account with an `AccountSet` transaction. + +```javascript +const disablekey_issuingchain = await client_issuingchain.submitAndWait({ + "TransactionType": "AccountSet", + "Account": wallet_issuingchain.address, + "SetFlag": 4 + }, {autofill: true, wallet: wallet_issuingchain}) +``` + + +{% include '_snippets/rippled-api-links.md' %} +{% include '_snippets/tx-type-links.md' %} +{% include '_snippets/rippled_versions.md' %} \ No newline at end of file diff --git a/content/tutorials/tasks/use-xrpl-sidechains/submit-cross-chain-transaction.md b/content/tutorials/tasks/use-xrpl-sidechains/submit-cross-chain-transaction.md new file mode 100644 index 0000000000..3213e433ce --- /dev/null +++ b/content/tutorials/tasks/use-xrpl-sidechains/submit-cross-chain-transaction.md @@ -0,0 +1,136 @@ +--- +html: submit-cross-chain-transactions.html +parent: use-xrpl-sidechains.html +blurb: Steps to submit a cross-chain transaction, using a bridge. +labels: + - Interoperability +--- +# Submit Cross-chain Transactions + +_(Requires the [XChainBridge amendment][] :not_enabled:)_ + +This tutorial explains how to create a test account on a locking chain (_Devent_), and transfer XRP to an issuing chain (_Sidechain-Devnet_), using a supported [client library](client-libraries.html) to query and submit transactions. Witness servers are already set up to monitor the XRP-XRP bridge and submit attestations. + +## Prerequisites + +- The locking and issuing chains are both up and running. +- The witness servers are up and running. +- Set up the XRP-XRP bridge. + + +## Steps + +### 1. Connect to the locking chain (Devnet) and issuing chain (Sidechain-Devnet). + +```javascript +const xrpl = require('xrpl') + +const WS_URL_lockingchain = 'wss://s.devnet.rippletest.net:51233/' // Locking chain +const WS_URL_issuingchain = 'wss://sidechain-net2.devnet.rippletest.net:51233/' // Issuing chain + +// Define the XChainBridge +const xchainbridge = { + "LockingChainDoor": "rnQAXXWoFNN6PEqwqsdTngCtFPCrmfuqFJ", // Locking chain door account + "LockingChainIssue": { + "currency": "XRP" + }, + "IssuingChainDoor": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh", // Use the genesis address hardcoded in rippled + "IssuingChainIssue": { + "currency": "XRP" + } +} + +async function main() { + // Define the network clients. + const client_lockingchain = new xrpl.Client(WS_URL_lockingchain) + await client_lockingchain.connect() + + const client_issuingchain = new xrpl.Client(WS_URL_issuingchain) + await client_issuingchain.connect() + + // ... custom code goes here + + // Disconnect when done (If you omit this, Node.js won't end the process) + await client_lockingchain.disconnect() + await client_issuingchain.disconnect() +} + +main() +``` + +### 2. Fund a wallet on Devnet and generate a wallet address for Sidechain-Devnet. + +```javascript + // Create a wallet and fund it using the XRP faucet on Devnet. + const wallet_lockingchain = (await client_lockingchain.fundWallet()).wallet + console.log(wallet_lockingchain.address) + + // Generate a wallet to create and fund on the issuing chain. + const wallet_issuingchain = await xrpl.Wallet.generate() + console.log(wallet_issuingchain.address) +``` + +### 3. Submit an `XChainAccountCreateCommit` transaction from the Devnet wallet. + +```javascript + const createwallet_issuingchain = await client_lockingchain.submitAndWait({ + "TransactionType": "XChainAccountCreateCommit", + "Account": wallet_lockingchain.address, + "Destination": wallet_issuingchain.address, + "XChainBridge": xchainbridge, + "SignatureReward": "100", + "Amount": "5000000000" + }, {autofill: true, wallet: wallet_lockingchain}) +``` + +### 4. Create a claim ID with `XChainCreateClaimID`, using your account on the issuing chain. + +```javascript + const createclaim = await client_issuingchain.submitAndWait({ + "TransactionType": "XChainCreateClaimID", + "Account": wallet_issuingchain.address, + "OtherChainSource": wallet_lockingchain.address, + "SignatureReward": "100", + "XChainBridge": xchainbridge + }, {autofill: true, wallet: wallet_issuingchain}) +``` + +### 5. Retrieve the claim ID from the transaction metadata. + +```javascript + let metadata = createclaim.result.meta.AffectedNodes + + let claimnode = null; + + for (const item of metadata) { + if (item.CreatedNode && item.CreatedNode.LedgerEntryType === 'XChainOwnedClaimID') { + claimnode = item.CreatedNode + break + } + } + + const claimID = claimnode.NewFields.XChainClaimID +``` + +### 6. Submit an `XChainCommit` transaction with the claim ID, using your account on the locking chain. + +If you don't specify an "OtherChainDestination", the account that submitted the `XChainCreateClaimID` transaction needs to submit an `XChainClaim` transaction to claim the funds. + +```javascript + const xchaincommit = await client_lockingchain.submitAndWait({ + "TransactionType": "XChainCommit", + "Account": wallet_lockingchain.address, + "OtherChainDestination": wallet_issuingchain.address, + "Amount": "10000", + "XChainBridge": xchainbridge, + "XChainClaimID": claimID + }, {autofill: true, wallet: wallet_lockingchain}) +``` + +**Note:** When enough `XChainAddClaimAttestation` signatures are submitted by the witness servers to reach quorum, the funds are released on the issuing chain to the `OtherChainDestination`. + + + +{% include '_snippets/rippled-api-links.md' %} +{% include '_snippets/tx-type-links.md' %} +{% include '_snippets/rippled_versions.md' %} \ No newline at end of file diff --git a/dactyl-config.yml b/dactyl-config.yml index 2e06a3f5ad..9ae9166966 100644 --- a/dactyl-config.yml +++ b/dactyl-config.yml @@ -1535,6 +1535,23 @@ pages: - ja + # XRPL Sidechains ----------------------------------------------------------- + + - md: concepts/xrpl-sidechains/xrpl-sidechains.md + targets: + - en + - ja + + - md: concepts/xrpl-sidechains/cross-chain-bridges.md + targets: + - en + - ja + + - md: concepts/xrpl-sidechains/witness-servers.md + targets: + - en + - ja + # Tutorials -------------------------------------------------------------------- @@ -2273,6 +2290,29 @@ pages: - en - ja + # Use XRPL Sidechains ---------------------------------------------------------- + + - md: tutorials/tasks/use-xrpl-sidechains/index.md + targets: + - en + - ja + + - md: tutorials/tasks/use-xrpl-sidechains/set-up-xrp-xrp-bridge.md + targets: + - en + - ja + + - md: tutorials/tasks/use-xrpl-sidechains/set-up-iou-iou-bridge.md + targets: + - en + - ja + + - md: tutorials/tasks/use-xrpl-sidechains/submit-cross-chain-transaction.md + targets: + - en + - ja + + # References ------------------------------------------------------------------- - name: References @@ -2413,6 +2453,11 @@ pages: targets: - ja + - md: references/protocol/ledger-data/ledger-entry-types/bridge.md + targets: + - en + - ja + - md: references/protocol/ledger-data/ledger-entry-types/check.md targets: - en @@ -2525,6 +2570,16 @@ pages: targets: - ja + - md: references/protocol/ledger-data/ledger-entry-types/xchainownedclaimid.md + targets: + - en + - ja + + - md: references/protocol/ledger-data/ledger-entry-types/xchainownedcreateaccountclaimid.md + targets: + - en + - ja + - md: references/protocol/transactions/index.md targets: - en @@ -2799,6 +2854,46 @@ pages: targets: - ja + - md: references/protocol/transactions/types/xchainaccountcreatecommit.md + targets: + - en + - ja + + - md: references/protocol/transactions/types/xchainaddaccountcreateattestation.md + targets: + - en + - ja + + - md: references/protocol/transactions/types/xchainaddclaimattestation.md + targets: + - en + - ja + + - md: references/protocol/transactions/types/xchainclaim.md + targets: + - en + - ja + + - md: references/protocol/transactions/types/xchaincommit.md + targets: + - en + - ja + + - md: references/protocol/transactions/types/xchaincreatebridge.md + targets: + - en + - ja + + - md: references/protocol/transactions/types/xchaincreateclaimid.md + targets: + - en + - ja + + - md: references/protocol/transactions/types/xchainmodifybridge.md + targets: + - en + - ja + - md: references/protocol/transactions/pseudo-transaction-types/pseudo-transaction-types.md targets: - en diff --git a/template/page-websocket-api-tool.html.jinja b/template/page-websocket-api-tool.html.jinja index 475765cbf6..4eb1ba7370 100644 --- a/template/page-websocket-api-tool.html.jinja +++ b/template/page-websocket-api-tool.html.jinja @@ -136,6 +136,13 @@ "shortname": "Devnet", "longname": "s.devnet.rippletest.net (Devnet Public Cluster)" }, + { + "id": "wstool-1-connection-sidechain-devnet", + "ws_url": "wss://sidechain-net2.devnet.rippletest.net:51233/", + "jsonrpc_url": "https://sidechain-net2.devnet.rippletest.net:51234/", + "shortname": "Sidechain-Devnet", + "longname": "sidechain-net2.devnet.rippletest.net (Issuing Sidechain Devnet Public Cluster)" + }, { "id": "wstool-1-connection-localhost", "ws_url": "ws://localhost:6006/", From 71c50b0514d62bcf2a81783a6d6bdea5030a865f Mon Sep 17 00:00:00 2001 From: mashharuki Date: Sun, 17 Dec 2023 15:44:39 +0900 Subject: [PATCH 03/25] add fully AMM sample codes --- .../_code-samples/create-amm/ts/create-amm.ts | 151 ++++ .../_code-samples/create-amm/ts/lib/amm.ts | 770 ++++++++++++++++++ .../create-amm/ts/util/consts.ts | 3 + 3 files changed, 924 insertions(+) create mode 100644 content/_code-samples/create-amm/ts/create-amm.ts create mode 100644 content/_code-samples/create-amm/ts/lib/amm.ts create mode 100644 content/_code-samples/create-amm/ts/util/consts.ts diff --git a/content/_code-samples/create-amm/ts/create-amm.ts b/content/_code-samples/create-amm/ts/create-amm.ts new file mode 100644 index 0000000000..9ce61dc4db --- /dev/null +++ b/content/_code-samples/create-amm/ts/create-amm.ts @@ -0,0 +1,151 @@ +'use strict' + +require('dotenv').config(); +var xrpl = require('xrpl') +// Configure console.log to print deeper into nested objects so you can +// better see properties of the AMM: +require('util').inspect.defaultOptions.depth = 5 +import { + AmmInfo, + TokenInfo, + acquireTokens, + bidAmm, + checkExistsAmm, + confirmAmm, + createAmm, + depositAmm, + getAmmcost, + get_new_token, + swap, + voteAmm, + withdrawAmm +} from './lib/amm'; +import { + WS_URL +} from './util/consts'; + +/** + * AMM機能を試すためのスクリプト + */ +async function main() { + const client = new xrpl.Client(WS_URL); + await client.connect() + + // Get credentials from the Faucet ------------------------------------------- + console.log("Requesting address from the faucet...") + // const wallet = (await client.fundWallet()).wallet + + // To use an existing account, use code such as the following: + const wallet = xrpl.Wallet.fromSeed(process.env.SECRET_FEED!) + + // Create New Token + const msh_amount = await get_new_token(client, wallet, "MSH", "10000") + // call get new token method (FOO トークンを発行) + const foo_amount = await get_new_token(client, wallet, "FOO", "1000") + + // Acquire tokens ------------------------------------------------------------ + await acquireTokens(client, wallet, msh_amount); + await acquireTokens(client, wallet, foo_amount); + + // create AMM Info + const amm_info_request: AmmInfo = { + "command": "amm_info", + "asset": { + "currency": msh_amount.currency!, + "issuer": msh_amount.issuer!, + }, + "asset2": { + "currency": foo_amount.currency!, + "issuer": foo_amount.issuer! + }, + "ledger_index": "validated" + } + + // Check if AMM already exists ---------------------------------------------- + await checkExistsAmm(client, amm_info_request, msh_amount, foo_amount); + + // Look up AMM transaction cost --------------------------------------------- + const amm_fee_drops = await getAmmcost(client); + + // Create AMM --------------------------------------------------------------- + // This example assumes that 15 TST ≈ 100 FOO in value. + await createAmm(client, wallet, msh_amount, foo_amount, amm_fee_drops) + + // Confirm that AMM exists -------------------------------------------------- + const { + account_lines_result: account_lines_result, + ammInfo: ammInfo + } = await confirmAmm(client, wallet, amm_info_request); + + // console.log("account_lines_result:", account_lines_result) + console.log("ammAddress:", ammInfo.issuer) + + // deposit AMM + await depositAmm(client, wallet, msh_amount, "15", foo_amount, "100") + // withdraw AMM + await withdrawAmm(client, wallet, msh_amount, "5", foo_amount, "5") + // BidAMM + await bidAmm(client, wallet, msh_amount, foo_amount, ammInfo) + // VoteAMM + await voteAmm(client, wallet, msh_amount, foo_amount, 500) + // Swap (payment Transaction) + await swap(client, wallet, ammInfo.issuer, msh_amount, foo_amount, "1", "2") + + // confirm AMM again + const { + account_lines_result: account_lines_result2, + } = await confirmAmm(client, wallet, amm_info_request); + + //console.log("account_lines_result2:", account_lines_result2) + + // ============= (another XRP pattern) =============== + + // create AMM Info (another XRP pattern) + const amm_info_request2: AmmInfo = { + "command": "amm_info", + "asset": { + "currency": msh_amount.currency!, + "issuer": msh_amount.issuer!, + }, + "asset2": { + "currency": "XRP", + "issuer": null + }, + "ledger_index": "validated" + } + + // create XRP Amount info + const xrpInfo: TokenInfo = { + "currency": null, + "value": "10000000", + "issuer": null + } + + // Check if AMM already exists ---------------------------------------------- + await checkExistsAmm(client, amm_info_request2, msh_amount, xrpInfo); + // Create AMM --------------------------------------------------------------- + // This example assumes that 15 TST ≈ 100 FOO in value. + await createAmm(client, wallet, msh_amount, xrpInfo, amm_fee_drops) + + // Confirm that AMM exists -------------------------------------------------- + const { + ammInfo: ammInfo2 + } = await confirmAmm(client, wallet, amm_info_request2); + + // console.log("account_lines_result:", account_lines_result) + console.log("ammAddress2:", ammInfo2.issuer) + // deposit AMM + await depositAmm(client, wallet, msh_amount, "15", xrpInfo, "10") + // withdraw AMM + await withdrawAmm(client, wallet, msh_amount, "5", xrpInfo, "5") + // Swap (payment Transaction) XRP ->> MSH + await swap(client, wallet, ammInfo2.issuer, msh_amount, xrpInfo, "1", "2000000") + // Swap (payment Transaction) MSH ->> XRP + await swap(client, wallet, ammInfo2.issuer, xrpInfo, msh_amount, "2000", "1") + + + // Disconnect when done ----------------------------------------------------- + await client.disconnect() +} + +main() \ No newline at end of file diff --git a/content/_code-samples/create-amm/ts/lib/amm.ts b/content/_code-samples/create-amm/ts/lib/amm.ts new file mode 100644 index 0000000000..3adda49ed5 --- /dev/null +++ b/content/_code-samples/create-amm/ts/lib/amm.ts @@ -0,0 +1,770 @@ +var xrpl = require('xrpl') +import { + EXPLORER +} from './../util/consts'; + +export type TokenInfo = { + "currency": string | null; + "value": string; + "issuer": string | null; +} + +export type AmmInfo = { + "command": string; + "asset": { + "currency": string; + "issuer": string; + }, + "asset2": { + "currency": string; + "issuer": string | null; + } | null, + "ledger_index": "validated" +} + +/** + * get token method + */ +export const acquireTokens = async( + client: any, + wallet: any, + token: TokenInfo, +) => { + try { + const offer_result = await client.submitAndWait({ + "TransactionType": "OfferCreate", + "Account": wallet.address, + "TakerPays": { + currency: token.currency, + issuer: token.issuer, + value: "1000" + }, + "TakerGets": xrpl.xrpToDrops(25*10*1.16) + }, { + autofill: true, + wallet: wallet + }) + + // get metaData & TransactionResult + const metaData: any = offer_result.result.meta!; + const transactionResult = metaData.TransactionResult; + + if (transactionResult == "tesSUCCESS") { + console.log(`MSH offer placed: ${EXPLORER}/transactions/${offer_result.result.hash}`) + const balance_changes = xrpl.getBalanceChanges(metaData) + + for (const bc of balance_changes) { + if (bc.account != wallet.address) {continue} + for (const bal of bc.balances) { + if (bal.currency == "MSH") { + console.log(`Got ${bal.value} ${bal.currency}.${bal.issuer}.`) + break + } + } + break + } + + } else { + throw `Error sending transaction: ${offer_result}` + } + } catch(err) { + console.error("Acquire tokens err: ", err) + } +}; + +/** + * check Amm pair is existed + */ +export const checkExistsAmm = async ( + client: any, + amm_info_request: AmmInfo, + token1Info: TokenInfo, + token2Info: TokenInfo, +) => { + + try { + const amm_info_result = await client.request(amm_info_request) + console.log(amm_info_result) + } catch(err: any) { + if (err.data.error === 'actNotFound') { + if(token2Info.issuer != null) { + console.log(`No AMM exists yet for the pair + ${token2Info.currency}.${token2Info.issuer} / + ${token1Info.currency}.${token1Info.issuer} + (This is probably as expected.)`) + } else { + console.log(`No AMM exists yet for the pair + XRP / + ${token1Info.currency}.${token1Info.issuer} + (This is probably as expected.)`) + } + } else { + throw(err) + } + } +}; + +/** + * get const info for craete carete AMM pair + */ +export const getAmmcost = async( + client: any +): Promise => { + const ss = await client.request({ + "command": "server_state" + }) + const amm_fee_drops = ss.result.state.validated_ledger!.reserve_inc.toString() + console.log(`Current AMMCreate transaction cost: ${xrpl.dropsToXrp(amm_fee_drops)} XRP`) + + return amm_fee_drops; +} + +/** + * create AMM method + */ +export const createAmm = async( + client: any, + wallet: any, + token1Info: TokenInfo, + token2Info: TokenInfo, + amm_fee_drops: string, +) => { + try { + var ammcreate_result; + if(token2Info.currency != null) { + ammcreate_result = await client.submitAndWait({ + "TransactionType": "AMMCreate", + "Account": wallet.address, + "Amount": { + currency: token1Info.currency, + issuer: token1Info.issuer, + value: "15" + }, + "Amount2": { + "currency": token2Info.currency, + "issuer": token2Info.issuer, + "value": "100" + }, + "TradingFee": 500, // 0.5% + "Fee": amm_fee_drops + }, { + autofill: true, + wallet: wallet, + failHard: true + }) + } else { + ammcreate_result = await client.submitAndWait({ + "TransactionType": "AMMCreate", + "Account": wallet.address, + "Amount": { + currency: token1Info.currency, + issuer: token1Info.issuer, + value: "15" + }, + "Amount2": token2Info.value, + "TradingFee": 500, // 0.5% + "Fee": amm_fee_drops + }, { + autofill: true, + wallet: wallet, + failHard: true + }) + } + + // get metaData & TransactionResult + const metaData: any = ammcreate_result.result.meta!; + const transactionResult = metaData.TransactionResult; + + // Use fail_hard so you don't waste the tx cost if you mess up + if (transactionResult == "tesSUCCESS") { + console.log(`AMM created: ${EXPLORER}/transactions/${ammcreate_result.result.hash}`) + } else { + throw `Error sending transaction: ${JSON.stringify(ammcreate_result)}` + } + } catch(err) { + console.error("create amm err:", err) + } +} + +/** + * confirm AMM method + */ +export const confirmAmm = async( + client: any, + wallet: any, + amm_info_request: AmmInfo +): Promise => { + try { + // get AMM info + const amm_info_result2 = await client.request(amm_info_request) + console.log("amm_info_result2:", amm_info_result2) + + const results = amm_info_result2.result as any; + + const lp_token = results.amm.lp_token + const amount = results.amm.amount + const amount2 = results.amm.amount2 + + const ammInfo: TokenInfo = { + "currency": lp_token.currency, + "issuer": lp_token.issuer, + "value": "0" + } + + console.log(`The AMM account ${lp_token.issuer} has ${lp_token.value} total + LP tokens outstanding, and uses the currency code ${lp_token.currency}.`) + if(amount2.currency != undefined) { + console.log(`In its pool, the AMM holds ${amount.value} ${amount.currency}.${amount.issuer} + and ${amount2.value} ${amount2.currency}.${amount2.issuer}`) + } else { + console.log(`In its pool, the AMM holds ${amount.value} ${amount.currency}.${amount.issuer} + and ${amount2} XRP`) + } + + // check balanse + const account_lines_result = await client.request({ + "command": "account_lines", + "account": wallet.address, + // Tip: To look up only the new AMM's LP Tokens, uncomment: + // "peer": lp_token.issuer, + "ledger_index": "validated" + }) + return { + account_lines_result, + ammInfo + }; + } catch(err) { + console.error("Check token balances err:", err) + return null; + } +} + +/** + * bid AMM method + */ +export const bidAmm = async( + client: any, + wallet: any, + token1Info: TokenInfo, + token2Info: TokenInfo, + ammInfo: TokenInfo +) => { + try { + const result = await client.submitAndWait({ + "TransactionType": "AMMBid", + "Account": wallet.address, + "Asset": { + currency: token1Info.currency, + issuer: token1Info.issuer, + }, + "Asset2": { + "currency": token2Info.currency, + "issuer": token2Info.issuer, + }, + "BidMax" : { + "currency" : ammInfo.currency, + "issuer" : ammInfo.issuer, + "value" : "5" + }, + }, { + autofill: true, + wallet: wallet, + failHard: true + }) + + // get metaData & TransactionResult + const metaData: any = result.result.meta!; + const transactionResult = metaData.TransactionResult; + + // Use fail_hard so you don't waste the tx cost if you mess up + if (transactionResult == "tesSUCCESS") { + console.log(`AMM bid: ${EXPLORER}/transactions/${result.result.hash}`) + } else { + throw `Error sending transaction: ${JSON.stringify(result)}` + } + } catch(err) { + console.error("error occuered while bidAmm:", err) + } +}; + +/** + * vote AMM method + */ +export const voteAmm = async( + client: any, + wallet: any, + token1Info: TokenInfo, + token2Info: TokenInfo, + tradingFee: number +) => { + try { + const result = await client.submitAndWait({ + "TransactionType": "AMMVote", + "Account": wallet.address, + "Asset": { + currency: token1Info.currency, + issuer: token1Info.issuer, + }, + "Asset2": { + "currency": token2Info.currency, + "issuer": token2Info.issuer, + }, + "TradingFee" : tradingFee, + }, { + autofill: true, + wallet: wallet, + failHard: true + }) + + // get metaData & TransactionResult + const metaData: any = result.result.meta!; + const transactionResult = metaData.TransactionResult; + + // Use fail_hard so you don't waste the tx cost if you mess up + if (transactionResult == "tesSUCCESS") { + console.log(`AMM vote: ${EXPLORER}/transactions/${result.result.hash}`) + } else { + throw `Error sending transaction: ${JSON.stringify(result)}` + } + } catch(err) { + console.error("error occuered while voteAmm:", err) + } +}; + +/** + * deposit AMM + */ +export const depositAmm = async( + client: any, + wallet: any, + token1Info: TokenInfo, + token1Amount: string, + token2Info: TokenInfo, + token2Amount: string, +) => { + try { + var result; + if(token2Info.currency != null) { + result = await client.submitAndWait({ + "TransactionType": "AMMDeposit", + "Account": wallet.address, + "Amount": { + "currency": token1Info.currency, + "issuer": token1Info.issuer, + "value": token1Amount + }, + "Amount2": { + "currency": token2Info.currency, + "issuer": token2Info.issuer, + "value": token2Amount + }, + "Asset": { + "currency": token1Info.currency, + "issuer": token1Info.issuer, + }, + "Asset2": { + "currency": token2Info.currency, + "issuer": token2Info.issuer, + }, + "Flags" : 1048576, + }, { + autofill: true, + wallet: wallet, + failHard: true + }) + } else { + result = await client.submitAndWait({ + "TransactionType": "AMMDeposit", + "Account": wallet.address, + "Amount": { + "currency": token1Info.currency, + "issuer": token1Info.issuer, + "value": token1Amount + }, + "Amount2": token2Amount, + "Asset": { + "currency": token1Info.currency, + "issuer": token1Info.issuer, + }, + "Asset2": { + "currency": "XRP" + }, + "Flags" : 1048576, + }, { + autofill: true, + wallet: wallet, + failHard: true + }) + } + + + // get metaData & TransactionResult + const metaData: any = result.result.meta!; + const transactionResult = metaData.TransactionResult; + + // Use fail_hard so you don't waste the tx cost if you mess up + if (transactionResult == "tesSUCCESS") { + console.log(`AMM deposit: ${EXPLORER}/transactions/${result.result.hash}`) + } else { + throw `Error sending transaction: ${JSON.stringify(result)}` + } + } catch(err) { + console.error("error occuered while depositAmm:", err) + } +}; + +/** + * Withdraw AMM + */ +export const withdrawAmm = async( + client: any, + wallet: any, + token1Info: TokenInfo, + token1Amount: string, + token2Info: TokenInfo, + token2Amount: string, +) => { + try { + var result; + + if(token2Info.currency != null) { + result = await client.submitAndWait({ + "TransactionType": "AMMWithdraw", + "Account": wallet.address, + "Amount": { + "currency": token1Info.currency, + "issuer": token1Info.issuer, + "value": token1Amount + }, + "Amount2": { + "currency": token2Info.currency, + "issuer": token2Info.issuer, + "value": token2Amount + }, + "Asset": { + "currency": token1Info.currency, + "issuer": token1Info.issuer, + }, + "Asset2": { + "currency": token2Info.currency, + "issuer": token2Info.issuer, + }, + "Fee" : "10", + "Flags" : 1048576, + }, { + autofill: true, + wallet: wallet, + failHard: true + }) + } else { + result = await client.submitAndWait({ + "TransactionType": "AMMWithdraw", + "Account": wallet.address, + "Amount": { + "currency": token1Info.currency, + "issuer": token1Info.issuer, + "value": token1Amount + }, + "Amount2": token2Amount, + "Asset": { + "currency": token1Info.currency, + "issuer": token1Info.issuer, + }, + "Asset2": { + "currency": "XRP" + }, + "Fee" : "10", + "Flags" : 1048576, + }, { + autofill: true, + wallet: wallet, + failHard: true + }) + } + + // get metaData & TransactionResult + const metaData: any = result.result.meta!; + const transactionResult = metaData.TransactionResult; + + // Use fail_hard so you don't waste the tx cost if you mess up + if (transactionResult == "tesSUCCESS") { + console.log(`AMM withdraw: ${EXPLORER}/transactions/${result.result.hash}`) + } else { + throw `Error sending transaction: ${JSON.stringify(result)}` + } + } catch(err) { + console.error("error occuered while withdrawAmm:", err) + } +}; + +/** + * Swap method + */ +export const swap = async( + client: any, + wallet: any, + ammAddress: string, + token1Info: TokenInfo, + token2Info: TokenInfo, + token1Value: string, + token2Value: string +) => { + client.on('path_find', (stream: any) => { + console.log(JSON.stringify(stream.alternatives, null, ' ')) + }) + // path find + var result; + + if(token1Info.currency != null && token2Info.currency != null) { + result = await client.request({ + command: 'path_find', + subcommand: 'create', + source_account: wallet.address, + source_amount: { + "currency": token2Info.currency, + "value": token2Value, + "issuer": token2Info.issuer + }, + destination_account: wallet.address, + destination_amount: { + "currency": token1Info.currency, + "value": token1Value, + "issuer": token1Info.issuer + } + }); + } else if(token2Info.currency == null) { + result = await client.request({ + command: 'path_find', + subcommand: 'create', + source_account: wallet.address, + source_amount: { + "currency": "XRP", + }, + destination_account: wallet.address, + destination_amount: { + "currency": token1Info.currency, + "value": token1Value, + "issuer": token1Info.issuer + } + }); + } + + console.log("path find:", result) + + // create swap transaction data + var swapTxData; + if(token1Info.currency != null && token2Info.currency != null) { + swapTxData = { + "TransactionType": "Payment", + "Account": wallet.address, + "Destination": wallet.address, + "Amount": { + "currency": token1Info.currency, + "value": token1Value, + "issuer": token1Info.issuer + }, + "SendMax": { + "currency": token2Info.currency, + "value": token2Value, + "issuer": token2Info.issuer + }, + "Paths": [ + [ + { + "account": token2Info.issuer, + "type": 1 + }, + { + "currency": token1Info.currency, + "issuer": token1Info.issuer, + "type": 48 + } + ] + ] + } + } else if (token2Info.currency == null) { // XRP > other token + swapTxData = { + "TransactionType": "Payment", + "Account": wallet.address, + "Destination": wallet.address, + "Amount": { + "currency": token1Info.currency, + "value": token1Value, + "issuer": token1Info.issuer + }, + "SendMax": token2Value, + "Paths": [ + [ + { + "currency": token1Info.currency, + "issuer": token1Info.issuer, + "type": 48 + } + ] + ] + } + } else if (token1Info.currency == null) { // other token > XRP + swapTxData = { + "TransactionType": "Payment", + "Account": wallet.address, + "Destination": wallet.address, + "Amount": token1Value, + "SendMax": { + "currency": token2Info.currency, + "value": token2Value, + "issuer": token2Info.issuer + }, + "Paths": [ + [ + { + "currency": "XRP", + "type": 16 + } + ] + ] + } + } + + try { + const pay_prepared = await client.autofill(swapTxData); + + const pay_signed = wallet.sign(pay_prepared); + + if (token1Info.currency != null) { + console.log(`Sending ${token1Info.value} ${token1Info.currency} to ${ammAddress}...`) + } else if(token2Info.currency == null) { + console.log(`Sending ${token2Info.value} ${token2Info.currency} to ${ammAddress}...`) + } + + const pay_result = await client.submitAndWait(pay_signed.tx_blob); + + if (pay_result.result.meta.TransactionResult == "tesSUCCESS") { + console.log(`Transaction succeeded: ${EXPLORER}/transactions/${pay_signed.hash}`) + } else { + throw `Error sending transaction: ${pay_result.result.meta.TransactionResult}` + }; + + // Check balances ------------------------------------------------------------ + console.log("Getting hot address balances..."); + // get hot address data + const balances = await client.request({ + command: "account_lines", + account: wallet.address, + ledger_index: "validated" + }) + console.log("wallet address's balance:", balances.result); + } catch(err) { + console.error("error occuered while swaping:", err); + } +}; + +/* Issue tokens function --------------------------------------------------------------- + * Fund a new issuer using the faucet, and issue some fungible tokens + * to the specified address. In production, you would not do this; instead, + * you would acquire tokens from an existing issuer (for example, you might + * buy them in the DEX, or make an off-ledger deposit at a stablecoin issuer). + * For a more thorough explanation of this process, see + * "Issue a Fungible Token": https://xrpl.org/issue-a-fungible-token.html + * Params: + * client: an xrpl.Client instance that is already connected to the network + * wallet: an xrpl.Wallet instance that should hold the new tokens + * currency_code: string currency code (3-char ISO-like or hex code) + * issue_quantity: string number of tokens to issue. Arbitrarily capped + * at "10000000000" + * Resolves to: an "Amount"-type JSON object, such as: + * { + * "currency": "TST", + * "issuer": "rP9jPyP5kyvFRb6ZiRghAGw5u8SGAmU4bd", + * "value": "123.456" + * } + * + * @param client + * @param wallet + * @param currency_code + * @param issue_quantity + * @returns + */ +export const get_new_token = async ( + client: any, + wallet: any, + currency_code: string, + issue_quantity: string +) => { + // Get credentials from the Testnet Faucet ----------------------------------- + console.log("Funding an issuer address with the faucet...") + const issuer = (await client.fundWallet()).wallet + console.log(`Got issuer address ${issuer.address}.`) + + // Enable issuer DefaultRipple ---------------------------------------------- + const issuer_setup_result = await client.submitAndWait({ + "TransactionType": "AccountSet", + "Account": issuer.address, + "SetFlag": xrpl.AccountSetAsfFlags.asfDefaultRipple + }, { + autofill: true, + wallet: issuer + } ) + + // get metaData & TransactionResult + const metaData: any = issuer_setup_result.result.meta!; + const transactionResult = metaData.TransactionResult; + + if (transactionResult == "tesSUCCESS") { + console.log(`Issuer DefaultRipple enabled: ${EXPLORER}/transactions/${issuer_setup_result.result.hash}`) + } else { + throw `Error sending transaction: ${issuer_setup_result}` + } + + // Create trust line to issuer ---------------------------------------------- + const trust_result = await client.submitAndWait({ + "TransactionType": "TrustSet", + "Account": wallet.address, + "LimitAmount": { + "currency": currency_code, + "issuer": issuer.address, + "value": "10000000000" // Large limit, arbitrarily chosen + } + }, { + autofill: true, + wallet: wallet + }) + + // get metaData & TransactionResult + const metaData2: any = issuer_setup_result.result.meta!; + const transactionResult2 = metaData2.TransactionResult; + + if (transactionResult2 == "tesSUCCESS") { + console.log(`Trust line created: ${EXPLORER}/transactions/${trust_result.result.hash}`) + } else { + throw `Error sending transaction: ${trust_result}` + } + + // Issue tokens ------------------------------------------------------------- + const issue_result = await client.submitAndWait({ + "TransactionType": "Payment", + "Account": issuer.address, + "Amount": { + "currency": currency_code, + "value": issue_quantity, + "issuer": issuer.address + }, + "Destination": wallet.address + }, { + autofill: true, + wallet: issuer + }) + + if (transactionResult == "tesSUCCESS") { + console.log(`Tokens issued: ${EXPLORER}/transactions/${issue_result.result.hash}`) + } else { + throw `Error sending transaction: ${issue_result}` + } + + const tokenInfo: TokenInfo = { + "currency": currency_code, + "value": issue_quantity, + "issuer": issuer.address + } + + return tokenInfo; +} \ No newline at end of file diff --git a/content/_code-samples/create-amm/ts/util/consts.ts b/content/_code-samples/create-amm/ts/util/consts.ts new file mode 100644 index 0000000000..859fc9a9ff --- /dev/null +++ b/content/_code-samples/create-amm/ts/util/consts.ts @@ -0,0 +1,3 @@ +// Connect to the network ----------------------------------------------------- +export const WS_URL = 'wss://s.devnet.rippletest.net:51233' +export const EXPLORER = 'https://devnet.xrpl.org' \ No newline at end of file From dd80d98502adb7ba4046a556c8533e7340eacfe9 Mon Sep 17 00:00:00 2001 From: Amarantha Kulkarni Date: Mon, 18 Dec 2023 10:44:26 -0800 Subject: [PATCH 04/25] Remove or update links to deprecated pages --- content/tutorials/get-started/send-xrp.md | 4 ++-- .../manage-account-settings/require-destination-tags.md | 2 +- content/tutorials/manage-account-settings/use-tickets.md | 2 +- .../tutorials/use-tokens/create-an-automated-market-maker.md | 2 +- content/tutorials/use-tokens/enable-no-freeze.md | 2 +- content/tutorials/use-tokens/enact-global-freeze.md | 2 +- content/tutorials/use-tokens/issue-a-fungible-token.md | 2 +- .../use-tokens/trade-in-the-decentralized-exchange.md | 2 +- dactyl-config.yml | 4 ++-- locale/ja/LC_MESSAGES/messages.po | 4 ++-- 10 files changed, 13 insertions(+), 13 deletions(-) diff --git a/content/tutorials/get-started/send-xrp.md b/content/tutorials/get-started/send-xrp.md index f1d7ddd451..5f0abbc111 100644 --- a/content/tutorials/get-started/send-xrp.md +++ b/content/tutorials/get-started/send-xrp.md @@ -61,7 +61,7 @@ The secret key shown here is for example only. For development purposes, you can {% include '_snippets/interactive-tutorials/generate-step.md' %} -When you're [building production-ready software](production-readiness.html), you should use an existing account, and manage your keys using a [secure signing configuration](secure-signing.html). +When you're building production-ready software, you should use an existing account, and manage your keys using a [secure signing configuration](secure-signing.html). ### 2. Connect to a Testnet Server @@ -392,7 +392,7 @@ print_r("Seed: " . $wallet->getSeed()); // Example: sp6JS7f14BuwFY8Mw6bTtLKWauoU **Warning:** You should only use an address and secret that you generated securely, on your local machine. If another computer generated the address and secret and sent it to you over a network, it's possible that someone else on the network may see that information. If they do, they'll have as much control over your XRP as you do. It's also recommended not to use the same address for the Testnet and Mainnet, because transactions that you created for use on one network could also be valid to execute on the other network, depending on the parameters you provided. -Generating an address and secret doesn't get you XRP directly; you're only choosing a random number. You must also receive XRP at that address to [fund the account](accounts.html#creating-accounts). A common way to acquire XRP is to buy it from an [exchange](exchanges.html), then withdraw it to your own address. +Generating an address and secret doesn't get you XRP directly; you're only choosing a random number. You must also receive XRP at that address to [fund the account](accounts.html#creating-accounts). A common way to acquire XRP is to buy it from an exchange, then withdraw it to your own address. ### Connecting to the Production XRP Ledger diff --git a/content/tutorials/manage-account-settings/require-destination-tags.md b/content/tutorials/manage-account-settings/require-destination-tags.md index f6eb763d33..af3bdcc14a 100644 --- a/content/tutorials/manage-account-settings/require-destination-tags.md +++ b/content/tutorials/manage-account-settings/require-destination-tags.md @@ -43,7 +43,7 @@ To transact on the XRP Ledger, you need an address and secret key, and some XRP. {% include '_snippets/interactive-tutorials/generate-step.md' %} -When you're [building production-ready software](production-readiness.html), you should use an existing account, and manage your keys using a [secure signing configuration](secure-signing.html). +When you're building production-ready software, you should use an existing account, and manage your keys using a [secure signing configuration](secure-signing.html). ### {{n.next()}}. Connect to the Network diff --git a/content/tutorials/manage-account-settings/use-tickets.md b/content/tutorials/manage-account-settings/use-tickets.md index 5e8a236c25..5387a74102 100644 --- a/content/tutorials/manage-account-settings/use-tickets.md +++ b/content/tutorials/manage-account-settings/use-tickets.md @@ -40,7 +40,7 @@ To transact on the XRP Ledger, you need an address and secret key, and some XRP. {% include '_snippets/interactive-tutorials/generate-step.md' %} -When you're [building production-ready software](production-readiness.html), you should use an existing account, and manage your keys using a [secure signing configuration](secure-signing.html). +When you're building production-ready software, you should use an existing account, and manage your keys using a [secure signing configuration](secure-signing.html). ### {{n.next()}}. Connect to Network diff --git a/content/tutorials/use-tokens/create-an-automated-market-maker.md b/content/tutorials/use-tokens/create-an-automated-market-maker.md index 99755a2fa3..c5db2f7484 100644 --- a/content/tutorials/use-tokens/create-an-automated-market-maker.md +++ b/content/tutorials/use-tokens/create-an-automated-market-maker.md @@ -62,7 +62,7 @@ To transact on the XRP Ledger, you need an address, a secret key, and some XRP. {% include '_snippets/interactive-tutorials/generate-step.md' %} -When you're [building production-ready software](production-readiness.html), you should use an existing account, and manage your keys using a [secure signing configuration](set-up-secure-signing.html). The following code shows how to get a `Wallet` instance using either the faucet or a seed provided by environment variable: +When you're building production-ready software, you should use an existing account, and manage your keys using a [secure signing configuration](set-up-secure-signing.html). The following code shows how to get a `Wallet` instance using either the faucet or a seed provided by environment variable: diff --git a/content/tutorials/use-tokens/enable-no-freeze.md b/content/tutorials/use-tokens/enable-no-freeze.md index 504fa2ebfe..1856223e96 100644 --- a/content/tutorials/use-tokens/enable-no-freeze.md +++ b/content/tutorials/use-tokens/enable-no-freeze.md @@ -42,7 +42,7 @@ For this tutorial, you can get credentials from the following interface: {% include '_snippets/interactive-tutorials/generate-step.md' %} -When you're [building production-ready software](production-readiness.html), you should use an existing account, and manage your keys using a [secure signing configuration](secure-signing.html). +When you're building production-ready software, you should use an existing account, and manage your keys using a [secure signing configuration](secure-signing.html). ### {{n.next()}}. Connect to the Network diff --git a/content/tutorials/use-tokens/enact-global-freeze.md b/content/tutorials/use-tokens/enact-global-freeze.md index 2a2e636ecf..895f9b263e 100644 --- a/content/tutorials/use-tokens/enact-global-freeze.md +++ b/content/tutorials/use-tokens/enact-global-freeze.md @@ -45,7 +45,7 @@ For this tutorial, you can get credentials from the following interface: {% include '_snippets/interactive-tutorials/generate-step.md' %} -When you're [building production-ready software](production-readiness.html), you should use an existing account, and manage your keys using a [secure signing configuration](secure-signing.html). +When you're building production-ready software, you should use an existing account, and manage your keys using a [secure signing configuration](secure-signing.html). ### {{n.next()}}. Connect to the Network diff --git a/content/tutorials/use-tokens/issue-a-fungible-token.md b/content/tutorials/use-tokens/issue-a-fungible-token.md index 6e983ae854..b1417fb86b 100644 --- a/content/tutorials/use-tokens/issue-a-fungible-token.md +++ b/content/tutorials/use-tokens/issue-a-fungible-token.md @@ -59,7 +59,7 @@ In this tutorial, the hot address receives the tokens you issue from the cold ad **Caution:** Ripple provides the [Testnet and Devnet](parallel-networks.html) for testing purposes only, and sometimes resets the state of these test networks along with all balances. As a precaution, **do not** use the same addresses on Testnet/Devnet and Mainnet. -When you're [building production-ready software](production-readiness.html), you should use an existing account, and manage your keys using a [secure signing configuration](secure-signing.html). +When you're building production-ready software, you should use an existing account, and manage your keys using a [secure signing configuration](secure-signing.html). ### {{n.next()}}. Connect to the Network diff --git a/content/tutorials/use-tokens/trade-in-the-decentralized-exchange.md b/content/tutorials/use-tokens/trade-in-the-decentralized-exchange.md index 763d3c98d9..6f3513f348 100644 --- a/content/tutorials/use-tokens/trade-in-the-decentralized-exchange.md +++ b/content/tutorials/use-tokens/trade-in-the-decentralized-exchange.md @@ -69,7 +69,7 @@ To transact on the XRP Ledger, you need an address, a secret key, and some XRP. {% include '_snippets/interactive-tutorials/generate-step.md' %} -When you're [building production-ready software](production-readiness.html), you should use an existing account, and manage your keys using a [secure signing configuration](secure-signing.html). The following code shows how to create a `Wallet` instance to use your keys: +When you're building production-ready software, you should use an existing account, and manage your keys using a [secure signing configuration](secure-signing.html). The following code shows how to create a `Wallet` instance to use your keys: diff --git a/dactyl-config.yml b/dactyl-config.yml index 2e06a3f5ad..91b2a98163 100644 --- a/dactyl-config.yml +++ b/dactyl-config.yml @@ -5328,7 +5328,7 @@ pages: - name: Wallets html: wallets.html template: pagetype-redirect.html.jinja - redirect_url: xrp-overview.html + redirect_url: crypto-wallets.html. nav_omit: true targets: - en @@ -5336,7 +5336,7 @@ pages: - name: ウォレット html: wallets.html template: pagetype-redirect.html.jinja - redirect_url: xrp-overview.html + redirect_url: crypto-wallets.html nav_omit: true targets: - ja diff --git a/locale/ja/LC_MESSAGES/messages.po b/locale/ja/LC_MESSAGES/messages.po index ec7e625c8c..2614b1f8ce 100644 --- a/locale/ja/LC_MESSAGES/messages.po +++ b/locale/ja/LC_MESSAGES/messages.po @@ -4006,9 +4006,9 @@ msgstr "目次" #~ msgid "" #~ "XRP is traded on more than 140 " -#~ "markets and exchanges" +#~ "markets and exchanges" #~ " worldwide." -#~ msgstr "XRPは世界中の140以上の市場と取引所で取引されています。" +#~ msgstr "XRPは世界中の140以上の市場とで取引されています。" #~ msgid "Find Out More" #~ msgstr "詳細を見る" From fe7d177dd03209d3f503ed2a07526163c3b2bd56 Mon Sep 17 00:00:00 2001 From: Amarantha Kulkarni Date: Mon, 18 Dec 2023 10:48:48 -0800 Subject: [PATCH 05/25] Replace cycler patterns with hard-coded numbers in tutorials --- content/tutorials/get-started/get-started-using-java.md | 9 ++++----- .../tutorials/get-started/get-started-using-python.md | 9 ++++----- .../monitor-incoming-payments-with-websocket.md | 9 ++++----- 3 files changed, 12 insertions(+), 15 deletions(-) diff --git a/content/tutorials/get-started/get-started-using-java.md b/content/tutorials/get-started/get-started-using-java.md index f32dc51f8f..cfb95d1b6c 100644 --- a/content/tutorials/get-started/get-started-using-java.md +++ b/content/tutorials/get-started/get-started-using-java.md @@ -75,7 +75,6 @@ To install with Maven, add the following to your project's `pom.xml` file and th Check out the [xrpl4j sample project](https://github.com/XRPLF/xrpl4j-sample) for a full Maven project containing the code from this tutorial. ## Start Building -{% set n = cycler(* range(1,99)) %} When you're working with the XRP Ledger, there are a few things you'll need to manage, whether you're adding XRP to your [account](accounts.html), integrating with the [decentralized exchange](decentralized-exchange.html), or [issuing tokens](tokens.html). This tutorial walks you through basic patterns common to getting started with all of these use cases and provides sample code for implementing them. @@ -86,7 +85,7 @@ Here are the basic steps you'll need to cover for almost any XRP Ledger project: 1. [Query the XRP Ledger.](#3-query-the-xrp-ledger) -### {{n.next()}}. Connect to the XRP Ledger +### 1. Connect to the XRP Ledger To make queries and submit transactions, you need to connect to the XRP Ledger. To do this with `xrpl4j`, you can use an [`XrplClient`](https://javadoc.io/doc/org.xrpl/xrpl4j-client/3.0.1/org/xrpl/xrpl4j/client/XrplClient.html): @@ -109,7 +108,7 @@ The sample code in the previous section shows you how to connect to the Testnet, final HttpUrl rippledUrl = HttpUrl.get("https://s2.ripple.com:51234/"); XrplClient xrplClient = new XrplClient(rippledUrl); -### {{n.next()}}. Get account +### 2. Get account To store value and execute transactions on the XRP Ledger, you need to get an account: a [set of keys](cryptographic-keys.html#key-components) and an [address](addresses.html) that's been [funded with enough XRP](accounts.html#creating-accounts) to meet the [account reserve](reserves.html). The address is the identifier of your account and you use the [private key](cryptographic-keys.html#private-key) to sign transactions that you submit to the XRP Ledger. For production purposes, you should take care to store your keys and set up a [secure signing method](secure-signing.html). @@ -137,7 +136,7 @@ For testing and development purposes, you can use a `FaucetClient` connected to {{ include_code("_code-samples/get-started/java/GetAccountInfo.java", start_with="// Fund the account using the testnet Faucet", end_before="// Look up your Account Info", language="java") }} -### {{n.next()}}. Query the XRP Ledger +### 3. Query the XRP Ledger You can query the XRP Ledger to get information about [a specific account](account-methods.html), [a specific transaction](tx.html), the state of a [current or a historical ledger](ledger-methods.html), and [the XRP Ledger's decentralized exchange](path-and-order-book-methods.html). You need to make these queries, among other reasons, to look up account info to follow best practices for [reliable transaction submission](reliable-transaction-submission.html). @@ -146,7 +145,7 @@ Here, we'll use the [`XrplClient` we constructed](#1-connect-to-the-xrp-ledger) {{ include_code("_code-samples/get-started/java/GetAccountInfo.java", start_with="// Look up your Account Info", end_before="// Print the result", language="java") }} -### {{n.next()}}. Putting it all together +### 4. Putting it all together Using these building blocks, we can create a Java app that: diff --git a/content/tutorials/get-started/get-started-using-python.md b/content/tutorials/get-started/get-started-using-python.md index 6fc98ed8aa..f46a02258c 100644 --- a/content/tutorials/get-started/get-started-using-python.md +++ b/content/tutorials/get-started/get-started-using-python.md @@ -40,7 +40,6 @@ pip3 install xrpl-py ``` ## Start Building -{% set n = cycler(* range(1,99)) %} When you're working with the XRP Ledger, there are a few things you'll need to manage, whether you're adding XRP to your [account](accounts.html), integrating with the [decentralized exchange](decentralized-exchange.html), or [issuing tokens](tokens.html). This tutorial walks you through basic patterns common to getting started with all of these use cases and provides sample code for implementing them. @@ -51,7 +50,7 @@ Here are the basic steps you'll need to cover for almost any XRP Ledger project: 1. [Query the XRP Ledger.](#3-query-the-xrp-ledger) -### {{n.next()}}. Connect to the XRP Ledger +### 1. Connect to the XRP Ledger To make queries and submit transactions, you need to connect to the XRP Ledger. To do this with `xrpl-py`, use the [`xrp.clients` module](https://xrpl-py.readthedocs.io/en/latest/source/xrpl.clients.html): @@ -76,7 +75,7 @@ The sample code in the previous section shows you how to connect to the Testnet, client = JsonRpcClient(JSON_RPC_URL) -### {{n.next()}}. Get account +### 2. Get account To store value and execute transactions on the XRP Ledger, you need an account: a [set of keys](cryptographic-keys.html#key-components) and an [address](addresses.html) that's been [funded with enough XRP](accounts.html#creating-accounts) to meet the [account reserve](reserves.html). The address is the identifier of your account and you use the [private key](cryptographic-keys.html#private-key) to sign transactions that you submit to the XRP Ledger. @@ -128,7 +127,7 @@ You can use `xrpl-py`'s [`xrpl.core.addresscodec`](https://xrpl-py.readthedocs.i The X-address format [packs the address and destination tag](https://github.com/XRPLF/XRPL-Standards/issues/6) into a more user-friendly value. -### {{n.next()}}. Query the XRP Ledger +### 3. Query the XRP Ledger You can query the XRP Ledger to get information about [a specific account](account-methods.html), [a specific transaction](tx.html), the state of a [current or a historical ledger](ledger-methods.html), and [the XRP Ledger's decentralized exchange](path-and-order-book-methods.html). You need to make these queries, among other reasons, to look up account info to follow best practices for [reliable transaction submission](reliable-transaction-submission.html). @@ -139,7 +138,7 @@ Here, we use `xrpl-py`'s [`xrpl.account`](https://xrpl-py.readthedocs.io/en/late -### {{n.next()}}. Putting it all together +### 4. Putting it all together Using these building blocks, we can create a Python app that: diff --git a/content/tutorials/get-started/monitor-incoming-payments-with-websocket.md b/content/tutorials/get-started/monitor-incoming-payments-with-websocket.md index 325c0990c6..95afb7384d 100644 --- a/content/tutorials/get-started/monitor-incoming-payments-with-websocket.md +++ b/content/tutorials/get-started/monitor-incoming-payments-with-websocket.md @@ -34,9 +34,8 @@ function writeToConsole(console_selector, message) { } -{% set n = cycler(* range(1,99)) %} -## {{n.next()}}. Connect to the XRP Ledger +## 1. Connect to the XRP Ledger The first step of monitoring for incoming payments is to connect to the XRP Ledger, specifically a `rippled` server. @@ -111,7 +110,7 @@ $("#connect-socket-button").click((event) => { -## {{n.next()}}. Dispatch Incoming Messages to Handlers +## 2. Dispatch Incoming Messages to Handlers Since WebSocket connections can have several messages going each way and there is not a strict 1:1 correlation between requests and responses, you need to identify what to do with each incoming message. A good model for coding this is to set up a "dispatcher" function that reads incoming messages and relays each message to the correct code path for handling it. To help dispatch messages appropriately, the `rippled` server provides a `type` field on every WebSocket message: @@ -257,7 +256,7 @@ $("#dispatch_ping").click((event) => { }) -## {{n.next()}}. Subscribe to the Account +## 3. Subscribe to the Account To get a live notification whenever a transaction affects your account, you can subscribe to the account with the [subscribe method][]. In fact, it doesn't have to be your own account: since all transactions are public, you can subscribe to any account or even a combination of accounts. @@ -331,7 +330,7 @@ WS_HANDLERS["transaction"] = log_tx -## {{n.next()}}. Read Incoming Payments +## 4. Read Incoming Payments When you subscribe to an account, you get messages for _all transactions to or from the account_, as well as _transactions that affect the account indirectly_, such as trading its [tokens](tokens.html). If your goal is to recognize when the account has received incoming payments, you must filter the transactions stream and process the payments based on the amount they actually delivered. Look for the following information: From bb1648fcd076cdba0cf715ae25e51d271b8bfed7 Mon Sep 17 00:00:00 2001 From: Amarantha Kulkarni Date: Mon, 18 Dec 2023 14:08:55 -0800 Subject: [PATCH 06/25] Fix typo that was causing a broken link --- dactyl-config.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dactyl-config.yml b/dactyl-config.yml index 91b2a98163..4c3ddb9a31 100644 --- a/dactyl-config.yml +++ b/dactyl-config.yml @@ -5328,7 +5328,7 @@ pages: - name: Wallets html: wallets.html template: pagetype-redirect.html.jinja - redirect_url: crypto-wallets.html. + redirect_url: crypto-wallets.html nav_omit: true targets: - en From c68079e30f3d53592fa68c13802df94972fa5fdc Mon Sep 17 00:00:00 2001 From: mDuo13 Date: Mon, 18 Dec 2023 15:20:44 -0800 Subject: [PATCH 07/25] Remove unused old JS get started --- .../get-started-using-javascript.ja.md.old | 339 ------------------ 1 file changed, 339 deletions(-) delete mode 100644 content/tutorials/get-started/get-started-using-javascript.ja.md.old diff --git a/content/tutorials/get-started/get-started-using-javascript.ja.md.old b/content/tutorials/get-started/get-started-using-javascript.ja.md.old deleted file mode 100644 index 05e9324bc9..0000000000 --- a/content/tutorials/get-started/get-started-using-javascript.ja.md.old +++ /dev/null @@ -1,339 +0,0 @@ ---- -html: get-started-using-javascript.html -parent: get-started.html -blurb: XRP Ledgerに照会するエントリーレベルのJavaScriptアプリケーションを構築します。 -top_nav_name: JavaScript -top_nav_grouping: Get Started -labels: - - 開発 -showcase_icon: assets/img/logos/javascript.svg ---- -# RippleAPI入門ガイド - -このチュートリアルでは、[Node.js](http://nodejs.org/)と[RippleAPI](rippleapi-reference.html)(XRP LedgerにアクセスするためのJavaScript API)を使用して、XRP Ledgerに接続されるアプリケーションを開発するための基本事項を説明します。 - -このガイドで使用しているスクリプトと構成ファイルは、[このサイトのGitHubリポジトリで入手できます](https://github.com/XRPLF/xrpl-dev-portal/tree/master/content/_code-samples/rippleapi_quickstart)。 - - - -# 環境の設置 - -RippleAPIを使用するための最初のステップは、開発環境の設置です。 - - - -## Node.jsとnpmのインストール - -RippleAPIはNode.jsランタイム環境向けのアプリケーションとして構築されているため、最初のステップはNode.jsのインストールです。RippleAPIでは、Node.js v6以降が必要です。Node.js v10 LTSを使用することをお勧めします。 - -このステップは、オペレーティングシステムによって内容が異なります。使用しているオペレーティングシステムの[パッケージマネージャーを使用してNode.jsをインストールする場合の公式の手引き](https://nodejs.org/en/download/package-manager/)に準拠することをお勧めします。Node.jsとnpm(Node Package Manager)のパッケージが分かれている場合、両方をインストールします(これに該当するのは、Arch Linux、CentOS、Fedora、RHELの場合です)。 - -Node.jsのインストール後、`node`バイナリーのバージョンはコマンドラインから確認できます。 - -``` -node --version -``` - -プラットフォームによっては、バイナリーの名前が`nodejs`となっています。 - -``` -nodejs --version -``` - - - -## Yarnのインストール - -RippleAPIでは、Yarnを使用して依存関係を管理します。Yarn v1.13.0を使用することをお勧めします。 - -このステップは、オペレーティングシステムによって内容が異なります。使用しているオペレーティングシステムの[パッケージマネージャーを使用してYarnをインストールする場合の公式の手引き](https://yarnpkg.com/en/docs/install#mac-stable)に準拠することをお勧めします。 - -Yarnのインストール後、`yarn`バイナリーのバージョンはコマンドラインから確認できます。 - -``` -yarn --version -``` - - - -## RippleAPIと依存関係のインストール - -以下のステップに従い、Yarnを使用してRippleAPIと依存関係のインストールを完了します。 - - -### 1. プロジェクトの新規ディレクトリーを作成 - -`my_ripple_experiment`といった名前でフォルダーを作成します。 - -``` -mkdir my_ripple_experiment && cd my_ripple_experiment -``` - -コードに対する変更を追跡できるよう、このディレクトリーに[Git](https://git-scm.com/book/en/v2/Getting-Started-Installing-Git)リポジトリーを作成します(省略可)。 - -``` -git init -``` - -作業内容のバージョン管理や共有を目的として、[GitHubにリポジトリーを作成](https://docs.github.com/en/get-started/quickstart/create-a-repo/)してもかまいません。設置後、ローカルマシンに[リポジトリーのクローンを作成](https://docs.github.com/en/repositories/creating-and-managing-repositories/cloning-a-repository/)し、そのディレクトリーに`cd`します。 - - -### 2. プロジェクトの新規`package.json`ファイルを作成 - -次の内容が含まれている、以下のテンプレートを使用します。 - -- RippleAPI自体(`ripple-lib`) -- (省略可)コード品質を確認するための[ESLint](https://eslint.org/)(`eslint`) - -``` -{% include '_code-samples/rippleapi_quickstart/package.json' %} -``` - - -### 3. Yarnを使用してRippleAPIと依存関係をインストール - -Yarnを使用して、プロジェクトで作成した`package.json`ファイルに定義されているRippleAPIと依存関係をインストールします。 - -``` -yarn -``` - -これで、RippleAPIと依存関係がローカルフォルダー`node_modules/`にインストールされます。 - -インストールプロセスの終了時に、いくつかの警告が表示される場合があります。以下の警告は無視してかまいません。 - -``` -warning eslint > file-entry-cache > flat-cache > circular-json@0.3.3: CircularJSON is in maintenance only, flatted is its successor. - -npm WARN optional Skipping failed optional dependency /chokidar/fsevents: - -npm WARN notsup Not compatible with your operating system or architecture: fsevents@1.0.6 -``` - - - -# 最初のRippleAPIスクリプト - -スクリプト`get-account-info.js`は、ハードコーディングされたアカウントに関する情報をフェッチします。このスクリプトを使用して、RippleAPIが動作することをテストします。 - -``` -{% include '_code-samples/rippleapi_quickstart/get-account-info.js' %} -``` - - - -## スクリプトの実行 - -以下のコマンドを使用して、最初のRippleAPIスクリプトを実行します。 - -``` -node get-account-info.js -``` - -出力: - -``` -getting account info for rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn -{ sequence: 359, - xrpBalance: '75.181663', - ownerCount: 4, - previousInitiatedTransactionID: 'E5C6DD25B2DCF534056D98A2EFE3B7CFAE4EBC624854DE3FA436F733A56D8BD9', - previousAffectingTransactionID: 'E5C6DD25B2DCF534056D98A2EFE3B7CFAE4EBC624854DE3FA436F733A56D8BD9', - previousAffectingTransactionLedgerVersion: 18489336 } -getAccountInfo done -done and disconnected. -``` - - - -## スクリプトの内容解説 - -このスクリプトでは、RippleAPI固有のコードに加え、JavaScriptにおける近年の開発成果である構文や規定も利用しています。今回のサンプルコードを小さめのチャンクに分割して、個別に説明していきます。 - - -### スクリプトの冒頭 - -``` -'use strict'; -const RippleAPI = require('ripple-lib').RippleAPI; -``` - -先頭行では、[strictモード](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Strict_mode)を有効にしています。このモードを使用するかどうかは任意に選択できますが、JavaScriptで陥りやすいいくつかの落とし穴を回避する上で役立ちます。 - -2行目では、Node.jsのrequire関数を使用して、RippleAPIを現在のスコープにインポートしています。RippleAPIは、[`ripple-lib`がエクスポートするモジュール](https://github.com/XRPLF/xrpl.js/blob/develop/src/index.ts)の1つです。 - - -### APIのインスタンス化 - -``` -const api = new RippleAPI({ - server: 'wss://s1.ripple.com' // Public rippled server -}); -``` - -このセクションでは、RippleAPIクラスの新規インスタンスを作成し、変数`api`に代入しています([`const`キーワード](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/const)は、値`api`を何らかの別の値に再代入できないことを意味します。ただし、オブジェクトの内部状態は変化する可能性があります)。 - -コンストラクターへの引数の1つはoptionsオブジェクトであり、このオブジェクトには[さまざまなオプション](rippleapi-reference.html#parameters)が用意されています。`server`パラメーターでは、どの`rippled`サーバーに接続するのかを指定しています。 - -- この`server`設定例では、セキュアなWebSocket接続を使用して、Ripple社が運営している公開サーバーの1つに接続しています。 -- `server`オプションを記述しない場合、RippleAPIは、ネットワーク接続の不要なメソッドのみが提供される[オフラインモード](rippleapi-reference.html#offline-functionality)で実行されます。 -- 代わりに[XRP Ledgerテストネット](xrp-testnet-faucet.html)サーバーを指定すると、本番環境のXRP Ledgerではなく、別空間のテストネットワークに接続できます。 -- [独自の`rippled`を運用している](install-rippled.html)場合は、ローカルサーバーに接続するよう指示できます。例えば、代わりに`server: 'ws://localhost:5005'`と記述します。 - - -### 接続とPromise - -``` -api.connect().then(() => { -``` - -[connect()メソッド](rippleapi-reference.html#connect)は、特殊なJavaScriptオブジェクトである[Promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise)を返す多くのRippleAPIメソッドの1つです。Promiseは、XRP Ledgerを照会するなど、値を後ほど返す非同期操作の実行を目的としています。 - -何らかの式(`api.connect()`など)からPromiseが返された場合、Promiseの`then`メソッドを呼び出して、コールバック関数を渡します。関数を引数として渡すことはJavaScriptでは常套的な手法であり、JavaScriptの関数が[第一級オブジェクト](https://en.wikipedia.org/wiki/First-class_function)であることを利用しています。 - -Promiseは、自身の非同期動作を完了すると、渡されたコールバック関数を実行します。`then`メソッドからの戻り値は別のPromiseオブジェクトであるため、別の`then`メソッドへの、または同様にコールバックを受け付けるPromiseの`catch`メソッドへの「チェーン」にすることができます。`catch`に渡すコールバックは、何らかの問題が生じた場合に呼び出されます。 - -この例では、非同期関数を手軽に定義できる手段である[arrow関数](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions)を使用しています。この方法は、1回限りの関数をコールバックとして大量に定義する場合に便利です。`()=> {...}`という構文は、 {...}/>`function() {...}`とほぼ等価です。パラメーターを1つ取る非同期関数が必要な場合は、代わりに`info => {...}`などの構文を使用できます。この構文は、 {...}/>`function(info) {...}`という構文とほぼ同一です。 - - -### カスタムコード - -``` - /* begin custom code ------------------------------------ */ - const myAddress = 'rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn'; - - console.log('getting account info for', myAddress); - return api.getAccountInfo(myAddress); - -}).then(info => { - console.log(info); - console.log('getAccountInfo done'); - - /* end custom code -------------------------------------- */ -``` - -ここが、スクリプトで実行する処理を記述するために変更を加える部分です。 - -このサンプルコードでは、XRP Ledgerアカウントのアドレスを使用してXRP Ledgerアカウントを参照しています。さまざまなアドレスを指定してコードを実行し、結果が変化することを確認してみてください。 - -`console.log()`関数はNode.jsとWebブラウザーの両方に組み込まれているもので、結果をコンソールに出力します。この例では大量のコンソール出力を得られるので、コードによって実行される処理の内容を簡単に理解できます。 - -このサンプルコードは、(RippleAPIが接続を終了した時点で呼び出される)コールバック関数の中が始点となっています。その関数がRippleAPIの[`getAccountInfo`](rippleapi-reference.html#getaccountinfo)メソッドを呼び出すと、結果が返されます。 - -`getAccountInfo` APIメソッドは別のPromiseを返すものであるため、`}).then( info => {`の行で、このPromiseの非同期処理が完了した時点で実行される別の非同期コールバック関数を定義しています。前述の例とは異なり、このコールバック関数は、`getAccountInfo` APIメソッドからの非同期戻り値を保持する`info`という引数を1つ取ります。このコールバック関数の残りの部分は、その戻り値をコンソールに出力するものです。 - - -### クリーンアップ - -``` -}).then(() => { - return api.disconnect(); -}).then(() => { - console.log('done and disconnected.'); -}).catch(console.error); -``` - -サンプルコードの残りの部分は、概ね[ボイラープレートコード](rippleapi-reference.html#boilerplate)としての性質を持ちます。1行目は前のコールバック関数を終了するもので、次に、終了時に実行される別のコールバックへのチェーンを作成しています。そのメソッドはXRP Ledgerからの明示的な切断を実行し、終了時にコンソールへの書き込みを実行する別のコールバックが記述されています。スクリプトで[RippleAPIイベント](rippleapi-reference.html#api-events)を待機する場合は、イベントの待機を終了するまで切断を実行しないでください。 - -`catch`メソッドで、このPromiseチェーンを終了します。ここに記述しているコールバックは、いずれかのPromiseまたはそのコールバック関数でエラーが発生した場合に実行されます。ここでは、カスタムのコールバックを定義するのではなく、コンソールへの書き込みを実行する標準の`console.error`関数を渡しています。より高機能のコールバック関数をここに定義して、特定のタイプのエラーをインテリジェントにキャッチすることもできます。 - - - -# 検証の待機 - -XRP Ledger(または任意の分散されたシステム)を使用する上で最大の課題の1つとなるのが、最終的かつ不変のトランザクション結果を把握することです。[ベストプラクティスに従っている](reliable-transaction-submission.html)場合も、トランザクションが最終的に受け入れられるか拒否されるまで、[コンセンサスプロセス](consensus.html)を待機しなければならないことに変わりはありません。以下のサンプルコードは、トランザクションの最終的な結果を待機する方法を示しています。 - -``` -{% include '_code-samples/submit-and-verify/submit-and-verify.js' %} -``` - -このコードは注文トランザクションを作成して送信するものですが、他のタイプのトランザクションにも同様の原則があてはまります。トランザクションを送信した後、setTimeoutを使用して所定の時間が経過するまで待機し、新しいPromiseでレジャーをもう一度照会して、トランザクションが検証済みとなっているかどうかを確認します。検証済みとなっていない場合は、検証済みレジャーの中にトランザクションが見つかるか、返されたレジャーがLastLedgerSequenceパラメーターの値よりも大きくなるまで、このプロセスを繰り返します。 - -まれなケースとして(特に、大きな遅延や電源喪失が発生した場合)、トランザクションを送信してから、`maxLedgerVersion`がネットワークから渡されたと判断するまでの間に、レジャーのいずれかのバージョンが`rippled`サーバーで欠落することがあります。この場合、トランザクションが失敗したのか、欠落したバージョンのレジャーに含まれているのかを最終的に確定することはできません。RippleAPIは、この場合、`MissingLedgerHistoryError`を返します。 - -`rippled`サーバーの管理者である場合は、[欠落しているレジャーを手動で要求できます](ledger_request.html)。管理者でない場合は、別のサーバーを使用してレジャー履歴を確認してみるという方法が考えられます(Rippleは、この目的で、すべての履歴が記録される公開サーバーを`s2.ripple.com`で運用しています)。 - -詳細は、[信頼できるトランザクションの送信](reliable-transaction-submission.html)を参照してください。 - - - -# WebブラウザーでのRippleAPI - -RippleAPIは、ブラウザー互換のバージョンをコンパイルし、RippleAPIスクリプトよりも前に[lodash](https://www.npmjs.com/package/lodash)を依存関係として含めた場合、Webブラウザーでも使用できます。 - - - -## ブラウザー互換バージョンのRippleAPIのビルド - -RippleAPIをブラウザーで使用するには、ブラウザー互換バージョンをビルドする必要があります。以下の手順では、RippleAPIをコンパイルして、Webページに含めることのできる単一のJavaScriptファイルを生成します。 - - -### 1. RippleAPI gitリポジトリーのコピーをダウンロード - -[Git](https://git-scm.com/book/en/v2/Getting-Started-Installing-Git)がインストールされている場合は、リポジトリーのクローンを作成して、**master**ブランチをチェックアウトできます。このブランチには、常に最新の公式リリースが収められています。 - -``` -git clone https://github.com/XRPLF/xrpl.js.git -cd ripple-lib -git checkout master -``` - -または、特定のリリースのアーカイブ(.zipまたは.tar.gz)を[RippleAPIリリースページ](https://github.com/XRPLF/xrpl.js/releases)からダウンロードし、抽出します。 - - -### 2. Yarnのインストール - -[Yarnのインストール](#yarnのインストール)に関する手順に従います。 - - -### 3. Yarnを使用して依存関係をインストール - -``` -yarn -``` - - -### 4. Gulpを使用して単一のJavaScript出力をビルド - -RippleAPIには、[gulp](http://gulpjs.com/)パッケージを使用してすべてのソースコードをコンパイルし、ブラウザー互換バージョンのJavaScriptファイルを生成するためのコードが付属しています。Gulpは依存関係の1つとして自動的にインストールされるため、実行するだけで済みます。RippleAPIの構成上、これは容易に実行できるようになっています。 - -``` -yarn run build -``` - -出力: - -``` -> ripple-lib@0.16.5 build /home/username/ripple-lib -> gulp - -[14:11:02] Using gulpfile /home/username/ripple-lib/gulpfile.js -[14:11:02] Starting 'build'... -[14:11:03] Starting 'build-debug'... -[14:11:03] Starting 'build-min'... -[14:11:18] Finished 'build-debug' after 15 s -[14:11:18] Finished 'build' after 16 s -[14:11:18] Finished 'build-min' after 15 s -[14:11:18] Starting 'default'... -[14:11:18] Finished 'default' after 19 μs -``` - -完了までに、しばらく時間がかかる場合があります。最終的に、ビルドプロセスによって、目的のファイルが含まれた新しい`build/`フォルダーが作成されます。 - -`build/ripple-.js`ファイルは、ブラウザーですぐに使用できる(ビルドしたバージョンの)RippleAPIの直接エクスポートです。名前の末尾が`-min.js`のファイルも同じものですが、読み込みを高速化するため、内容が[縮小](https://en.wikipedia.org/wiki/Minification_%28programming%29)されています。 - - - -## ブラウザーでのRippleAPIのデモ - -以下のHTMLファイルは、RippleAPIのブラウザーバージョンで公開`rippled`サーバーに接続し、そのサーバーに関する情報のレポートを生成するための基本的な使用方法を示しています。Node.jsの「require」構文を使用するのではなく、ブラウザーバージョンを使用して、`RippleAPI`クラスが含まれている`ripple`という名前のグローバル変数を作成します。 - -この例を使用するには、最初に[RippleAPIのブラウザー互換バージョンをビルド](#ブラウザー互換バージョンのrippleapiのビルド)した後、結果として生成される出力ファイルのいずれかを、このHTMLファイルと同一のフォルダーにコピーします(縮小バージョンとフルサイズバージョンのどちらを使用してもかまいません)。この例にある2番目の`