Compare commits
515 Commits
v2015-01-1
...
DataAPI-v2
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d3cca26317 | ||
|
|
e1a7c82454 | ||
|
|
40b39b5aee | ||
|
|
ee371167e4 | ||
|
|
e39e05eab5 | ||
|
|
ae07e94f74 | ||
|
|
be15bc4d02 | ||
|
|
103a8f157c | ||
|
|
2c806eed1f | ||
|
|
46e53f718a | ||
|
|
2db8f5800a | ||
|
|
fd94152c4f | ||
|
|
fd961521b8 | ||
|
|
2a18ed14f6 | ||
|
|
2e999d183d | ||
|
|
d5a2928e74 | ||
|
|
10d1ca76a3 | ||
|
|
c1d79696ff | ||
|
|
22b6033e96 | ||
|
|
d7d6bbaaae | ||
|
|
2045bc55f5 | ||
|
|
1f3eeeb5a0 | ||
|
|
d1281f8c3b | ||
|
|
e53e4581d1 | ||
|
|
d50fdd7638 | ||
|
|
340883f505 | ||
|
|
dd67b51c59 | ||
|
|
959f4e28d3 | ||
|
|
2d563f53f3 | ||
|
|
af0e6f5baa | ||
|
|
482b453602 | ||
|
|
6a11960240 | ||
|
|
63d5b8b2de | ||
|
|
fee3a5dc39 | ||
|
|
d1a537f434 | ||
|
|
976a383ed0 | ||
|
|
752f8fa0c0 | ||
|
|
7ec702365a | ||
|
|
b22c1c406b | ||
|
|
0d917b4165 | ||
|
|
499faf6ea1 | ||
|
|
dfafdcc237 | ||
|
|
9fc1f5894d | ||
|
|
5d9d32c879 | ||
|
|
a60f186187 | ||
|
|
ae47dcbb3f | ||
|
|
aac47fa398 | ||
|
|
e8b8eb87a6 | ||
|
|
d04cdfc6de | ||
|
|
ffdb26db76 | ||
|
|
a1e89557b8 | ||
|
|
41ee3f3271 | ||
|
|
25a18df9bb | ||
|
|
d5408d7361 | ||
|
|
bc9524974f | ||
|
|
bb8b48b0bb | ||
|
|
68ab7c85f0 | ||
|
|
45ae8a248d | ||
|
|
1296f0739d | ||
|
|
dddaad56b1 | ||
|
|
c310d255b5 | ||
|
|
6b5297c2e0 | ||
|
|
dc808f32f4 | ||
|
|
6fadacf7b6 | ||
|
|
d0fc1c5b84 | ||
|
|
47407e82c8 | ||
|
|
6d13f7cd94 | ||
|
|
3170211d51 | ||
|
|
bafd714dac | ||
|
|
30a5b6d04b | ||
|
|
e0b95e07d1 | ||
|
|
d22c95a922 | ||
|
|
9abb1c6f20 | ||
|
|
5b274c06ca | ||
|
|
198a11c7bf | ||
|
|
798ea6fa40 | ||
|
|
c7de77110e | ||
|
|
083201af41 | ||
|
|
608c3ec455 | ||
|
|
3f9ceb3a5d | ||
|
|
a8004c09be | ||
|
|
a63da19b70 | ||
|
|
25e4b4e475 | ||
|
|
7260e01e7c | ||
|
|
8b1dc35d30 | ||
|
|
8c1d619ca2 | ||
|
|
fe2bafb795 | ||
|
|
b72347591e | ||
|
|
6f569795bd | ||
|
|
cd8d63ab1d | ||
|
|
45c327ff89 | ||
|
|
5b4b933433 | ||
|
|
e454c0dd01 | ||
|
|
2158e17899 | ||
|
|
11771b7426 | ||
|
|
0553a57709 | ||
|
|
84e93f47e1 | ||
|
|
257d473063 | ||
|
|
dbf45774f4 | ||
|
|
d2f9d39144 | ||
|
|
b2be858b6b | ||
|
|
528b0d81fa | ||
|
|
f61d211643 | ||
|
|
3b3f276526 | ||
|
|
bee8866b9b | ||
|
|
2498f22381 | ||
|
|
4c4d2f55e5 | ||
|
|
5cbace86bb | ||
|
|
cdd269e017 | ||
|
|
aaf064e3d0 | ||
|
|
60d9850683 | ||
|
|
c7907d1afb | ||
|
|
8ba08534dd | ||
|
|
2025e27c71 | ||
|
|
90d110c30c | ||
|
|
d51af9a4bc | ||
|
|
0aa73ba456 | ||
|
|
ae7de9ab7a | ||
|
|
8355c4a970 | ||
|
|
0c780e04de | ||
|
|
eadcb28938 | ||
|
|
76882bebea | ||
|
|
e1b0eb161d | ||
|
|
ee642243d8 | ||
|
|
8bbc7a2113 | ||
|
|
48868bf226 | ||
|
|
c17135213a | ||
|
|
0cfea076d4 | ||
|
|
5c2b01401c | ||
|
|
a0ab201b99 | ||
|
|
69b14a980a | ||
|
|
a1c113140a | ||
|
|
bdbd06846b | ||
|
|
0530971149 | ||
|
|
32c7e96183 | ||
|
|
b5d84a9753 | ||
|
|
5f4e45adb7 | ||
|
|
4bd8807d28 | ||
|
|
ff92a3dba3 | ||
|
|
63d92fdce0 | ||
|
|
4d6c063861 | ||
|
|
34614a754f | ||
|
|
720d2d13b5 | ||
|
|
7cfd88e128 | ||
|
|
1d6f044809 | ||
|
|
6a9e64a1cf | ||
|
|
0b8300ed0d | ||
|
|
69b3e7dc0c | ||
|
|
735e2b2a71 | ||
|
|
b0071e2e01 | ||
|
|
4c4867a136 | ||
|
|
039a4d82c0 | ||
|
|
617291ccbf | ||
|
|
4bf117a3db | ||
|
|
5f57c51843 | ||
|
|
da0844e1bd | ||
|
|
f02901a25d | ||
|
|
664afdd0b9 | ||
|
|
82ef801cab | ||
|
|
3052d88426 | ||
|
|
a8ae2171ea | ||
|
|
85f840a028 | ||
|
|
6e9f26ce9d | ||
|
|
e4b69054b9 | ||
|
|
280cf42c30 | ||
|
|
d482c001a6 | ||
|
|
4abae449ac | ||
|
|
b1b2aab423 | ||
|
|
c83d8b1085 | ||
|
|
2d2762ee24 | ||
|
|
e197c27bd2 | ||
|
|
68c03417bf | ||
|
|
89e5ddb07f | ||
|
|
6e9a41fa35 | ||
|
|
c6180dfb93 | ||
|
|
4fb43de014 | ||
|
|
0593a77586 | ||
|
|
b9f67a8eec | ||
|
|
3edc69ca23 | ||
|
|
6aacfddcd1 | ||
|
|
27f3c16a5d | ||
|
|
2fce92bef2 | ||
|
|
a0f6e04887 | ||
|
|
6b0ff4089f | ||
|
|
c354af9518 | ||
|
|
8407097fbd | ||
|
|
708f994abb | ||
|
|
0bc2bb4fef | ||
|
|
0657f9d8be | ||
|
|
bd8c6abc37 | ||
|
|
491c206d67 | ||
|
|
05278ea7ec | ||
|
|
1a1222ac3c | ||
|
|
b78d43785c | ||
|
|
c32409e3eb | ||
|
|
68a3aab84a | ||
|
|
e57c842477 | ||
|
|
02d367830f | ||
|
|
6b1a4f349a | ||
|
|
d86b89219b | ||
|
|
2c86443542 | ||
|
|
7cc911abc0 | ||
|
|
262990a542 | ||
|
|
d312f2a9e2 | ||
|
|
09240a6210 | ||
|
|
c81e9b7b33 | ||
|
|
3aeaebc777 | ||
|
|
68def5c4fe | ||
|
|
2c52991c30 | ||
|
|
2006f0fab3 | ||
|
|
33e3828115 | ||
|
|
ec8b9502dc | ||
|
|
81235bff03 | ||
|
|
45f1781d86 | ||
|
|
2af2209a36 | ||
|
|
e444d7248f | ||
|
|
ec746dae39 | ||
|
|
91ef7c1855 | ||
|
|
bab10c2bd6 | ||
|
|
3367e66a49 | ||
|
|
16e87ee30c | ||
|
|
540b5fc8f9 | ||
|
|
08c610f875 | ||
|
|
505db16142 | ||
|
|
b52fae1103 | ||
|
|
87a62e5ec2 | ||
|
|
620a0ba986 | ||
|
|
a12ff14556 | ||
|
|
30bc321480 | ||
|
|
d33c4d923f | ||
|
|
04c7f18a6f | ||
|
|
5636c138dc | ||
|
|
94b1b92e1f | ||
|
|
f70542e5c6 | ||
|
|
19ff7c0bd2 | ||
|
|
323ea72dbc | ||
|
|
025fa43a0a | ||
|
|
5c9cd7eb9e | ||
|
|
718814ee2e | ||
|
|
bde7d17f70 | ||
|
|
9c2a89e412 | ||
|
|
58630c3f77 | ||
|
|
863eba71a2 | ||
|
|
8b9181ad17 | ||
|
|
bc549ab6fb | ||
|
|
c9bee61538 | ||
|
|
9d650dcf79 | ||
|
|
48fee21c90 | ||
|
|
37d919e4d2 | ||
|
|
d95e3e7b2a | ||
|
|
accebce312 | ||
|
|
e7103c54bb | ||
|
|
c8330ca159 | ||
|
|
16bf577980 | ||
|
|
7d0d626f29 | ||
|
|
fe5436e9d1 | ||
|
|
aa18bae235 | ||
|
|
08665b2cb5 | ||
|
|
9671287381 | ||
|
|
a59412d3e6 | ||
|
|
58b094f2d7 | ||
|
|
61dd005b5c | ||
|
|
13911a963a | ||
|
|
9fafed371d | ||
|
|
faa2fda34f | ||
|
|
ad33fc9829 | ||
|
|
c3b34246b9 | ||
|
|
dc69a56519 | ||
|
|
465845cb3b | ||
|
|
afa1dfc546 | ||
|
|
1f0163c6eb | ||
|
|
455753dadb | ||
|
|
859f7bd1e1 | ||
|
|
cf8a08614e | ||
|
|
e5a8ab3cbd | ||
|
|
b1d8e3f7cc | ||
|
|
80fedb8636 | ||
|
|
f26166ac86 | ||
|
|
c8e638580e | ||
|
|
09cdcbbcd1 | ||
|
|
bb06e1f835 | ||
|
|
3fe9a0dd18 | ||
|
|
f48b0a7bde | ||
|
|
bd835d766b | ||
|
|
04c47b2d37 | ||
|
|
df0c263fdf | ||
|
|
03bf0f0c21 | ||
|
|
29ee42f024 | ||
|
|
753e84afa0 | ||
|
|
ae7f142fa9 | ||
|
|
9952d0f2c2 | ||
|
|
cc6dd8c21c | ||
|
|
c9485dc166 | ||
|
|
cd45568c05 | ||
|
|
a2b0a30ee2 | ||
|
|
73899e2075 | ||
|
|
e1d709570b | ||
|
|
9de2306a16 | ||
|
|
ee540ad410 | ||
|
|
9859fa5530 | ||
|
|
d718220f9c | ||
|
|
ddc2dae380 | ||
|
|
dbb8befe34 | ||
|
|
c0303ce96d | ||
|
|
6205928e7b | ||
|
|
69d1397899 | ||
|
|
14add3efa4 | ||
|
|
142a71b4b1 | ||
|
|
0fb6c68bb5 | ||
|
|
73395188ac | ||
|
|
843a027fb7 | ||
|
|
682176fb85 | ||
|
|
0444ac78ca | ||
|
|
7f48d60614 | ||
|
|
7f427789d8 | ||
|
|
d484f86f0e | ||
|
|
529256a372 | ||
|
|
b334f05723 | ||
|
|
7d64a79a98 | ||
|
|
f01c53a3d3 | ||
|
|
f293c72081 | ||
|
|
7551b2b07c | ||
|
|
10db16ec0f | ||
|
|
785bf76708 | ||
|
|
675de8f2e9 | ||
|
|
e935aef5d8 | ||
|
|
88e1bbd73c | ||
|
|
807ea9a629 | ||
|
|
902f066ef6 | ||
|
|
7412250cc8 | ||
|
|
64e116966d | ||
|
|
2b909c55d7 | ||
|
|
a9b4056fff | ||
|
|
9de4f1e62f | ||
|
|
ae12cf57d6 | ||
|
|
a7efe01c02 | ||
|
|
4b75791094 | ||
|
|
294add68f9 | ||
|
|
25feb9d144 | ||
|
|
b218c188ef | ||
|
|
e85e0b7700 | ||
|
|
caf9217816 | ||
|
|
00ea8db687 | ||
|
|
09de7c0cee | ||
|
|
b500fad56d | ||
|
|
a825c99f66 | ||
|
|
11bccfb01d | ||
|
|
eb09da9eb8 | ||
|
|
69d6112701 | ||
|
|
9d7841bb44 | ||
|
|
30bde4c3bd | ||
|
|
25160ff2f0 | ||
|
|
662bc7e9ab | ||
|
|
2dc08cc9fc | ||
|
|
8ebcbdc3c2 | ||
|
|
081e8ff8e9 | ||
|
|
28acdf43d5 | ||
|
|
abd10897fc | ||
|
|
d6c1bd5c72 | ||
|
|
d1a726d59e | ||
|
|
b0d2f58200 | ||
|
|
c8e4582af3 | ||
|
|
2d8ab2b9d1 | ||
|
|
cb2c3a60e8 | ||
|
|
ade1cf8618 | ||
|
|
e784072201 | ||
|
|
a087a46b6b | ||
|
|
60725ae21a | ||
|
|
909b1807d6 | ||
|
|
a9f2b58f3d | ||
|
|
b579677b6f | ||
|
|
18345804b5 | ||
|
|
4d46d92d8d | ||
|
|
61a4e8eba2 | ||
|
|
e732a01562 | ||
|
|
f57a7307f3 | ||
|
|
8658fb9d01 | ||
|
|
5e4bfcb626 | ||
|
|
4a3657fbea | ||
|
|
bb8698869c | ||
|
|
d56dd29f24 | ||
|
|
ee15965a68 | ||
|
|
aff130c95e | ||
|
|
d74ab3c3f1 | ||
|
|
dc5483abab | ||
|
|
faae63b68a | ||
|
|
e255879488 | ||
|
|
85377d688e | ||
|
|
7a37b976c9 | ||
|
|
568dafa75c | ||
|
|
0430ac9452 | ||
|
|
d4709103ac | ||
|
|
a1d35fe68d | ||
|
|
9c329eec6c | ||
|
|
919c03a992 | ||
|
|
a424612068 | ||
|
|
70baaf3f5a | ||
|
|
cba17fe87d | ||
|
|
8b44e81736 | ||
|
|
6dcfefa662 | ||
|
|
1a8b3a3292 | ||
|
|
f47c024d9a | ||
|
|
70fa01fbdc | ||
|
|
dcd78fc1ae | ||
|
|
f1fdceeed4 | ||
|
|
c9d0c06d65 | ||
|
|
2db4088f68 | ||
|
|
b2ce860f3e | ||
|
|
55d2a91e2f | ||
|
|
bb886ced67 | ||
|
|
b802addee8 | ||
|
|
bd1ad65240 | ||
|
|
c30d1b707f | ||
|
|
32af4980d4 | ||
|
|
80b4cbea5a | ||
|
|
9917ce881f | ||
|
|
bd53030087 | ||
|
|
56e9340a1d | ||
|
|
db8d35f9de | ||
|
|
8dfd5597f9 | ||
|
|
e0891bae5a | ||
|
|
0cfff516bd | ||
|
|
a09401934e | ||
|
|
e9bdbb8ce2 | ||
|
|
51c119fe13 | ||
|
|
1f868ef0d9 | ||
|
|
45d56c2dce | ||
|
|
716a8ae7be | ||
|
|
7836bf28b3 | ||
|
|
cae717a78b | ||
|
|
9979d2701a | ||
|
|
15b122c918 | ||
|
|
9792839886 | ||
|
|
ea175223b4 | ||
|
|
a54bb1d65e | ||
|
|
fe95dc1c91 | ||
|
|
805ef0885f | ||
|
|
7838f4b2be | ||
|
|
9dab148a24 | ||
|
|
3c7ec6f05a | ||
|
|
459069710f | ||
|
|
57cd31984b | ||
|
|
96f39b03aa | ||
|
|
393bba741f | ||
|
|
ffd5f799d5 | ||
|
|
6ac254ac33 | ||
|
|
42ec6e5326 | ||
|
|
649a1b26ee | ||
|
|
c7cd09a1fa | ||
|
|
5e5cdb7e18 | ||
|
|
bc48711a73 | ||
|
|
35df90bae7 | ||
|
|
6ba1b2024f | ||
|
|
4ed3290a8e | ||
|
|
2776075ec6 | ||
|
|
2776b830a2 | ||
|
|
6c7cea9db8 | ||
|
|
a807b56192 | ||
|
|
d2c5c9bfa3 | ||
|
|
12524f4d89 | ||
|
|
4a568ba8dc | ||
|
|
2f7c2e6df9 | ||
|
|
a8b153d548 | ||
|
|
7a2d7598ff | ||
|
|
df7e0a1dbf | ||
|
|
45861ee4cf | ||
|
|
e89b4c4728 | ||
|
|
0cdd0efd86 | ||
|
|
fdc837e126 | ||
|
|
025d8777ea | ||
|
|
8cd2bf22ba | ||
|
|
d26620bfe0 | ||
|
|
21ea67a55d | ||
|
|
539d23bfce | ||
|
|
df6cfa9fb5 | ||
|
|
d604e0911f | ||
|
|
0c0c220056 | ||
|
|
7543211c4b | ||
|
|
74c979d0b8 | ||
|
|
84b37deb8e | ||
|
|
baf7a0b9a3 | ||
|
|
e8471f6e0f | ||
|
|
e9566e28b3 | ||
|
|
4dde10be1c | ||
|
|
0e26660b32 | ||
|
|
3ea3a6d396 | ||
|
|
8910864fde | ||
|
|
23346cd4eb | ||
|
|
3ea148d97a | ||
|
|
6b3ba9ccfb | ||
|
|
d5515f17f4 | ||
|
|
d92edd63f2 | ||
|
|
9f5912fcc1 | ||
|
|
c6e1265785 | ||
|
|
c16132eb33 | ||
|
|
55779207b8 | ||
|
|
87c2fc9251 | ||
|
|
a3b466c1c5 | ||
|
|
214cf1d2a2 | ||
|
|
ff56a5bd22 | ||
|
|
48601d13d2 | ||
|
|
8a1f683b3b | ||
|
|
f97e8d9ef0 | ||
|
|
9514c28dc6 | ||
|
|
dd7aefc4e5 | ||
|
|
9848b259f4 | ||
|
|
9b6e2261e8 | ||
|
|
4c48b4ce7b | ||
|
|
7cbd38c5a3 | ||
|
|
8c35fa9f32 | ||
|
|
fd44f61d54 | ||
|
|
487bdec13a | ||
|
|
0b4ffd06c5 | ||
|
|
a59b1728e8 | ||
|
|
343916614b |
2
.gitignore
vendored
@@ -1,3 +1,5 @@
|
||||
/node_modules/
|
||||
*~
|
||||
.DS_Store
|
||||
content/code_samples/*/node_modules/
|
||||
__pycache__
|
||||
|
||||
5
LICENSE
@@ -2,10 +2,9 @@ The Ripple Dev Portal and all its original contents are provided under the MIT L
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Ripple Dev Portal Copyright (c) 2014 Ripple Labs, Inc.
|
||||
Ripple Dev Portal Copyright (c) 2014, 2015 Ripple Labs, Inc.
|
||||
Flatdoc Copyright (c) 2013, 2014, Rico Sta. Cruz.
|
||||
jQuery Copyright (c) 2005, 2014 jQuery Foundation and other contributors,
|
||||
https://jquery.org/
|
||||
jQuery Copyright (c) 2005, 2014 jQuery Foundation and other contributors, https://jquery.org/
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
|
||||
87
README.md
@@ -1,6 +1,89 @@
|
||||
ripple-dev-portal
|
||||
=================
|
||||
|
||||
The [Ripple Developer Portal](https://dev.ripple.com) is the authoritative source for Ripple documentation, including the `rippled` server, Ripple-REST API, Gatewayd, and other Ripple software.
|
||||
The [Ripple Developer Portal](https://dev.ripple.com) is the authoritative source for Ripple documentation, including the `rippled` server, RippleAPI, the Ripple Data API, and other Ripple open-source software.
|
||||
|
||||
Please contribute pull requests to the **gh-pages** branch with any improvements or revisions.
|
||||
|
||||
Repository Layout
|
||||
-----------------
|
||||
|
||||
The HTML pages in this portal are generated from the markdown files in the [content/](content/) folder. Always edit the markdown files, not the HTML files.
|
||||
|
||||
The [tool/](tool/) folder contains a tool, called **Dactyl**, for generating the HTML files in the top level. The `dactyl_build.py` script uses the templates and the a YAML config file to generate HTML output. The `dactyl_link_checker.py` script checks the generated HTML content for broken links. The `dactyl_style_checker.py` script (experimental) checks the content for style guide violations.
|
||||
|
||||
In general, Dactyl assumes you are running it with `tool/` as the current working directory, and the included config uses the top level of this repository as the output directory.
|
||||
|
||||
Dactyl Setup
|
||||
------------
|
||||
|
||||
Dactyl uses Python 3 and a number of modules. First, make sure you have Python 3 installed in your local operating system, then use [PIP](https://pip.pypa.io/en/stable/) to install the dependencies:
|
||||
|
||||
`pip3 install -r tool/packages.txt`
|
||||
|
||||
|
||||
Building
|
||||
--------
|
||||
|
||||
The default configuration is [`dactyl-config.yml`](tool/dactyl-config.yml). You can specify an alternate config file with the `-c` or `--config` parameter:
|
||||
|
||||
`./dactyl_build.py -c alt-config.yml`
|
||||
`./dactyl_link_checker.py -c alt-config.yml`
|
||||
|
||||
This script does the following:
|
||||
|
||||
1. Chooses a target based on the commandline `-t` parameter. If not specified, uses the first target listed in the config file. If building for PDF, add the `--pdf your_output_file.pdf` parameter (The output filename must end in `.pdf`!)
|
||||
2. Reads the list of **pages** from the config.
|
||||
3. For all pages that have a filename as the `md` parameter in the config, it reads the file from the configured **content_path** and "preprocesses" any [Jinja2 Templating Language](http://jinja.pocoo.org/docs/dev/templates/) statements in those files. The markdown files can use this opportunity to include other files, or include or exclude content based on the `target` and `pages` parameters.
|
||||
4. For all pages that have a URL as the `md` parameter, it fetches the file via HTTP(S). No pre-processing occurs on such contents.
|
||||
5. For all the retrieved and preprocessed markdown files, it parses them using Python's markdown library, with extras enabled to approximate GitHub-flavored markdown.
|
||||
6. For each page, it parses the **template** configured for the page using Jinja2, falling back to the **default_template** (or **pdf_template**). If it produced HTML from a Markdown source, it passes that HTML as the `content` parameter to the template. It also passes in several other arguments from the config file, including definition of the current page as the `currentpage` parameter.
|
||||
7. It applies several post-processing steps on the generated HTML. Additional [filters](#filters) can be configured as plugins to run on a per-page or per-target basis. Dactyl always performs link substitution by target.
|
||||
8. If building for PDF: It outputs the resulting HTML files to the configured **temporary_files_path**, using filenames specified in the **html** parameter of each page in the config file. It also copies the **template_static_path** and **content_static_path** folders to the temporary folder. Then it runs [Prince](http://www.princexml.com/) to generate a PDF. It writes the generated PDF to the **out_path**.
|
||||
9. Otherwise: It outputs the resulting HTML files to the **out_path**. This does not generate a working copy of the site unless the necessary static files are also available at the **out_path**. (This is true by default, since the default output directory is the top level of the repository.) You can have it copy the configured **template_static_path** (containing files referenced by the templates) and the **content_static_path** (containing files referenced by the content) to the output directory using the `--copy_static` or `-s` parameter.
|
||||
|
||||
|
||||
Githubify Mode
|
||||
--------------
|
||||
|
||||
Alternate usage: `-g` produces a GitHub-flavored Markdown version of a single file. This parameter takes one argument, which should be a markdown file in the **content_path**. The tool uses Jinja2 to "preprocess" the file, as above, but stops after assembling GitHub-flavored Markdown and writes the output to the same filename in the **out_path**.
|
||||
|
||||
**Note:** The tool never erases files from the **out_path** or the **temporary_files_path**. You may want to do that yourself, especially if you remove files from your config or rename them.
|
||||
|
||||
|
||||
Multiple Targets
|
||||
----------------
|
||||
|
||||
You can define multiple **targets** in the config file with arbitrary key-value parameters. The two parameters that the tool cares about by default are **name** (used to identify the target on the commandline and in the pages section of the config) and **filters** (which lists filter plugins to apply, if provided).
|
||||
|
||||
By default, the tool builds the first target in the list. Every page in the `pages` array is included in every target unless the page definition includes an explicit list of **targets** to build. (Each member in the list should be the **name** of a target.)
|
||||
|
||||
The tool can perform automatic substitution of links in the resulting HTML (or Markdown, when using [githubify](#githubify-mode)). For each parameter in the page definition that matches the name of a target, it replaces links to the `html` file with the contents of the target-name-parameter. Anchors from the original link carry over. This allows you to link to other pages using the filenames from the local version of the site, but replace them with different links for a live site. (As seen in the default configuration, Ripple.com has very different URLs for many pages.)
|
||||
|
||||
Filters
|
||||
-------
|
||||
|
||||
Dactyl can apply various filters on document content, which is useful for handling compatibility with alternate Markdown flavors, among other things. The **filters** option, at the target or page level of the config, should contain an array of filters to apply. (Filters at the target level apply to all pages in that target; filters at the page level apply to that page only.) Each filter is implemented by a Python script in the Dactyl directory named `filter_{filter_name}.py`, based on the {filter_name} specified in the config.
|
||||
|
||||
Filters can apply at any or all of three steps: Raw markdown, raw HTML, or BeautifulSoup, as follows:
|
||||
|
||||
Raw markdown filters implement a `filter_markdown(md)` function, which inputs and outputs a string of markdown text.
|
||||
|
||||
Raw HTML filters implement a `filter_html(html)` function, which inputs and outputs a string of HTML text.
|
||||
|
||||
BeautifulSoup filters implement a `filter_soup(soup)` method, which takes a BeautifulSoup4 representation of the parsed HTML content as input. Because the input is passed by reference, the function modifies the soup in place instead of returning it.
|
||||
|
||||
Dactyl comes with the following filters:
|
||||
|
||||
* `remove_doctoc` - Remove DOCTOC-generated tables of contents
|
||||
* `multicode_tabs` - Un-comment <div class="multicode"> and </div> tags
|
||||
* `standardize_header_ids` - Modify the `id` fields of generated header (<h#>) elements to use dashes instead of underscores. (This is for compatibility with previously-used doc tools.)
|
||||
* `buttonize` - Adds the `button` class to links whose text ends in >
|
||||
* `markdown_in_divs` - Automatically add the `markdown="1"` element to <div> elements so that their contents get parsed as Markdown. (No longer used by the Dev Portal, but useful for compatibility with Markdown flavors that do this automatically.)
|
||||
|
||||
|
||||
Contributing
|
||||
------------
|
||||
|
||||
The Developer Portal welcomes outside contributions, especially to the documentation contents. If you have any corrections, improvements, or expansions of the portal, please contribute pull requests to the **master** branch.
|
||||
|
||||
Contributions become copyright Ripple and are provided under the MIT [LICENSE](LICENSE).
|
||||
|
||||
@@ -1,886 +0,0 @@
|
||||
# INTRODUCTION #
|
||||
|
||||
`ripple-rest : v1.1.1`
|
||||
|
||||
## Ripple-REST API ##
|
||||
|
||||
The `ripple-rest` API makes it easy to access the Ripple system via a RESTful web interface. In this section, we will cover the concepts you need to understand, and get you started accessing the API and learning how to use it.
|
||||
|
||||
While there are other API's to use with Ripple (i.e. Accessing the `rippled` server directly via a web socket), this documentation is meant only for the `ripple-rest` API as this is the high-level API recommended for working with Ripple and some of the endpoints provide abstractions to make it much easier to use than the traditional websocket API's.
|
||||
|
||||
Installation instructions and source code can be found in the `ripple-rest` repository <a href="https://github.com/ripple/ripple-rest" target="_blank">here</a>.
|
||||
|
||||
Older versions of the `ripple-rest` documentation will archived <a href="https://github.com/ripple/ripple-dev-portal/tree/master/archive" target="_blank">here</a>.
|
||||
|
||||
|
||||
## Available API Routes ##
|
||||
|
||||
* [`GET /v1/accounts/{:address}/payments/paths`](#preparing-a-payment)
|
||||
* [`GET /v1/accounts/{:address}/payments`](#confirming-a-payment)
|
||||
* [`GET /v1/accounts/{:address}/balances`](#account-balances)
|
||||
* [`GET /v1/accounts/{:address}/settings`](#account-settings)
|
||||
* [`GET /v1/accounts/{:address}/trustlines`](#reviewing-trustlines)
|
||||
* [`GET /v1/accounts/{:address}/notifications`](#checking-notifications)
|
||||
* [`GET /v1/server/connected`](#check-connection-state)
|
||||
* [`GET /v1/server`](#get-server-status)
|
||||
* [`GET /v1/tx`](#retrieve-ripple-transaction)
|
||||
* [`GET /v1/uuid`](#create-client-resource-id)
|
||||
|
||||
|
||||
* [`POST /v1/payments`](#submitting-a-payment)
|
||||
* [`POST /v1/accounts/{:address}/settings`](#updating-account-settings)
|
||||
* [`POST /v1/accounts/{:address}/trustlines`](#granting-a-trustline)
|
||||
|
||||
## API Overview ##
|
||||
|
||||
### Ripple Concepts ###
|
||||
|
||||
Ripple is a system for making financial transactions. You can use Ripple to send money anywhere in the world, in any currency, instantly and for free.
|
||||
|
||||
In the Ripple world, each account is identified by a <a href="https://ripple.com/wiki/Account" target="_blank">Ripple Address</a>. A Ripple address is a string that uniquely identifies an account, for example: `rNsJKf3kaxvFvR8RrDi9P3LBk2Zp6VL8mp`
|
||||
|
||||
A Ripple ___payment___ can be sent using Ripple's native currency, XRP, directly from one account to another. Payments can also be sent in other currencies, for example US dollars, Euros, Pounds or Bitcoins, though the process is slightly more complicated.
|
||||
|
||||
Payments are made between two accounts, by specifying the ___source___ and ___destination___ address for those accounts. A payment also involves an ___amount___, which includes both the numeric amount and the currency, for example: `100+XRP`.
|
||||
|
||||
When you make a payment in a currency other than XRP, you also need to include the Ripple address of the ___issuer___. The issuer is the gateway or other entity who holds the foreign-currency funds on your behalf. For foreign-currency payments, the amount will look something like this: `100+USD+rNsJKf3kaxvFvR8RrDi9P3LBk2Zp6VL8mp`.
|
||||
|
||||
While the `ripple-rest` API provides a high-level interface for sending and receiving payments, there are other endpoints within the API that you can use to work with generic ripple transactions, and to check the status of the Ripple server.
|
||||
|
||||
### Sending Payments ###
|
||||
|
||||
Sending a payment involves three steps:
|
||||
|
||||
1. You need to generate the payment object by doing using what is called a pathfind(preparing a payment). If the payment is to be made in a currency other than XRP, the Ripple system will identify the chain of trust, or ___path___, that connects the source and destination accounts; when creating the payment, the `ripple-rest` API will automatically find the set of possible paths for you.
|
||||
|
||||
2. You can modify the payment object if necessary, and then ___submit___ it to the API for processing. It is recommended to submit the payment object generated directly to prevent any errors from occuring.
|
||||
|
||||
3. Finally, you have to ___confirm___ that the payment has gone through by checking the payment's ___status___. This is because the payment submission is considered an asynchronous process, payments themselves can still fail even after they have been submitted successfully.
|
||||
|
||||
Note that when you submit a payment for processing, you have to assign a unique `client resource identifier` to that payment. This is a string which uniquely identifies the payment, and ensures that you do not accidentally submit the same payment twice. You can also use the `client_resource_id` to retrieve a payment once it has been submitted.
|
||||
|
||||
### Transaction Types ###
|
||||
|
||||
The Ripple protocol supports multiple types of transactions other than just payments. Transactions are considered to be any changes to the database made on behalf of a Ripple Address. Transactions are first constructed and then submitted to the network. After transaction processing, meta data is associated with the transaction which itemizes the resulting changes to the ledger.
|
||||
|
||||
+ Payment: Payment transaction is an authorized transfer of balance from one address to another.
|
||||
|
||||
+ Trustline: Trustline transaction is an authorized grant of trust between two addresses.
|
||||
|
||||
+ Setting: Setting transaction is an authorized update of account flags under a Ripple Account.
|
||||
|
||||
## Getting Started ##
|
||||
|
||||
### Setup ###
|
||||
|
||||
Before you can use the `ripple-rest` API, you will need to have three things:
|
||||
|
||||
* An installed version of `ripple-rest` running locally or remotely. Instructions on installing `ripple-rest` can be found in the readme.md file in the Github Repository <a href="https://github.com/ripple/ripple-rest" target="_blank">here</a>.
|
||||
|
||||
* An activated Ripple account. If you don't have a Ripple account, you can use the Ripple web client to create one, as described in the <a href="https://ripple.com/wiki/Client_Manual" target="_blank">Client Manual</a>. Make sure you have a copy of the Ripple address for your account; the address can be found by clicking on the __Receive__ tab in the web client.
|
||||
|
||||
* The URL of the server running the `ripple-rest` API that you wish to use. In this documentation, we will assume that the server is installed and running on a server you have connectivity to.
|
||||
|
||||
As a programmer, you will also need to have a suitable HTTP client library that allows you to make secure HTTP (`HTTPS`) requests. To follow the examples below, you will need to have access to the `curl` command-line tool.
|
||||
|
||||
|
||||
### Exploring the API ###
|
||||
|
||||
Let's start by using `curl` to see if the `ripple-rest` API is currently running. Type the following into a terminal window:
|
||||
|
||||
`curl http://[ripple-rest-server]/v1/server`
|
||||
|
||||
After a short delay, the following response should be displayed:
|
||||
|
||||
```js
|
||||
{
|
||||
"rippled_server_url": "wss://s-west.ripple.com:443",
|
||||
"rippled_server_status": {
|
||||
"build_version": "0.23.0",
|
||||
"complete_ledgers": "5526705-6142138",
|
||||
"fetch_pack": 2004,
|
||||
"hostid": "NEAT",
|
||||
"last_close": {
|
||||
"converge_time_s": 2.005,
|
||||
"proposers": 5
|
||||
},
|
||||
"load_factor": 1,
|
||||
"peers": 55,
|
||||
"pubkey_node": "n9KmrBnGoyVf89WYdiAnvGnKFaVqjLdAYjKrBuvg2r8pMxGPp6MF",
|
||||
"server_state": "full",
|
||||
"validated_ledger": {
|
||||
"age": 1,
|
||||
"base_fee_xrp": 0.00001,
|
||||
"hash": "BADDAB671EF21E8ED56B21253123D2C74139FE34E12DBE4B1F5527772EC88494",
|
||||
"reserve_base_xrp": 20,
|
||||
"reserve_inc_xrp": 5,
|
||||
"seq": 6142138
|
||||
},
|
||||
"validation_quorum": 3
|
||||
},
|
||||
"success": true,
|
||||
"api_documentation_url": "https://github.com/ripple/ripple-rest"
|
||||
}
|
||||
```
|
||||
|
||||
The `ripple-rest` API conforms to the following general behavior for a web interface:
|
||||
|
||||
* The HTTP method identifies what you are trying to do. Generally, HTTP `GET` requests are used to retrieve information, while HTTP `POST` requests are used to make changes or submit information.
|
||||
|
||||
* You make HTTP (or HTTPS) requests to the API endpoint, including the desired resources within the URL itself.
|
||||
|
||||
* If more complicated information needs to be sent, it will be included as JSON-formatted data within the body of the HTTP POST request.
|
||||
|
||||
* Upon completion, the server will return an HTTP status code of 200 (OK), and a `Content-Type` value of `application/json`. The body of the response will be a JSON-formatted object containing the information returned by the endpoint.
|
||||
|
||||
* The returned JSON object will include a `success` field indicating whether the request was successful or not.
|
||||
|
||||
|
||||
### Errors ###
|
||||
|
||||
There are two different ways in which errors are returned by the `ripple-rest` API:
|
||||
|
||||
Low-level errors are indicated by the server returning an appropriate HTTP status code. The following status codes are currently supported:
|
||||
|
||||
+ `Bad Request (400)` The JSON body submitted is malformed or invalid.
|
||||
+ `Method Not Accepted (404)` The endpoint is not allowed.
|
||||
+ `Gateway Timeout (502)` The rippled server is taking to long to respond.
|
||||
+ `Bad Gateway (504)` The rippled server is non-responsive.
|
||||
|
||||
Application-level errors are described further in the body of the JSON response with the following fields:
|
||||
|
||||
+ `success` This will be set to `false` if an error occurred.
|
||||
|
||||
+ `error` A short string identifying the error that occurred.
|
||||
|
||||
+ `message` A longer human-readable string explaining what went wrong.
|
||||
|
||||
|
||||
### API Objects ###
|
||||
|
||||
#### <a id="amount_object"></a> 1. Amount ####
|
||||
|
||||
All currencies on the Ripple Network have issuers, except for XRP. In the case of XRP, the `issuer` field may be omitted or set to `""`. Otherwise, the `issuer` must be a valid Ripple address of the gateway that issues the currency.
|
||||
|
||||
For more information about XRP see <a href="https://ripple.com/wiki/XRP" target="_blank">the Ripple wiki page on XRP</a>. For more information about using currencies other than XRP on the Ripple Network see <a href="https://ripple.com/wiki/Ripple_for_Gateways" target="_blank">the Ripple wiki page for gateways</a>.
|
||||
|
||||
Amount Object:
|
||||
|
||||
```js
|
||||
{
|
||||
"value": "1.0",
|
||||
"currency": "USD",
|
||||
"issuer": "r..."
|
||||
}
|
||||
```
|
||||
|
||||
or for XRP:
|
||||
|
||||
```js
|
||||
{
|
||||
"value": "1.0",
|
||||
"currency": "XRP",
|
||||
"issuer": ""
|
||||
}
|
||||
```
|
||||
|
||||
#### <a id="payment_object"></a> 2. Payment ####
|
||||
|
||||
The `Payment` object is a simplified version of the standard Ripple transaction format.
|
||||
|
||||
This `Payment` format is intended to be straightforward to create and parse, from strongly or loosely typed programming languages. Once a transaction is processed and validated it also includes information about the final details of the payment.
|
||||
|
||||
<!-- A minimal `Payment` object will look like this:
|
||||
|
||||
```js
|
||||
{
|
||||
"src_address": "rKXCummUHnenhYudNb9UoJ4mGBR75vFcgz",
|
||||
"dst_address": "rNw4ozCG514KEjPs5cDrqEcdsi31Jtfm5r",
|
||||
"dst_amount": {
|
||||
"value": "0.001",
|
||||
"currency": "XRP",
|
||||
"issuer": ""
|
||||
}
|
||||
}
|
||||
```
|
||||
-->
|
||||
|
||||
+ `source_address` is the Ripple address for the source account, as a string.
|
||||
|
||||
+ `destination_address` is the Ripple address for the destination account, as a string.
|
||||
|
||||
+ `destination_amount` is an [Amount](#amount_object) object representing the amount that should be deposited into the destination account.
|
||||
|
||||
The full set of fields accepted on `Payment` submission is as follows:
|
||||
|
||||
+ `source_tag` is an optional unsigned 32 bit integer (0-4294967294, inclusive) that is generally used if the sender is a hosted wallet at a gateway. This should be the same as the `destination_tag` used to identify the hosted wallet when they are receiving a payment.
|
||||
|
||||
+ `destination_tag` is an optional unsigned 32 bit integer (0-4294967294, inclusive) that is generally used if the receiver is a hosted wallet at a gateway.
|
||||
|
||||
+ `source_slippage` can be specified to give the `source_amount` a cushion and increase its chance of being processed successfully. This is helpful if the payment path changes slightly between the time when a payment options quote is given and when the payment is submitted. The `source_address` will never be charged more than `source_slippage` + the `value` specified in `source_amount`.
|
||||
|
||||
+ `invoice_id` is an optional 256-bit hash field that can be used to link payments to an invoice or bill.
|
||||
|
||||
+ `paths` is a "stringified" version of the Ripple PathSet structure. Most users of this API will want to treat this field as opaque. See the [Ripple Wiki](https://ripple.com/wiki/Payment_paths) for more information about Ripple pathfinding.
|
||||
|
||||
+ `flag_no_direct_ripple` is a boolean that can be set to `true` if `paths` are specified and the sender would like the Ripple Network to disregard any direct paths from the `source_address` to the `destination_address`. This may be used to take advantage of an arbitrage opportunity or by gateways wishing to issue balances from a hot wallet to a user who has mistakenly set a trustline directly to the hot wallet. Most users will not need to use this option.
|
||||
|
||||
+ `flag_partial_payment` is a boolean that, if set to true, indicates that this payment should go through even if the whole amount cannot be sent because of a lack of liquidity or funds in the `source_address` account. The vast majority of senders will never need to use this option.
|
||||
|
||||
Payment Object:
|
||||
|
||||
```js
|
||||
{
|
||||
/* User Specified */
|
||||
|
||||
"source_address": "rKXCummUHnenhYudNb9UoJ4mGBR75vFcgz",
|
||||
"source_tag": "",
|
||||
"source_amount": {
|
||||
"value": "0.001",
|
||||
"currency": "XRP",
|
||||
"issuer": ""
|
||||
},
|
||||
"source_slippage": "0",
|
||||
"destination_address": "rNw4ozCG514KEjPs5cDrqEcdsi31Jtfm5r",
|
||||
"destination_tag": "",
|
||||
"destination_amount": {
|
||||
"value": "0.001",
|
||||
"currency": "XRP",
|
||||
"issuer": ""
|
||||
},
|
||||
|
||||
/* Advanced Options */
|
||||
|
||||
"invoice_id": "",
|
||||
"paths": "[]",
|
||||
"flag_no_direct_ripple": false,
|
||||
"flag_partial_payment": false
|
||||
}
|
||||
```
|
||||
# PAYMENTS #
|
||||
|
||||
`ripple-rest` provides access to `ripple-lib`'s robust transaction submission processes. This means that it will set the fee, manage the transaction sequence numbers, sign the transaction with your secret, and resubmit the transaction up to 10 times if `rippled` reports an initial error that can be solved automatically.
|
||||
|
||||
## Making Payments ##
|
||||
|
||||
### Preparing a Payment ###
|
||||
|
||||
__GET /v1/accounts/{:address}/payments/paths/{destination_account}/{destination_amount}__
|
||||
|
||||
|
||||
To prepare a payment, you first make an HTTP `GET` call to the above endpoint. This will generate a list of possible payments between the two parties for the desired amount, taking into account the established trustlines between the two parties for the currency being transferred. You can then choose one of the returned payments, modify it if necessary (for example, to set slippage values or tags), and then submit the payment for processing.
|
||||
|
||||
The following URL parameters are required by this API endpoint:
|
||||
|
||||
+ `address` *[required]* The Ripple address for the source account.
|
||||
+ `destination_account` *[required]* The Ripple address for the destination account.
|
||||
+ `destination_amount` *[required]* The amount to be sent to the destination account. Note that this value uses `+` characters to separate the `value`, `currency` and `issuer` fields.
|
||||
+ For XRP, the format is: `0.1+XRP`
|
||||
|
||||
+ For other currencies, you need to include the Ripple address of the currency's issuer, like this: `0.1+USD+r...`
|
||||
|
||||
Optionally, you can also include the following as a query string parameter:
|
||||
|
||||
`source_currencies` *[optional]* A comma-separated list of source currencies. This is used to filter the returned list of possible payments. Each source currency can be specified either as a currency code (eg, `USD`), or as a currency code and issuer (eg, `USD+r...`). If the issuer is not specified for a currency other than XRP, then the results will be limited to the specified currency, but any issuer for that currency will be included in the results.
|
||||
|
||||
Note that this call is a wrapper around the [Ripple path-find](https://ripple.com/wiki/RPC_API#path_find) command, and returns an array of [`Payment`](#payment_object) objects, like this:
|
||||
|
||||
```js
|
||||
{
|
||||
"success": true,
|
||||
"payments": [
|
||||
{ /* Payment */ },
|
||||
{ /* Payment */ },
|
||||
...
|
||||
]
|
||||
}
|
||||
```
|
||||
You can then select the desired payment, modify it if necessary, and submit the payment object to the [`POST /v1/payments`](#submitting-a-payment) endpoint for processing.
|
||||
|
||||
__NOTE:__ This command may be quite slow. If the command times out, please try it again.
|
||||
|
||||
### Submitting a Payment ###
|
||||
|
||||
__`POST /v1/payments`__
|
||||
|
||||
Before you can submit a payment, you will need to have three pieces of information:
|
||||
|
||||
+ The [`Payment`](#payment_object) *[required]* object to be submitted.
|
||||
|
||||
+ The `secret` *[required]* or private key for your Ripple account.
|
||||
|
||||
__DO NOT SUBMIT YOUR SECRET TO AN UNTRUSTED REST API SERVER__ -- this is the key to your account and your money. If you are using the test server provided, only use test accounts to submit payments.
|
||||
|
||||
+ A `client_resource_id` *[required]* that will uniquely identify this payment. This is a 36-character UUID (universally unique identifier) value which will uniquely identify this payment within the `ripple-rest` API. Note that you can use the [`GET /v1/uuid`](#calculating_a_uuid) endpoint to calculate a UUID value if you do not have a UUID generator readily available.
|
||||
|
||||
This HTTP `POST` request must have a content-type of `application/json`, and the body of the request should look like this:
|
||||
|
||||
```js
|
||||
{
|
||||
"secret": "s...",
|
||||
"client_resource_id": "...",
|
||||
"payment": {
|
||||
"source_account": "rPs7nVbSops6xm4v77wpoPFf549cqjzUy9",
|
||||
"source_tag": "",
|
||||
"source_amount": {
|
||||
"value": "1",
|
||||
"currency": "XRP",
|
||||
"issuer": ""
|
||||
},
|
||||
"source_slippage": "0",
|
||||
"destination_account" "rKB4oSXwPkRpb2sZRhgGyRfaEhhYS6tf4M",
|
||||
"destination_tag": "",
|
||||
"destination_amount": {
|
||||
"value": "1",
|
||||
"currency": "XRP",
|
||||
"issuer": ""
|
||||
},
|
||||
"invoice_id": "",
|
||||
"paths": "[]",
|
||||
"no_direct_ripple": false,
|
||||
"partial_payment": false,
|
||||
"direction": "outgoing",
|
||||
"state": "validated",
|
||||
"result": "tesSUCCESS",
|
||||
"ledger": "6141074",
|
||||
"hash": "85C5E6762DE7969DC1BD69B3C8C7387A5B8FCE6A416AA1F74C0ED5D10F08EADD",
|
||||
"timestamp": "2014-04-18T01:21:00.000Z",
|
||||
"fee": "0.000012",
|
||||
"source_balance_changes":
|
||||
[
|
||||
{
|
||||
"value": "-1.000012",
|
||||
"currency": "XRP",
|
||||
"issuer": ""
|
||||
}
|
||||
],
|
||||
"destination_balance_changes":
|
||||
[
|
||||
{
|
||||
"value": "1",
|
||||
"currency": "XRP",
|
||||
"issuer": ""
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Upon completion, the server will return a JSON object which looks like the following:
|
||||
|
||||
```js
|
||||
{
|
||||
"success": true,
|
||||
"client_resource_id": "f2f811b7-dc3b-4078-a2c2-e4ca9e453981",
|
||||
"status_url": ".../v1/accounts/r1.../payments/f2f811b7-dc3b-4078-a2c2-e4ca9e453981"
|
||||
}
|
||||
```
|
||||
|
||||
The `status_url` value is a URL that can be queried to get the current status for this payment. This will be a reference to the `GET /v1/accounts/{account}/payments` endpoint, with the client resource ID filled in to retrieve the details of the payment. More information on this endpoint can be found in the section on [confirming a payment](#confirming-a-payment).
|
||||
|
||||
If an error occurred that prevented the payment from being submitted, the response object will look like this:
|
||||
|
||||
```js
|
||||
{
|
||||
"success": false,
|
||||
"error": "tecPATH_DRY",
|
||||
"message": "Path could not send partial amount. Please ensure that the src_address has sufficient funds (in the src_amount currency, if specified) to execute this transaction."
|
||||
}
|
||||
```
|
||||
|
||||
More information about transaction errors can be found on the [Ripple Wiki](https://ripple.com/wiki/Transaction_errors).
|
||||
|
||||
Note that payments cannot be cancelled once they have been submitted.
|
||||
|
||||
### Confirming a Payment ###
|
||||
|
||||
__`GET /v1/accounts/{:address}/payments/{:hash} or {:client_resource_id}`__
|
||||
|
||||
To confirm that your payment has been submitted successfully, you can call this API endpoint. The `hash` value can either be the transaction hash for the desired payment, or the payment's client resource ID.
|
||||
|
||||
The server will return the details of your payment:
|
||||
|
||||
```js
|
||||
{
|
||||
"success": true,
|
||||
"payment": {
|
||||
"source_account": "rPs7nVbSops6xm4v77wpoPFf549cqjzUy9",
|
||||
"source_tag": "",
|
||||
"source_amount": {
|
||||
"value": "1",
|
||||
"currency": "XRP",
|
||||
"issuer": ""
|
||||
},
|
||||
"source_slippage": "0",
|
||||
"destination_account" "rKB4oSXwPkRpb2sZRhgGyRfaEhhYS6tf4M",
|
||||
"destination_tag": "",
|
||||
"destination_amount": {
|
||||
"value": "1",
|
||||
"currency": "XRP",
|
||||
"issuer": ""
|
||||
},
|
||||
"invoice_id": "",
|
||||
"paths": "[]",
|
||||
"no_direct_ripple": false,
|
||||
"partial_payment": false,
|
||||
"direction": "outgoing",
|
||||
"state": "validated",
|
||||
"result": "tesSUCCESS",
|
||||
"ledger": "6141074",
|
||||
"hash": "85C5E6762DE7969DC1BD69B3C8C7387A5B8FCE6A416AA1F74C0ED5D10F08EADD",
|
||||
"timestamp": "2014-04-18T01:21:00.000Z",
|
||||
"fee": "0.000012",
|
||||
"source_balance_changes":
|
||||
[
|
||||
{
|
||||
"value": "-1.000012",
|
||||
"currency": "XRP",
|
||||
"issuer": ""
|
||||
}
|
||||
],
|
||||
"destination_balance_changes":
|
||||
[
|
||||
{
|
||||
"value": "1",
|
||||
"currency": "XRP",
|
||||
"issuer": ""
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
You can then check the `state` field to see if the payment has gone through; it will have the value "validated" when the payment has been validated and written to the Ripple ledger.
|
||||
|
||||
If the payment cannot be found, then an error will be returned instead:
|
||||
|
||||
```js
|
||||
{
|
||||
"success": true,
|
||||
"error": "Payment Not Found",
|
||||
"message": "This may indicate that the payment was never validated and written into the Ripple ledger and it was not submitted through this ripple-rest instance. This error may also be seen if the databases of either ripple-rest or rippled were recently created or deleted."
|
||||
}
|
||||
```
|
||||
|
||||
Note that there can be a delay in processing a submitted payment; if the payment does not exist yet, or has not been validated, you should wait for a short period of time before checking again.
|
||||
|
||||
## Receiving Payments ##
|
||||
|
||||
As well as sending payments, your application will need to know when incoming payments have been received. To do this, you first make the following API call:
|
||||
|
||||
__`GET /v1/accounts/{:address}/payments`__
|
||||
|
||||
This will return the most recent payments (both incoming and outgoing will be denoted in the direction)
|
||||
|
||||
```js
|
||||
{
|
||||
"success": true,
|
||||
"payments": [
|
||||
{ /* payment */ }.
|
||||
{ /* payment */ }.
|
||||
{ /* payment */ }.
|
||||
{ /* payment */ }.
|
||||
{ /* payment */ }
|
||||
]
|
||||
}
|
||||
```
|
||||
__`GET /v1/accounts/{:address}/payments?direction=incoming`__
|
||||
|
||||
This will return the most recent incoming payments for your account, up to a maximum of 20. You can process these historical payments if you want, and also retrieve more historical payments if you need to by using the `page` parameter, as described in the [Payment History](#payment-history) section below.
|
||||
|
||||
Regardless of what else you do with these payments, you need to extract the value of the `ledger` field from the most recent (ie, first) payment in the returned list. Convert this number to an integer and increment it by one. The resulting value, which will we call the `next_ledger` value, is the starting point for polling for new payments.
|
||||
|
||||
Your application should then periodically make the following API call:
|
||||
|
||||
__`GET /v1/accounts/{:address}/payments?direction=incoming&earliest_first=true&start_ledger={next_ledger}`__
|
||||
|
||||
This will return any _new_ payments which have been received, up to a maximum of 20. You should process these incoming payments. If you received a list of 20 payments, there may be more payments to be processed. You should then use the `page` parameter to get the next chunk of 20 payments, like this:
|
||||
|
||||
__`GET /v1/accounts/{:address}/payments?direction=incoming&earliest_first=true&start_ledger={next_ledger}&page=2`__
|
||||
|
||||
Continue retrieving the payments, incrementing the `page` parameter each time, until there are no new incoming payments to be processed.
|
||||
|
||||
__Note:__ We use the `earliest_first` parameter to retrieve the payments in ascending date order (ie, the oldest payment first). This ensures that if any more payments come in after the first API call with `start_ledger` set to `next_ledger`, you won't miss any payments. If you use the `page` parameter while retrieving the payments in descending order (ie, the most recent payment first), you may miss one or more payments while scanning through the pages.
|
||||
|
||||
Once you have retrieved all the payments, you should update your `next_ledger` value by once again taking the value of the `ledger` field from the most recent (ie, last) payment received, converting this value to an integer and incrementing it by one. This will give you the `next_ledger` value to use the next time you poll for payments.
|
||||
|
||||
Using this approach, you can regularly poll for new incoming payments, confident that no payments will be processed twice, and no incoming payments will be missed.
|
||||
|
||||
|
||||
## Payment History ##
|
||||
|
||||
__`GET /v1/accounts/{:address}/payments`__
|
||||
|
||||
This API endpoint can be used to browse through an account's payment history and also used to confirm specific payments after a payment has been submitted. The following query string parameters can be used to filter the list of returned payments:
|
||||
|
||||
+ `source_account` Filter the results to only include payments sent by the given account.
|
||||
|
||||
+ `destination_account` Filter the results to only include payments received by the given account.
|
||||
|
||||
+ `exclude_failed` If set to `true`, the results will only include payments which were successfully validated and written into the ledger. Otherwise, failed payments will be included.
|
||||
|
||||
+ `direction` Limit the results to only include the given type of payments. The following direction values are currently supported:
|
||||
+ `incoming`
|
||||
+ `outgoing`
|
||||
+ `pending`
|
||||
+ `earliest_first` If set to `true`, the payments will be returned in ascending date order. Otherwise, the payments will be returned in descending date order (ie, the most recent payment will be returned first). Defaults to `false`.
|
||||
|
||||
+ `start_ledger` The index for the starting ledger. If `earliest_first` is `true`, this will be the oldest ledger to be queried; otherwise, it will be the most recent ledger. Defaults to the first ledger in the `rippled` server's database.
|
||||
|
||||
+ `end_ledger` The index for the ending ledger. If `earliest_first` is `true`, this will be the most recent ledger to be queried; otherwise, it will be the oldest ledger. Defaults to the most recent ledger in the `rippled` server's database.
|
||||
|
||||
+ `results_per_page` The maximum number of payments to be returned at once. Defaults to 20.
|
||||
|
||||
+ `page` The page number to be returned. The first page of results will have page number `1`, the second page will have page number `2`, and so on. Defaults to `1`.
|
||||
|
||||
Upon completion, the server will return a JSON object which looks like the following:
|
||||
|
||||
```js
|
||||
{
|
||||
"success": true,
|
||||
"payments": [
|
||||
{
|
||||
"client_resource_id": "3492375b-d4d0-42db-9a80-a6a82925ccd5",
|
||||
"payment": {
|
||||
/* Payment */
|
||||
}
|
||||
}, {
|
||||
"client_resource_id": "4a4e3fa5-d81e-4786-8383-7164c3cc9b01",
|
||||
"payment": {
|
||||
/* Payment */
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
If the server returns fewer than `results_per_page` payments, then there are no more pages of results to be returned. Otherwise, increment the page number and re-issue the query to get the next page of results.
|
||||
|
||||
Note that the `ripple-rest` API has to retrieve the full list of payments from the server and then filter them before returning them back to the caller. This means that there is no speed advantage to specifying more filter values.
|
||||
|
||||
|
||||
|
||||
# ACCOUNTS #
|
||||
|
||||
`ripple-rest` provides the ability to review and confirm on information regarding your Ripple account. You can view your current balances and settings, as well as the ability to set your account setting flags.
|
||||
|
||||
## Account Balances ##
|
||||
|
||||
__`GET /v1/accounts/{:address}/balances`__
|
||||
|
||||
Retrieve the current balances for the given Ripple account.
|
||||
|
||||
The `account` parameter should be set to the Ripple address of the desired account. The server will return a JSON object which looks like the following:
|
||||
|
||||
```js
|
||||
{
|
||||
"success": true,
|
||||
"balances": [
|
||||
{
|
||||
"currency": "XRP",
|
||||
"amount": "1046.29877312",
|
||||
"issuer": ""
|
||||
},
|
||||
{
|
||||
"currency": "USD",
|
||||
"amount": "512.79",
|
||||
"issuer": "r...",
|
||||
}
|
||||
...
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
There will be one entry in the `balances` array for the account's XRP balance, and additional entries for each combination of currency code and issuer.
|
||||
|
||||
## Account Settings ##
|
||||
|
||||
You can retrieve an account's settings by using the following endpoint:
|
||||
|
||||
__`GET /v1/accounts/{account}/settings`__
|
||||
|
||||
The server will return a list of the current settings in force for the given account, in the form of a JSON object:
|
||||
|
||||
```js
|
||||
{
|
||||
"success": true,
|
||||
"settings": {
|
||||
"transfer_rate": 100,
|
||||
"password_spent": false,
|
||||
"require_destination_tag": false,
|
||||
"require_authorization": false,
|
||||
"disallow_xrp": false,
|
||||
"disable_master": false,
|
||||
"transaction_sequence": 22
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
The following account settings are currently supported:
|
||||
|
||||
+ `PasswordSpent` `true` if the password has been "spent", else `false`.
|
||||
<!--NOTE: This is not currently listed in the account settings schema, so I'm not sure what this setting is used for.
|
||||
-->
|
||||
+ `RequireDestTag` If this is set to `true`, incoming payments will only be validated if they include a `destination_tag` value. Note that this is used primarily by gateways that operate exclusively with hosted wallets.
|
||||
|
||||
+ `RequireAuth` If this is set to `true`, incoming trustlines will only be validated if this account first creates a trustline to the counterparty with the authorized flag set to true. This may be used by gateways to prevent accounts unknown to them from holding currencies they issue.
|
||||
|
||||
+ `DisallowXRP` If this is set to `true`, payments in XRP will not be allowed.
|
||||
|
||||
+ `EmailHash` The MD5 128-bit hash of the account owner's email address, if known.
|
||||
|
||||
+ `MessageKey` An optional public key, represented as a hex string, that can be used to allow others to send encrypted messages to the account owner.
|
||||
|
||||
+ `Domain` The domain name associated with this account.
|
||||
|
||||
+ `TransferRate` The rate charged each time a holder of currency issued by this account transfers some funds. The default rate is `"1.0"; a rate of `"1.01"` is a 1% charge on top of the amount being transferred. Up to nine decimal places are supported.
|
||||
|
||||
## Updating Account Settings ##
|
||||
|
||||
To change an account's settings, make an HTTP `POST` request to the above endpoint. The request must have a content-type of `application/json`, and the body of the request should look like this:
|
||||
|
||||
__`POST /v1/accounts/{account}/settings`__
|
||||
|
||||
```js
|
||||
{
|
||||
"secret": "s...",
|
||||
"settings": {
|
||||
"transfer_rate": 0,
|
||||
"password_spent": false,
|
||||
"require_destination_tag": false,
|
||||
"require_authorization": false,
|
||||
"disallow_xrp": false,
|
||||
"disable_master": false
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
The given settings will be updated.
|
||||
|
||||
# TRUSTLINES #
|
||||
|
||||
## Reviewing Trustlines ##
|
||||
|
||||
__`GET /v1/account/{:address}/trustlines`__
|
||||
|
||||
Retrieves all trustlines associated with the Ripple address. Upon completion, the server will return a JSON object which represents each trustline individually along with the currency, limit, and counterparty.
|
||||
|
||||
The following query string parameters are supported to provide additional filtering for either trustlines to a particular currency or trustlines from a specific counterparty:
|
||||
|
||||
+ `currency` Three letter currency denominations (i.e. USD, BTC).
|
||||
+ `counterparty` Ripple address of the counterparty trusted.
|
||||
|
||||
__`GET /v1/account/{:address}/trustlines?currency=USD&counterparty=rPs723Dsd...`__
|
||||
|
||||
The object returned looks like this:
|
||||
|
||||
```js
|
||||
{
|
||||
"success": true,
|
||||
"lines": [
|
||||
{
|
||||
"account": "rPs7nVbSops6xm4v77wpoPFf549cqjzUy9",
|
||||
"counterparty": "rMwjYedjc7qqtKYVLiAccJSmCwih4LnE2q",
|
||||
"currency": "USD",
|
||||
"trust_limit": "100",
|
||||
"reciprocated_trust_limit": "0",
|
||||
"account_allows_rippling": false,
|
||||
"counterparty_allows_rippling": true
|
||||
},
|
||||
{
|
||||
"account": "rPs7nVbSops6xm4v77wpoPFf549cqjzUy9",
|
||||
"counterparty": "rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs58B",
|
||||
"currency": "BTC",
|
||||
"trust_limit": "5",
|
||||
"reciprocated_trust_limit": "0",
|
||||
"account_allows_rippling": false,
|
||||
"counterparty_allows_rippling": true
|
||||
},
|
||||
{ /* trustline */ },
|
||||
{ /* trustline */ },
|
||||
{ /* trustline */ }
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
## Granting a Trustline ##
|
||||
|
||||
__`POST /v1/accounts/{:address}/trustlines`__
|
||||
|
||||
A trustline can also updated and simply set with a currency,amount,counterparty combination by submitting to this endpoint with the following JSON object.
|
||||
|
||||
```js
|
||||
{
|
||||
"secret": "sneThnzgBgxc3zXPG....",
|
||||
"trustline": {
|
||||
"limit": "110",
|
||||
"currency": "USD",
|
||||
"counterparty": "rMwjYedjc7qqtKYVLiAccJSmCwih4LnE2q",
|
||||
"allows_rippling": false
|
||||
}
|
||||
}
|
||||
```
|
||||
A successful submission will result in a returning JSON object that includes a transaction hash to the trustline transaction.
|
||||
|
||||
```js
|
||||
{
|
||||
"success": true,
|
||||
"line": {
|
||||
"account": "rPs7nVbSops6xm4v77wpoPGf549cqjzUy9",
|
||||
"counterparty": "rKB4oSXwPkRpb2sZRhgGyRfaEhhYS6tf4M",
|
||||
"currency": "USD",
|
||||
"trust_limit": "100",
|
||||
"allows_rippling": true
|
||||
},
|
||||
"ledger": "6146255",
|
||||
"hash": "6434F18B3997D81152F1AB31911E8D40E1346A05478419B7B3DF78B270C1151A"
|
||||
}
|
||||
```
|
||||
# NOTIFICATIONS #
|
||||
|
||||
Notifications can be used as a looping mechanism to monitor any transactions against your Ripple address or to confirm against missed notifications if your connection to `rippled` goes down. Notifications are generic and span across all types of Ripple transactions which is different than the "Payments" endpoints which specifically retrieve payment transactions. The "Payments" endpoints also provide full payment objects versus the notification objects which described the transaction at a higher level with less detail.
|
||||
|
||||
## Checking Notifications ##
|
||||
|
||||
__`GET /v1/accounts/{:address}/notifications/{:transaction_hash}`__
|
||||
|
||||
This endpoint will grab the notification based on the specific transaction hash specified. Once called the notification object retreived will provide information on the type of transaction and also the previous and next notifications will be shown as well. The `previous_notification_url` and `next_notification_url` can be used to walk up and down the notification queue. Once the `next_notification_url` is empty that means you have the most current notification, this applies for the `previous_notification_url` similarly when it's empty as it means you are holding the earliest notification available on the `rippled` you are connecting to.
|
||||
|
||||
A successful retrieval will look like this:
|
||||
|
||||
```js
|
||||
{
|
||||
"success": true,
|
||||
"notification": {
|
||||
"account": "rPs7nVbSops6xm4v77wpoPFf549cqjzUy9",
|
||||
"type": "payment",
|
||||
"direction": "outgoing",
|
||||
"state": "validated",
|
||||
"result": "tesSUCCESS",
|
||||
"ledger": "5704389",
|
||||
"hash": "EA1C8349FFFDB180BF6805FB69B32A41A5C86E27B4F79BED3CD8BA9A1E902721",
|
||||
"timestamp": "+046228-05-27T00:20:00.000Z",
|
||||
"transaction_url": "/v1/accounts/rPs7nVbSops6xm4v77wpoPFf549cqjzUy9/payments/EA1C8349FFFDB180BF6805FB69B32A41A5C86E27B4F79BED3CD8BA9A1E902721",
|
||||
"previous_hash": "1578758880412050B6C9C367DAE090B5452649549F00780276BED51BDEECF63C",
|
||||
"previous_notification_url": "/v1/accounts/rPs7nVbSops6xm4v77wpoPFf549cqjzUy9/notifications/1578758880412050B6C9C367DAE090B5452649549F00780276BED51BDEECF63C",
|
||||
"next_hash": "441E8AEC90A3674318710B4978E9598BD47190CF51E44CBD11C28FFF75FBC934",
|
||||
"next_notification_url": "/v1/accounts/rPs7nVbSops6xm4v77wpoPFf549cqjzUy9/notifications/441E8AEC90A3674318710B4978E9598BD47190CF51E44CBD11C28FFF75FBC934"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
The notification of the most recent transaction will show `next_notification_url` as an empty string.
|
||||
|
||||
The earliest notification available on the `rippled` server will show `previous_notification_url` as an empty string.
|
||||
|
||||
# RIPPLED SERVER STATUS #
|
||||
|
||||
The following two endpoints can be used to check if the `ripple-rest` API is currently connected to a `rippled` server, and to retrieve information about the current status of the API.
|
||||
|
||||
## Check Connection State ##
|
||||
<span></span>
|
||||
__`GET /v1/server/connected`__
|
||||
|
||||
Checks to see if the `ripple-rest` API is currently connected to a `rippled` server, and is ready to be used. This provides a quick and easy way to check to see if the API is up and running, before attempting to process transactions.
|
||||
|
||||
No additional parameters are required. Upon completion, the server will return `true` if the API is connected, and `false` otherwise.
|
||||
|
||||
```js
|
||||
{
|
||||
"success": true,
|
||||
"connected": true
|
||||
}
|
||||
```
|
||||
|
||||
## Get Server Status ##
|
||||
<span></span>
|
||||
__`GET /v1/server`__
|
||||
|
||||
Retrieve information about the current status of the `ripple-rest` API and the `rippled` server it is connected to.
|
||||
|
||||
This endpoint takes no parameters, and returns a JSON object with information on the current status of the API:
|
||||
|
||||
```js
|
||||
{
|
||||
"api_server_status": "online",
|
||||
"rippled_server_url": "wss://s_west.ripple.com:443",
|
||||
"rippled_server_status": {
|
||||
"info": {
|
||||
"build_version": "0.21.0-rc2",
|
||||
"complete_ledgers": "32570-4805506",
|
||||
"hostid": "BUSH",
|
||||
"last_close": {
|
||||
"converge_time_s": 2.011,
|
||||
"proposers": 5
|
||||
},
|
||||
"load_factor": 1,
|
||||
"peers": 51,
|
||||
"pubkey_node": "n9KNUUntNaDqvMVMKZLPHhGaWZDnx7soeUiHjeQE8ejR45DmHyfx",
|
||||
"server_state": "full",
|
||||
"validated_ledger": {
|
||||
"age": 2,
|
||||
"base_fee_xrp": 0.00001,
|
||||
"hash": "2B79CECB06A500A2FB92F4FB610D33A20CF8D7FB39F2C2C7C3A6BD0D75A1884A",
|
||||
"reserve_base_xrp": 20,
|
||||
"reserve_inc_xrp": 5,
|
||||
"seq": 4805506
|
||||
},
|
||||
"validation_quorum": 3
|
||||
}
|
||||
},
|
||||
"api_documentation_url": "https://github.com/ripple/ripple-rest"
|
||||
}
|
||||
```
|
||||
|
||||
If the server is not currently connected to the Ripple network, the following error will be returned:
|
||||
|
||||
```js
|
||||
{
|
||||
"success": false,
|
||||
"error": "rippled Disconnected",
|
||||
"message": "ripple-rest is unable to connect to the specified rippled server, or the rippled server is unable to communicate with the rest of the Ripple Network. Please check your internet and rippled server settings and try again"
|
||||
}
|
||||
```
|
||||
# UTILITIES #
|
||||
|
||||
## Retrieve Ripple Transaction ##
|
||||
|
||||
While the `ripple-rest` API is a high-level API built on top of the `rippled` server, there are times when you may need to access an underlying Ripple transaction rather than dealing with the `ripple-rest` data format. When you need to do this, you can retrieve a standard Ripple formatted transaction by using the following endpoint:
|
||||
|
||||
__`GET /v1/tx/{:transaction_hash}`__
|
||||
|
||||
This retrieves the underlying Ripple transaction with the given transaction hash value. Upon completion, the server will return following JSON object:
|
||||
|
||||
```js
|
||||
{
|
||||
"success": true,
|
||||
"tx": { /* Ripple Transaction */ }
|
||||
}
|
||||
```
|
||||
|
||||
Please refer to the [Transaction Format](https://ripple.com/wiki/Transactions) page in the Ripple Wiki for more information about Ripple transactions.
|
||||
|
||||
If the given transaction could not be found in the `rippled` server's historical database, the following error will be returned:
|
||||
|
||||
```js
|
||||
{
|
||||
"success": false,
|
||||
"error": "txnNotFound",
|
||||
"message": "Transaction not found."
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
## Create Client Resource ID ##
|
||||
<span></span>
|
||||
__`GET /v1/uuid`__
|
||||
|
||||
This endpoint creates a universally unique identifier (UUID) value which can be used to calculate a client resource ID for a payment. This can be useful if the application does not have a UUID generator handy.
|
||||
|
||||
This API endpoint takes no parameters, and returns a JSON object which looks like the following:
|
||||
|
||||
```js
|
||||
{
|
||||
"success": true,
|
||||
"uuid": "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx"
|
||||
}
|
||||
```
|
||||
@@ -1,512 +0,0 @@
|
||||
#INTRODUCTION
|
||||
|
||||
## Ripple-REST API (BETA)
|
||||
|
||||
_`ripple-rest` API is currently in BETA and subject to multiple changes and iterations as it is being finalized. Please double check with the_ <a href="https://github.com/ripple/ripple-rest" target="_blank">`ripple-rest`</a> _github repo for the most up-to-date versions and documentation. Feel free to poke around the branches to see what we're working on changing as well._
|
||||
|
||||
The `ripple-rest` API makes it easy to access the Ripple system via a RESTful web interface. In this section, we will cover the concepts you need to understand, and get you started accessing the API and learning how to use it.
|
||||
|
||||
While there are different APIs that you can use, for example by accessing the `rippled` server directly via a web socket, this documentation focuses on the `ripple-rest` API as this is the high-level API recommended for working with the Ripple system.
|
||||
|
||||
A test version of the `ripple-rest` server is up and running at:
|
||||
|
||||
<a href="https://ripple-rest.herokuapp.com" target="_blank">`https://ripple-rest.herokuapp.com`</a>
|
||||
|
||||
## Available API Routes
|
||||
|
||||
+ [`GET /api/v1/addresses/:address/payments/:dst_address/:dst_amount`](#preparing-a-payment)
|
||||
+ [`GET /api/v1/addresses/:address/next_notification`](#most-recent-notification)
|
||||
+ [`GET /api/v1/addresses/:address/next_notification/:prev-hash`](#checking-next-notification)
|
||||
+ [`GET /api/v1/addresses/:address/payments/:hash`](#retrieving-a-payment)
|
||||
+ [`GET /api/v1/status`](#check-rippled-status)
|
||||
+ [`POST /api/v1/addresses/:address/payments`](#submitting-a-payment)
|
||||
|
||||
## Ripple Concepts
|
||||
|
||||
### Ripple Address
|
||||
|
||||
Ripple is a system for making financial transactions. You can use Ripple to send money anywhere in the world, in any currency, instantly and for free.
|
||||
|
||||
In the Ripple world, each account is identified by a <a href="https://ripple.com/wiki/Account" target="_blank">Ripple Address</a>. A Ripple address is a string that uniquely identifies an account, for example: `rNsJKf3kaxvFvR8RrDi9P3LBk2Zp6VL8mp`
|
||||
|
||||
A Ripple ___payment___ can be sent using Ripple's native currency, XRP, directly from one account to another. Payments can also be sent in other currencies, for example US dollars, Euros, Pounds or Bitcoins, though the process is slightly more complicated.
|
||||
|
||||
Payments are made between two accounts, by specifying the ___source___ and ___destination___ address for those accounts. A payment also involves an ___amount___, which includes both the numeric amount and the currency, for example: `100+XRP`.
|
||||
|
||||
When you make a payment in a currency other than XRP, you also need to include the Ripple address of the ___issuer___. The issuer is the gateway or other entity who holds the foreign-currency funds on your behalf. For foreign-currency payments, the amount will look something like this: `100+USD+rNsJKf3kaxvFvR8RrDi9P3LBk2Zp6VL8mp`.
|
||||
|
||||
While the `ripple-rest` API provides a high-level interface for sending and receiving payments, there are other endpoints within the API that you can use to work with generic ripple transactions, and to check the status of the Ripple server.
|
||||
|
||||
### Sending Payments
|
||||
|
||||
Sending a payment involves three steps:
|
||||
|
||||
1. You need to create the payment object. If the payment is to be made in a currency other than XRP, the Ripple system will identify the chain of trust, or ___path___, that connects the source and destination accounts; when creating the payment, the `ripple-rest` API will automatically find the set of possible paths for you.
|
||||
|
||||
2. You can modify the payment object if necessary, and then ___submit___ it to the API for processing.
|
||||
|
||||
3. Finally, you can check to see if your payment has gone through by looking for the appropriate ___notification___.
|
||||
|
||||
You can also use notifications to see when a payment has been received.
|
||||
|
||||
### Transaction Types
|
||||
|
||||
The Ripple protocol supports multiple types of transactions other than just payments. Transactions are considered to be any changes to the database made on behalf of a Ripple Address. Transactions are first constructed and then submitted to the network. After transaction processing, meta data is associated with the transaction which itemizes the resulting changes to the ledger.
|
||||
|
||||
+ `Payment` - Payment transactions is an authorized transfer of balance from one address to another.
|
||||
+ `Trustline` - Trustline transactions is an authorized grant of trust between two addresses.
|
||||
|
||||
##Getting Started
|
||||
|
||||
### Setup
|
||||
|
||||
Before you can use the `ripple-rest` API, you will need to have two things:
|
||||
|
||||
* An activated Ripple account. If you don't have a Ripple account, you can use the Ripple web client to create one, as described in the <a href="https://ripple.com/wiki/Client_Manual" target="_blank">Client Manual</a>. Make sure you have a copy of the Ripple address for your account; the address can be found by clicking on the __Receive__ tab in the web client.
|
||||
|
||||
* The URL of the server running the `ripple-rest` API that you wish to use. In this documentation, we will assume that the server is running at <a href="https://ripple-rest.herokuapp.com" target="_blank">https://ripple-rest.herokuapp.com</a>, which is the URL for a test version of the server. When you follow the examples below, make sure that you replace this with the URL for the server you want to access. Please remember to only use
|
||||
|
||||
As a programmer, you will also need to have a suitable HTTP client library that allows you to make secure HTTP (`HTTPS`) requests. To follow the examples below, you will need to have access to the `curl` command-line tool.
|
||||
|
||||
|
||||
### Exploring the API
|
||||
|
||||
Let's start by using `curl` to see if the `ripple-rest` API is currently running. Type the following into a terminal window:
|
||||
|
||||
<a href="https://ripple-rest.herokuapp.com/api/v1/status" target="_blank">`curl https://ripple-rest.herokuapp.com/api/v1/status`</a>
|
||||
|
||||
After a short delay, the following response should be displayed:
|
||||
|
||||
```js
|
||||
{
|
||||
"api_server_status": "online",
|
||||
"rippled_server_url": "wss://s_west.ripple.com:443",
|
||||
"rippled_server_status": {
|
||||
"info": {
|
||||
"build_version": "0.21.0-rc2",
|
||||
"complete_ledgers": "32570-5254146",
|
||||
"hostid": "WEAN",
|
||||
"last_close": {
|
||||
"converge_time_s": 2.022,
|
||||
"proposers": 5
|
||||
},
|
||||
"load_factor": 1,
|
||||
"peers": 52,
|
||||
"pubkey_node": "n9LVyJ9GGBwHeeZ1bwPQUKj5P6vyD5tox2ozMPadMDvXx8CrPPmJ",
|
||||
"server_state": "full",
|
||||
"validated_ledger": {
|
||||
"age": 6,
|
||||
"base_fee_xrp": 1.0e-5,
|
||||
"hash": "ADF8BEFA91F4D355C60AE37E7ED79E91591704D052114F2BBDB6AF892E5E749E",
|
||||
"reserve_base_xrp": 20,
|
||||
"reserve_inc_xrp": 5,
|
||||
"seq": 5254146
|
||||
},
|
||||
"validation_quorum": 3
|
||||
}
|
||||
},
|
||||
"api_documentation_url": "https://github.com/ripple/ripple-rest"
|
||||
}
|
||||
```
|
||||
#### Using the API ####
|
||||
|
||||
The `ripple-rest` API conforms to the following general behavior for a web interface:
|
||||
|
||||
* The HTTP method identifies what you are trying to do. Generally, HTTP `GET` requests are used to retrieve information, while HTTP `POST` requests are used to make changes or submit information.
|
||||
|
||||
* You make HTTP (or HTTPS) requests to the API endpoint, including the desired resources within the URL itself.
|
||||
|
||||
* If more complicated information needs to be sent, it will be included as JSON-formatted data within the body of the HTTP POST request.
|
||||
|
||||
* Upon completion, the server will return an HTTP status code of 200 (OK), and a `Content-Type` value of `application/json`. The body of the response will be a JSON-formatted object containing the information returned by the endpoint.
|
||||
|
||||
* The returned JSON object will include a `success` field indicating whether the request was successful or not.
|
||||
|
||||
### Errors
|
||||
|
||||
Errors can be represented by general HTTP response codes. Errors specific to `ripple-rest` will return a 200 status but will include `error` and `message` fields, where `error` is a short string identifying the error that occurred, and `message` will be a longer human-readable string explaining what went wrong.
|
||||
|
||||
### API Objects
|
||||
|
||||
#### 1. Amount
|
||||
|
||||
All currencies on the Ripple Network have issuers, except for XRP. In the case of XRP, the `"issuer"` field may be omitted or set to `""`. Otherwise, the `"issuer"` must be a valid Ripple address of the gateway that issues the currency.
|
||||
|
||||
For more information about XRP see <a href="https://ripple.com/wiki/XRP" target="_blank">the Ripple wiki page on XRP</a>. For more information about using currencies other than XRP on the Ripple Network see <a href="https://ripple.com/wiki/Ripple_for_Gateways" target="_blank">the Ripple wiki page for gateways</a>.
|
||||
|
||||
Note that the `value` can either be specified as a string or a number. Internally this API uses a BigNumber library to retain higher precision if numbers are inputted as strings.
|
||||
|
||||
`Amount Object:`
|
||||
|
||||
```js
|
||||
{
|
||||
"value": "1.0",
|
||||
"currency": "USD",
|
||||
"issuer": "r..."
|
||||
}
|
||||
```
|
||||
`Or for XRP:`
|
||||
|
||||
```js
|
||||
{
|
||||
"value": "1.0",
|
||||
"currency": "XRP",
|
||||
"issuer": ""
|
||||
}
|
||||
```
|
||||
|
||||
#### 2. Payment
|
||||
|
||||
The `Payment` object is a simplified version of the standard Ripple transaction format.
|
||||
|
||||
This `Payment` format is intended to be straightforward to create and parse, from strongly or loosely typed programming languages. Once a transaction is processed and validated it also includes information about the final details of the payment.
|
||||
|
||||
The following fields are the minimum required to submit a `Payment`:
|
||||
|
||||
+ `src_address` is the Ripple address for the source account, as a string.
|
||||
+ `dst_address` is the Ripple address for the destination account, as a string.
|
||||
|
||||
+ `dst_amount` is an [Amount](#1-amount) object representing the amount that should be deposited into the destination account.
|
||||
|
||||
```js
|
||||
{
|
||||
"src_address": "rKXCummUHnenhYudNb9UoJ4mGBR75vFcgz",
|
||||
"dst_address": "rNw4ozCG514KEjPs5cDrqEcdsi31Jtfm5r",
|
||||
"dst_amount": {
|
||||
"value": "0.001",
|
||||
"currency": "XRP",
|
||||
"issuer": ""
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
The full set of fields accepted on `Payment` submission is as follows:
|
||||
|
||||
+ `src_tag` is an optional unsigned 32 bit integer (0-4294967294, inclusive) that is generally used if the sender is a hosted wallet at a gateway. This should be the same as the `dst_tag` used to identify the hosted wallet when they are receiving a payment.
|
||||
+ `dst_tag` is an optional unsigned 32 bit integer (0-4294967294, inclusive) that is generally used if the receiver is a hosted wallet at a gateway
|
||||
+ `src_slippage` can be specified to give the `src_amount` a cushion and increase its chance of being processed successfully. This is helpful if the payment path changes slightly between the time when a payment options quote is given and when the payment is submitted. The `src_address` will never be charged more than `src_slippage` + the `value` specified in `src_amount`
|
||||
+ `invoice_id` is an optional 256-bit hash field that can be used to link payments to an invoice or bill
|
||||
+ `paths` is a "stringified" version of the Ripple PathSet structure. Most users of this API will want to treat this field as opaque. See the [Ripple Wiki](https://ripple.com/wiki/Payment_paths) for more information about Ripple pathfinding
|
||||
+ `flag_no_direct_ripple` is a boolean that can be set to `true` if `paths` are specified and the sender would like the Ripple Network to disregard any direct paths from the `src_address` to the `dst_address`. This may be used to take advantage of an arbitrage opportunity or by gateways wishing to issue balances from a hot wallet to a user who has mistakenly set a trustline directly to the hot wallet. Most users will not need to use this option.
|
||||
+ `flag_partial_payment` is a boolean that, if set to true, indicates that this payment should go through even if the whole amount cannot be sent because of a lack of liquidity or funds in the `src_address` account. The vast majority of senders will never need to use this option.
|
||||
|
||||
```js
|
||||
{
|
||||
/* User Specified */
|
||||
|
||||
"src_address": "rKXCummUHnenhYudNb9UoJ4mGBR75vFcgz",
|
||||
"src_tag": "",
|
||||
"src_amount": {
|
||||
"value": "0.001",
|
||||
"currency": "XRP",
|
||||
"issuer": ""
|
||||
},
|
||||
"src_slippage": "0",
|
||||
"dst_address": "rNw4ozCG514KEjPs5cDrqEcdsi31Jtfm5r",
|
||||
"dst_tag": "",
|
||||
"dst_amount": {
|
||||
"value": "0.001",
|
||||
"currency": "XRP",
|
||||
"issuer": ""
|
||||
},
|
||||
|
||||
/* Advanced Options */
|
||||
|
||||
"invoice_id": "",
|
||||
"paths": "[]",
|
||||
"flag_no_direct_ripple": false,
|
||||
"flag_partial_payment": false
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
When a payment is confirmed in the Ripple ledger, it will have additional fields added:
|
||||
|
||||
+ `tx_result` will be `tesSUCCESS` if the transaction was successfully processed. If it was unsuccessful but a transaction fee was claimed the code will start with `tec`. More information about transaction errors can be found on the [Ripple Wiki](https://ripple.com/wiki/Transaction_errors).
|
||||
+ `tx_timestamp` is the UNIX timestamp for when the transaction was validated
|
||||
+ `tx_fee` is the network transaction fee charged for processing the transaction. For more information on fees, see the [Ripple Wiki](https://ripple.com/wiki/Transaction_fees). In the standard Ripple transaction format fees are expressed in drops, or millionths of an XRP, but for clarity the new formats introduced by this API always use the full XRP unit.
|
||||
+ `tx_src_bals_dec` is an array of [`Amount`](#1-amount) objects representing all of the balance changes of the `src_address` caused by the payment. Note that this includes the `tx_fee`
|
||||
+ `tx_dst_bals_inc` is an array of [`Amount`](#1-amount) objects representing all of the balance changes of the `dst_address` caused by the payment
|
||||
|
||||
```js
|
||||
{
|
||||
/* ... */
|
||||
|
||||
/* Generated After Validation */
|
||||
|
||||
"tx_direction": "outgoing",
|
||||
"tx_state": "confirmed",
|
||||
"tx_result": "tesSUCCESS",
|
||||
"tx_ledger": 4696959,
|
||||
"tx_hash": "55BA3440B1AAFFB64E51F497EFDF2022C90EDB171BBD979F04685904E38A89B7",
|
||||
"tx_timestamp": 1391025100000,
|
||||
"tx_timestamp_human": "2014-01-29T19:51:40.000Z",
|
||||
"tx_fee": "0.000012",
|
||||
"tx_src_bals_dec": [{
|
||||
"value": "-0.001012",
|
||||
"currency": "XRP",
|
||||
"issuer": ""
|
||||
}],
|
||||
"tx_dst_bals_inc": [{
|
||||
"value": "0.001",
|
||||
"currency": "XRP",
|
||||
"issuer": ""
|
||||
}]
|
||||
}
|
||||
```
|
||||
|
||||
#### 3. Notification
|
||||
|
||||
Notifications are new type of object not used elsewhere on the Ripple Network but intended to simplify the process of monitoring accounts for new activity.
|
||||
|
||||
If there is a new `Notification` for an account it will contain information about the type of transaction that affected the account, as well as a link to the full details of the transaction and a link to get the next notification.
|
||||
|
||||
|
||||
If there is a new `notification` for an account, it will come in this format:
|
||||
|
||||
+ `timestamp` is the UNIX timestamp for when the transaction was validated, or the number of milliseconds since January 1st, 1970 (00:00 UTC)
|
||||
+ `timestamp_human` is the transaction validation time represented in the format `YYYY-MM-DDTHH:mm:ss.sssZ`. The timezone is always UTC as denoted by the suffix "Z"
|
||||
+ `transaction_url` is a URL that can be queried to retrieve the full details of the transaction. If it the transaction is a payment it will be returned in the `Payment` object format, otherwise it will be returned in the standard Ripple transaction format
|
||||
+ `next_notification_url` is a URL that can be queried to get the notification following this one for the given address
|
||||
+ `source_transaction_id` will be the same as the `source_transaction_id` originally submitted by the sender. Senders should look for the `source_transaction_id`'s of payments they have submitted to `ripple-rest` amongst `Notification`s of validated payments. If the `source_transaction_id` of a particular payment appears in a `Notification` with the `state` listed as `validated`, then that payment has been successfully written into the Ripple Ledger
|
||||
|
||||
```js
|
||||
{
|
||||
"address": "rKXCummUHnenhYudNb9UoJ4mGBR75vFcgz",
|
||||
"type": "payment",
|
||||
"tx_direction": "outgoing",
|
||||
"tx_state": "confirmed",
|
||||
"tx_result": "tesSUCCESS",
|
||||
"tx_ledger": 4696959,
|
||||
"tx_hash": "55BA3440B1AAFFB64E51F497EFDF2022C90EDB171BBD979F04685904E38A89B7",
|
||||
"tx_timestamp": 1391025100000,
|
||||
"tx_timestamp_human": "2014-01-29T19:51:40.000Z",
|
||||
"tx_url":"http://api/v1/addresses/r../payments/55B..",
|
||||
"next_notification_url":"http://api/v1/addresses/r../next_notification/5.."
|
||||
"confirmation_token": "55BA3440B1AAFFB64E51F497EFDF2022C90EDB171BBD979F04685904E38A89B7"
|
||||
}
|
||||
```
|
||||
|
||||
If there are no new notifications, the empty `Notification` object will be returned in this format:
|
||||
|
||||
+ `type` will be `none` if there are no new notifications
|
||||
+ `tx_state` will be `pending` if there are still transactions waiting to clear and `empty` otherwise
|
||||
+ `next_notification_url` will be provided whether there are new notifications or not so that that field can always be used to query the API for new notifications.
|
||||
|
||||
```js
|
||||
{
|
||||
"address": "rKXCummUHnenhYudNb9UoJ4mGBR75vFcgz",
|
||||
"type": "none",
|
||||
"tx_direction": "",
|
||||
"tx_state": "empty",
|
||||
"tx_result": "",
|
||||
"tx_ledger": "",
|
||||
"tx_hash": "",
|
||||
"tx_timestamp": "",
|
||||
"tx_timestamp_human": "",
|
||||
"tx_url": "",
|
||||
"next_notification_url": "http://api/v1/addresses/r../next_notification/5..",
|
||||
"confirmation_token": ""
|
||||
}
|
||||
```
|
||||
|
||||
# PAYMENTS
|
||||
|
||||
`ripple-rest` provides access to `ripple-lib`'s robust transaction submission processes. This means that it will set the fee, manage the transaction sequence numbers, sign the transaction with your secret, and resubmit the transaction up to 10 times if `rippled` reports an initial error that can be solved automatically.
|
||||
|
||||
## Making Payments
|
||||
|
||||
### Preparing a Payment
|
||||
|
||||
#### `GET /api/v1/addresses/:address/payments/:dst_address/:dst_amount`
|
||||
|
||||
A payment needs to be formatted in the following order with the payment object to be submitted as a valid payment.
|
||||
|
||||
```js
|
||||
{
|
||||
"secret": "s...",
|
||||
"payment": { /* Payment Object */
|
||||
"source_address": "rKXCummUHnenhYudNb9UoJ4mGBR75vFcgz",
|
||||
"source_transaction_id": "12345",
|
||||
"destination_address": "rNw4ozCG514KEjPs5cDrqEcdsi31Jtfm5r",
|
||||
"destination_amount": {
|
||||
"value": "0.001",
|
||||
"currency": "XRP",
|
||||
"issuer": ""
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
The payment object itself can be prepared manually for any transactions that are occuring directly with XRP or if there are already established trustlines between the two parties for the currency being transferred. In most cases, a payment object can be created automatically by performing a `GET` on the payments endpoint.
|
||||
|
||||
This call generates possible payments for a given set of parameters. This is a wrapper around the [Ripple path-find command](https://ripple.com/wiki/RPC_API#path_find) that returns an array of [`Payment Objects`](#2-payment), which can be submitted directly.
|
||||
|
||||
This uses the [`Payment` Object format](#2-payment).
|
||||
|
||||
The `:dst_amount` parameter uses `+` to separate the `value`, `currency`, and `issuer` fields. For XRP the format is `0.1+XRP` and for other currencies it is `0.1+USD+r...`, where the `r...` is the Ripple address of the currency's issuer.
|
||||
|
||||
__NOTE:__ This command may be quite slow. If the command times out, please try it again.
|
||||
|
||||
### Submitting a Payment
|
||||
|
||||
#### `POST /api/v1/addresses/:address/payments`
|
||||
|
||||
Submit a payment in the [`Payment` Object](#2-payment) format.
|
||||
|
||||
__DO NOT SUBMIT YOUR SECRET TO AN UNTRUSTED REST API SERVER__ -- this is the key to your account and your money. If you are using the test server provided, only use test accounts to submit payments.
|
||||
|
||||
Request JSON:
|
||||
```js
|
||||
{
|
||||
"secret": "s...",
|
||||
"payment": { /* Payment */ }
|
||||
}
|
||||
```
|
||||
|
||||
Response:
|
||||
|
||||
```js
|
||||
{
|
||||
"success": true,
|
||||
"confirmation_token": "55BA3440B1AAFFB64E51F497EFDF2022C90EDB171BBD979F04685904E38A89B7"
|
||||
}
|
||||
```
|
||||
Or if there is a problem with the transaction:
|
||||
|
||||
```js
|
||||
{
|
||||
"success": false,
|
||||
"error": "tecPATH_DRY",
|
||||
"message": "Path could not send partial amount. Please ensure that the src_address has sufficient funds (in the src_amount currency, if specified) to execute this transaction."
|
||||
}
|
||||
```
|
||||
More information about transaction errors can be found on the [Ripple Wiki](https://ripple.com/wiki/Transaction_errors).
|
||||
|
||||
Save the `confirmation_token` to check for transaction confirmation by matching that against new `notification`'s. Payments cannot be cancelled once they are submitted.
|
||||
|
||||
### Confirming a Payment
|
||||
|
||||
#### `GET /api/v1/addresses/:address/next_notification/:tx_hash`
|
||||
|
||||
A payment can be confirmed by retrieving a notification with the `confirmation_token` from the sucessfully submited payment. The tx_state will be "confirmed" if the payment has successfully gone through.
|
||||
|
||||
```js
|
||||
{
|
||||
"success": true,
|
||||
"notification": {
|
||||
"address": "rNw4ozCG514KEjPs5cDrqEcdsi31Jtfm5r",
|
||||
"type": "payment",
|
||||
"tx_direction": "outgoing",
|
||||
"tx_state": "confirmed",
|
||||
"tx_result": "tesSUCCESS",
|
||||
"tx_ledger": 4850743,
|
||||
"tx_hash": "81D48826FA84B0B83902CA3BFE49E2503A5BA1069B214D492AE6AB145B6C4781",
|
||||
"tx_timestamp": 1391792990000,
|
||||
"tx_timestamp_human": "2014-02-07T17:09:50.000Z",
|
||||
"tx_url": "https://api/v1/addresses/r../payments/81..?ledger=4850743",
|
||||
"next_notification_url": "https://api/v1/addresses/r../next_notification/81..?ledger=4850743"
|
||||
"confirmation_token": "81D48826FA84B0B83902CA3BFE49E2503A5BA1069B214D492AE6AB145B6C4781"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#MONITORING
|
||||
|
||||
Applications will not only need to submit payments but monitor all incoming transactions that our occuring against the Ripple address. The general rule of thumb for monitoring your account should be the following:
|
||||
|
||||
1. Checking the most recent notification
|
||||
2. Checking the next notification
|
||||
|
||||
## Checking Notifications
|
||||
|
||||
### Most recent notification
|
||||
|
||||
#### `GET /api/v1/addresses/:address/next_notification`
|
||||
|
||||
Use this to retrieve the most recent notification on the account:
|
||||
|
||||
To find out more information about that payment follow the link at `tx_url`. Otherwise follow the `next_notification_url` and check for the next notification.
|
||||
|
||||
If notifications are being retrieved from a `rippled` server that does not have a full historical database, the response may have serveral blank fields.
|
||||
|
||||
```js
|
||||
{
|
||||
"success": true,
|
||||
"notification": {
|
||||
"address": "rKXCummUHnenhYudNb9UoJ4mGBR75vFcgz",
|
||||
"type": "payment",
|
||||
"tx_direction": "incoming",
|
||||
"tx_state": "confirmed",
|
||||
"tx_result": "tesSUCCESS",
|
||||
"tx_ledger": 4716034,
|
||||
"tx_hash": "EC19E24AA51D39E809597A5DCF3A7E253F98C27FE3287CB919319A5C59AD8302",
|
||||
"tx_timestamp": 1391130630000,
|
||||
"tx_timestamp_human": "2014-01-31T01:10:30.000Z",
|
||||
"tx_url": "http://ripple-rest.herokuapp.com:49598/api/v1/addresses/rKXCummUHnenhYudNb9UoJ4mGBR75vFcgz/payments/EC19E24AA51D39E809597A5DCF3A7E253F98C27FE3287CB919319A5C59AD8302?ledger=4716034",
|
||||
"next_notification_url": "http://ripple-rest.herokuapp.com:49598/api/v1/addresses/rKXCummUHnenhYudNb9UoJ4mGBR75vFcgz/next_notification/EC19E24AA51D39E809597A5DCF3A7E253F98C27FE3287CB919319A5C59AD8302?ledger=4716034"
|
||||
"confirmation_token": ""
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Checking next notification
|
||||
|
||||
#### `GET /api/v1/addresses/:address/next_notification/:prev_tx_hash`
|
||||
|
||||
By checking for the most recent notification above, take the hash from the most recent notification to monitor if another notification has arrived. If there is no notifications newer than the most recent, than you will receive the notification object with:
|
||||
|
||||
`"type": "none"`
|
||||
`"tx_state": "empty"`
|
||||
|
||||
Because the `type` is `none` and the `tx_state` is `empty`, that means there is no next notification (yet) and there are no transactions pending in the outgoing queue. A `tx_state` of `pending` would indicate that there are still transactions waiting for confirmation.
|
||||
|
||||
If there is a newer notification than the one you are checking on, than the response will contain a new notification object.
|
||||
|
||||
## Retrieving a Payment
|
||||
|
||||
#### `GET /api/v1/addresses/:address/payments/:tx_hash`
|
||||
|
||||
Use this to retrieve the details of a specfic payment with the transaction hash. A [`Payment` object format](#2-payment) will be returned with the details of the payment filled out including the path of the payment.
|
||||
|
||||
#RIPPLED SERVER STATUS
|
||||
|
||||
It is important to be able to check on the status of the `ripple-rest` server and the connected `rippled` server that it is currently connected to.
|
||||
|
||||
## Check 'rippled' Status
|
||||
|
||||
#### `GET /api/v1/status`
|
||||
|
||||
Will return the status of the current `rippled` server that the `ripple-rest` server is configured to communicate with. The response body looks like this:
|
||||
|
||||
```js
|
||||
{
|
||||
"api_server_status": "online",
|
||||
"rippled_server_url": "wss://s_west.ripple.com:443",
|
||||
"rippled_server_status": {
|
||||
"info": {
|
||||
"build_version": "0.21.0-rc2",
|
||||
"complete_ledgers": "32570-4805506",
|
||||
"hostid": "BUSH",
|
||||
"last_close": {
|
||||
"converge_time_s": 2.011,
|
||||
"proposers": 5
|
||||
},
|
||||
"load_factor": 1,
|
||||
"peers": 51,
|
||||
"pubkey_node": "n9KNUUntNaDqvMVMKZLPHhGaWZDnx7soeUiHjeQE8ejR45DmHyfx",
|
||||
"server_state": "full",
|
||||
"validated_ledger": {
|
||||
"age": 2,
|
||||
"base_fee_xrp": 0.00001,
|
||||
"hash": "2B79CECB06A500A2FB92F4FB610D33A20CF8D7FB39F2C2C7C3A6BD0D75A1884A",
|
||||
"reserve_base_xrp": 20,
|
||||
"reserve_inc_xrp": 5,
|
||||
"seq": 4805506
|
||||
},
|
||||
"validation_quorum": 3
|
||||
}
|
||||
},
|
||||
"api_documentation_url": "https://github.com/ripple/ripple-rest"
|
||||
}
|
||||
```
|
||||
@@ -1,36 +1,3 @@
|
||||
* {
|
||||
box-sizing:border-box;
|
||||
}
|
||||
body {
|
||||
background:#fafafa;
|
||||
background-image:url('img/bg-gray.png') repeat scroll center top transparent;
|
||||
color:#5b5b5b;
|
||||
font-family:'open sans';
|
||||
margin:0;
|
||||
padding:0;
|
||||
}
|
||||
h1 {
|
||||
font-size:35px;
|
||||
font-weight:300;
|
||||
text-align:center;
|
||||
border-bottom:1px solid #aaa;
|
||||
padding:0 0 20px 0;
|
||||
margin:30px 0;
|
||||
line-height:40px;
|
||||
}
|
||||
ul {
|
||||
list-style-type:none;
|
||||
padding:0;
|
||||
}
|
||||
h2 {
|
||||
font-family:'open sans';
|
||||
font-size:36px;
|
||||
font-weight:300;
|
||||
color:#173847;
|
||||
}
|
||||
#wrapper {
|
||||
padding:0 20px;
|
||||
}
|
||||
#command_wrapper {
|
||||
display:table;
|
||||
width:100%;
|
||||
@@ -49,25 +16,31 @@ h2 {
|
||||
margin:0;
|
||||
height:100%;
|
||||
}
|
||||
|
||||
aside.sidebar {
|
||||
padding-top: 15px;
|
||||
}
|
||||
|
||||
#command_list li {
|
||||
padding:4px 12px;
|
||||
display:block;
|
||||
width:200px;
|
||||
cursor:pointer;
|
||||
border-radius:28px;
|
||||
box-sizing:border-box;
|
||||
user-select:none;
|
||||
-webkit-user-select:none;
|
||||
-moz-user-select:none;
|
||||
color:#0088CC;
|
||||
width: 200px;
|
||||
}
|
||||
#command_list li:hover {
|
||||
color:#444;
|
||||
|
||||
#command_list li.selected a {
|
||||
cursor: default;
|
||||
text-decoration: none;
|
||||
color: #444;
|
||||
background: #f0f0f0;
|
||||
}
|
||||
#command_list li.selected {
|
||||
color:#444;
|
||||
background:#f0f0f0;
|
||||
|
||||
#command_list li.separator {
|
||||
color: #474648;
|
||||
font-family: "Open Sans",sans-serif;
|
||||
font-size: 13px;
|
||||
text-transform: uppercase;
|
||||
font-weight: bold;
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
#command_table {
|
||||
height:100%;
|
||||
}
|
||||
@@ -80,6 +53,7 @@ h2 {
|
||||
border-spacing:24px 0;
|
||||
width:96%;
|
||||
height: 100%;
|
||||
margin-top: 30px;
|
||||
}
|
||||
#io_wrapper > div {
|
||||
width:100%;
|
||||
@@ -149,40 +123,8 @@ h3 {
|
||||
}
|
||||
|
||||
#request_options > div {
|
||||
/* float:right;
|
||||
margin:0;
|
||||
width:200px;
|
||||
color:#fff;
|
||||
/*
|
||||
background-image:linear-gradient(283deg, rgba(255,255,255,0.1) 50%, transparent 55%), linear-gradient(top, rgba(255,255,255,0.15), transparent);
|
||||
background-image:-webkit-linear-gradient(283deg, rgba(255,255,255,0.1) 50%, transparent 55%), -webkit-linear-gradient(top, rgba(255,255,255,0.15), transparent);
|
||||
background-image:-moz-linear-gradient(283deg, rgba(255,255,255,0.1) 50%, transparent 55%), -moz-linear-gradient(top, rgba(255,255,255,0.15), transparent);
|
||||
background-image:linear-gradient(283deg, rgba(255,255,255,0.1) 50%, transparent 55%), linear-gradient(top, rgba(255,255,255,0.15), transparent);
|
||||
background-image:-webkit-linear-gradient(283deg, rgba(255,255,255,0.1) 50%, transparent 55%), -webkit-linear-gradient(top, rgba(255,255,255,0.15), transparent);
|
||||
background-image:-moz-linear-gradient(283deg, rgba(255,255,255,0.1) 50%, transparent 55%), -moz-linear-gradient(top, rgba(255,255,255,0.15), transparent);
|
||||
|
||||
|
||||
border-radius:4px;
|
||||
border-bottom:1px solid #fff;
|
||||
background-color: #346AA9;
|
||||
font-weight:300;
|
||||
font-size:16px;
|
||||
/* line-height:50px;
|
||||
text-align:center;
|
||||
cursor:default;
|
||||
|
||||
user-select:none;
|
||||
-webkit-user-select:none;
|
||||
-moz-user-select:none;
|
||||
*/
|
||||
margin-top: 5px;
|
||||
}
|
||||
/*#request_button {
|
||||
background-color: #346AA9;
|
||||
}
|
||||
#request_button.depressed {
|
||||
background:#295F7A;
|
||||
}*/
|
||||
#sign_button {
|
||||
display:none;
|
||||
background:#42602D;
|
||||
@@ -208,9 +150,8 @@ h3 {
|
||||
}
|
||||
#online_state {
|
||||
position:absolute;
|
||||
top:100px;
|
||||
/* right:20px; */
|
||||
line-height:50px;
|
||||
top:10px;
|
||||
line-height:30px;
|
||||
font-size:14px;
|
||||
font-style:italic;
|
||||
}
|
||||
@@ -281,19 +222,6 @@ ul.toolbar li {
|
||||
#status > div {
|
||||
border-bottom:1px dotted #aaa;
|
||||
}
|
||||
/*#description {
|
||||
margin-top:10px;
|
||||
padding:15px;
|
||||
border-radiuS:4px;
|
||||
font-size:16px;
|
||||
color:#3a87ad;
|
||||
background:#d9edf7;
|
||||
border:1px dotted #3a87ad;
|
||||
}*/
|
||||
|
||||
/*#selected_command {
|
||||
margin-top:-32px;
|
||||
}*/
|
||||
|
||||
#selected_command a {
|
||||
text-decoration:none;
|
||||
@@ -454,3 +382,4 @@ span.cm-atom {
|
||||
#rest_url div input {
|
||||
display: block;
|
||||
}
|
||||
|
||||
438
assets/css/devportal.css
Normal file
@@ -0,0 +1,438 @@
|
||||
.navbar-header {
|
||||
float: left;
|
||||
}
|
||||
|
||||
/* Big draft warning at top of page so it's hard to mix up with the live site */
|
||||
.draft-warning {
|
||||
background-color: red;
|
||||
color: white;
|
||||
padding: 10px 20px;
|
||||
margin: 10px;
|
||||
float: right;
|
||||
}
|
||||
|
||||
/* Images should occupy the full main column width if possible */
|
||||
.page-template-template-dev-portal-php .content img {
|
||||
width: 100%;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
/* Underline links in Dev Portal content */
|
||||
.page-template-template-dev-portal-php .main a {
|
||||
text-decoration: underline !important;
|
||||
}
|
||||
|
||||
/* "Button-style" links should look like buttons, not links */
|
||||
.page-template-template-dev-portal-php a.button {
|
||||
cursor: pointer;
|
||||
text-decoration: none !important;
|
||||
}
|
||||
|
||||
/* Code Tabs stuff */
|
||||
.page-template-template-dev-portal-php .multicode {
|
||||
color: #000;
|
||||
margin: 12px 0px 0px 0px;
|
||||
padding: 0 0 0 0;
|
||||
z-index: 1;
|
||||
padding-left: 10px;
|
||||
position: relative;
|
||||
}
|
||||
.page-template-template-dev-portal-php .multicode ul {
|
||||
margin: 0 !important;
|
||||
padding: 0;
|
||||
}
|
||||
.page-template-template-dev-portal-php .multicode pre {
|
||||
padding-top: 0;
|
||||
clear: both;
|
||||
}
|
||||
.page-template-template-dev-portal-php .multicode li {
|
||||
display: block;
|
||||
float: left;
|
||||
overflow: hidden;
|
||||
list-style-type: none;
|
||||
margin-right: 5px;
|
||||
border-top: 1px solid #DBDDE2;
|
||||
}
|
||||
.page-template-template-dev-portal-php .multicode ul > li:before {
|
||||
background: none;
|
||||
border: none;
|
||||
}
|
||||
.page-template-template-dev-portal-php .multicode a,
|
||||
.page-template-template-dev-portal-php a.current {
|
||||
color: black;
|
||||
background: #DFE2E7;
|
||||
border: 1px solid #DBDDE2;
|
||||
padding: 1em 1em 0 1em;
|
||||
margin: 0px;
|
||||
text-decoration: none;
|
||||
}
|
||||
.page-template-template-dev-portal-php .multicode a.current {
|
||||
background: #fff;
|
||||
border-bottom: 1px solid #fff;
|
||||
color: black;
|
||||
}
|
||||
.page-template-template-dev-portal-php .multicode a:hover {
|
||||
color: black;
|
||||
background: white;
|
||||
}
|
||||
/* End of code tabs stuff */
|
||||
|
||||
.page-template-template-dev-portal-php .button {
|
||||
border-radius: 5px;
|
||||
background-color: #27a2db;
|
||||
padding: 5px 20px;
|
||||
text-align: center;
|
||||
cursor: default;
|
||||
margin: 10px 0;
|
||||
-ms-user-select: none;
|
||||
user-select: none;
|
||||
-webkit-user-select: none;
|
||||
-moz-user-select: none;
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
color: #ffffff;
|
||||
-o-transition: .5s;
|
||||
-webkit-transition: .5s;
|
||||
transition: .5s;
|
||||
}
|
||||
.page-template-template-dev-portal-php .button:hover {
|
||||
background-color: #43bded;
|
||||
-o-transition: .5s;
|
||||
-webkit-transition: .5s;
|
||||
transition: .5s;
|
||||
}
|
||||
.page-template-template-dev-portal-php pre {
|
||||
overflow: visible;
|
||||
word-wrap: normal;
|
||||
}
|
||||
.page-template-template-dev-portal-php pre code {
|
||||
white-space: pre;
|
||||
}
|
||||
.page-template-template-dev-portal-php .code_sample pre {
|
||||
background: none;
|
||||
border: none;
|
||||
border-radius: 0;
|
||||
}
|
||||
.page-template-template-dev-portal-php .code_sample pre code {
|
||||
overflow: auto;
|
||||
max-height: 14em;
|
||||
background-color: #f5f5f5;
|
||||
border: 1px solid #cccccc;
|
||||
border-radius: 4px;
|
||||
}
|
||||
.page-template-template-dev-portal-php .code_sample pre code.expanded {
|
||||
overflow: visible;
|
||||
max-height: none;
|
||||
position: absolute;
|
||||
min-width: 661px;
|
||||
}
|
||||
.page-template-template-dev-portal-php .code_sample .code_toggler {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
}
|
||||
.page-template-template-dev-portal-php .navbar-default {
|
||||
border-bottom: none;
|
||||
}
|
||||
.page-template-template-dev-portal-php .wrap.container {
|
||||
margin-top: 110px;
|
||||
}
|
||||
.page-template-template-dev-portal-php .main {
|
||||
z-index: 5;
|
||||
border-left: 1px solid #cccccc;
|
||||
padding-left: 40px;
|
||||
}
|
||||
.page-template-template-dev-portal-php .content {
|
||||
padding-bottom: 50px;
|
||||
}
|
||||
.page-template-template-dev-portal-php .level-1 {
|
||||
margin: 10px 0 3px 0;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
.page-template-template-dev-portal-php .level-1 a {
|
||||
color: #000000;
|
||||
font-family: 'open_sansbold', sans-serif;
|
||||
letter-spacing: .04em;
|
||||
}
|
||||
.page-template-template-dev-portal-php .level-2 {
|
||||
margin-left: 2em;
|
||||
}
|
||||
.page-template-template-dev-portal-php .level-3 {
|
||||
margin-left: 4em;
|
||||
}
|
||||
.page-template-template-dev-portal-php .level-3 a {
|
||||
color: #999999;
|
||||
}
|
||||
.page-template-template-dev-portal-php .level-3 a:hover {
|
||||
color: #666;
|
||||
}
|
||||
.page-template-template-dev-portal-php .dev_nav_sidebar {
|
||||
padding-left: 5px;
|
||||
list-style-type: none;
|
||||
max-width: 370px;
|
||||
}
|
||||
.page-template-template-dev-portal-php .dev_nav_wrapper {
|
||||
position: fixed;
|
||||
width: 100%;
|
||||
overflow-y: scroll;
|
||||
top: 130px;
|
||||
}
|
||||
.page-template-template-dev-portal-php td {
|
||||
border: 1px solid #dbdde2;
|
||||
padding: 0.2em;
|
||||
}
|
||||
.page-template-template-dev-portal-php th {
|
||||
padding: 0.2em;
|
||||
}
|
||||
.page-template-template-dev-portal-php .content a[title="Source"] {
|
||||
float: right;
|
||||
padding-left: 20px;
|
||||
}
|
||||
.page-template-template-dev-portal-php .content table {
|
||||
clear: right;
|
||||
}
|
||||
.page-template-template-dev-portal-php h1:before,
|
||||
.page-template-template-dev-portal-php h2:before,
|
||||
.page-template-template-dev-portal-php h3:before {
|
||||
display: block;
|
||||
content: " ";
|
||||
margin-top: -130px;
|
||||
height: 130px;
|
||||
visibility: hidden;
|
||||
}
|
||||
@media (max-width: 1200px) {
|
||||
.page-template-template-dev-portal-php .dev_nav_wrapper {
|
||||
max-width: 290px;
|
||||
}
|
||||
}
|
||||
@media (max-width: 992px) {
|
||||
.page-template-template-dev-portal-php .dev_nav_wrapper {
|
||||
max-width: 230px;
|
||||
}
|
||||
}
|
||||
@media (max-width: 768px) {
|
||||
.page-template-template-dev-portal-php .dev_nav_wrapper,
|
||||
.page-template-template-dev-portal-php .sidebar {
|
||||
display: block;
|
||||
clear: both;
|
||||
overflow-y: inherit;
|
||||
position: static;
|
||||
max-width: 100%;
|
||||
}
|
||||
.page-template-template-dev-portal-php .main {
|
||||
position: static;
|
||||
clear: both;
|
||||
border-left: none;
|
||||
padding-left: 0px;
|
||||
overflow-wrap: break-word;
|
||||
word-wrap: break-word;
|
||||
overflow: hidden;
|
||||
}
|
||||
}
|
||||
@media (min-width: 768px) {
|
||||
.page-template-template-dev-portal-php .main {
|
||||
float: right;
|
||||
}
|
||||
}
|
||||
@media (max-width: 480px) {
|
||||
.page-template-template-dev-portal-php html {
|
||||
overflow-x: hidden !important;
|
||||
}
|
||||
}
|
||||
@media print {
|
||||
.page-template-template-dev-portal-php {
|
||||
/* undo code tabs */
|
||||
/* wrap code, not scroll */
|
||||
/* Source URLs are too big to float */
|
||||
/* Show URLs after links - even for anchors */
|
||||
/* Drop header, footer, google translate */
|
||||
/* table of contents can't scroll */
|
||||
/* better margins on main content */
|
||||
/* crazy print-section-numbering idea */
|
||||
}
|
||||
.page-template-template-dev-portal-php .multicode > div {
|
||||
display: block !important;
|
||||
}
|
||||
.page-template-template-dev-portal-php .multicode > ul {
|
||||
display: none !important;
|
||||
}
|
||||
.page-template-template-dev-portal-php .multicode > em,
|
||||
.page-template-template-dev-portal-php .multicode > p > em {
|
||||
display: block !important;
|
||||
page-break-after: avoid;
|
||||
}
|
||||
.page-template-template-dev-portal-php .multicode > p {
|
||||
display: block !important;
|
||||
}
|
||||
.page-template-template-dev-portal-php pre {
|
||||
white-space: pre-wrap;
|
||||
max-height: none !important;
|
||||
overflow: visible;
|
||||
page-break-inside: auto;
|
||||
word-wrap: break-word;
|
||||
}
|
||||
.page-template-template-dev-portal-php pre code {
|
||||
white-space: pre-wrap !important;
|
||||
}
|
||||
.page-template-template-dev-portal-php .content a[title="Source"] {
|
||||
float: none;
|
||||
}
|
||||
.page-template-template-dev-portal-php .main a:after {
|
||||
content: " (" attr(href) ")";
|
||||
}
|
||||
.page-template-template-dev-portal-php header,
|
||||
.page-template-template-dev-portal-php footer {
|
||||
display: none;
|
||||
}
|
||||
.page-template-template-dev-portal-php #goog-gt-tt {
|
||||
display: none;
|
||||
}
|
||||
.page-template-template-dev-portal-php .wrap.container {
|
||||
margin-top: 0 !important;
|
||||
}
|
||||
.page-template-template-dev-portal-php .dev_nav_wrapper {
|
||||
position: static !important;
|
||||
}
|
||||
.page-template-template-dev-portal-php .sidebar:before {
|
||||
display: none !important;
|
||||
}
|
||||
.page-template-template-dev-portal-php .sidebar {
|
||||
padding-top: 0 !important;
|
||||
display: block !important;
|
||||
float: none !important;
|
||||
}
|
||||
.page-template-template-dev-portal-php h1 {
|
||||
page-break-before: always;
|
||||
}
|
||||
.page-template-template-dev-portal-php .main {
|
||||
float: none !important;
|
||||
width: 85% !important;
|
||||
border-left: 0 !important;
|
||||
padding: 0 !important;
|
||||
margin: 0 !important;
|
||||
display: block !important;
|
||||
overflow: visible !important;
|
||||
}
|
||||
.page-template-template-dev-portal-php .main {
|
||||
counter-reset: level1;
|
||||
counter-reset: level2;
|
||||
counter-reset: level3;
|
||||
}
|
||||
.page-template-template-dev-portal-php .main h1 {
|
||||
counter-increment: level1;
|
||||
counter-reset: level2;
|
||||
}
|
||||
.page-template-template-dev-portal-php .main h1:before {
|
||||
content: counter(level1) ". " !important;
|
||||
display: inline !important;
|
||||
background: none !important;
|
||||
position: static !important;
|
||||
box-shadow: none !important;
|
||||
visibility: visible !important;
|
||||
}
|
||||
.page-template-template-dev-portal-php .main h2 {
|
||||
counter-reset: level3;
|
||||
}
|
||||
.page-template-template-dev-portal-php .main h2:before {
|
||||
counter-increment: level2;
|
||||
content: counter(level1) "." counter(level2) ". " !important;
|
||||
display: inline !important;
|
||||
background: none !important;
|
||||
position: static !important;
|
||||
box-shadow: none !important;
|
||||
visibility: visible !important;
|
||||
}
|
||||
.page-template-template-dev-portal-php .main h3:before {
|
||||
counter-increment: level3;
|
||||
content: counter(level1) "." counter(level2) "." counter(level3) ". " !important;
|
||||
display: inline !important;
|
||||
background: none !important;
|
||||
position: static !important;
|
||||
box-shadow: none !important;
|
||||
visibility: visible !important;
|
||||
}
|
||||
.page-template-template-dev-portal-php .menubar,
|
||||
.page-template-template-dev-portal-php .dev_nav_wrapper {
|
||||
counter-reset: toclevel1;
|
||||
}
|
||||
.page-template-template-dev-portal-php .level-1 {
|
||||
counter-reset: toclevel2;
|
||||
}
|
||||
.page-template-template-dev-portal-php .level-1:before {
|
||||
counter-increment: toclevel1;
|
||||
content: counters(toclevel1, ".") ". " !important;
|
||||
display: inline !important;
|
||||
background: none !important;
|
||||
position: static !important;
|
||||
box-shadow: none !important;
|
||||
}
|
||||
.page-template-template-dev-portal-php .level-2 {
|
||||
counter-reset: toclevel3;
|
||||
}
|
||||
.page-template-template-dev-portal-php .level-2:before {
|
||||
counter-increment: toclevel2;
|
||||
content: counters(toclevel1, ".") "." counters(toclevel2, ".") ". " !important;
|
||||
display: inline !important;
|
||||
background: none !important;
|
||||
position: static !important;
|
||||
box-shadow: none !important;
|
||||
}
|
||||
.page-template-template-dev-portal-php .level-3:before {
|
||||
counter-increment: toclevel3;
|
||||
content: counters(toclevel1, ".") "." counters(toclevel2, ".") "." counters(toclevel3, ".") ". " !important;
|
||||
display: inline !important;
|
||||
background: none !important;
|
||||
position: static !important;
|
||||
box-shadow: none !important;
|
||||
}
|
||||
}
|
||||
|
||||
/*------------- Code Tabs -----------------------------------------*/
|
||||
.multicode {
|
||||
color: #000;
|
||||
border-bottom: 1px solid #DBDDE2;
|
||||
margin: 12px 0px 0px 0px;
|
||||
padding: 0 0 0 0;
|
||||
z-index: 1;
|
||||
padding-left: 10px;
|
||||
}
|
||||
|
||||
.multicode ul {
|
||||
padding-bottom: 0;
|
||||
}
|
||||
|
||||
.multicode pre {
|
||||
padding-top: 0;
|
||||
}
|
||||
|
||||
.multicode li {
|
||||
display: inline;
|
||||
overflow: hidden;
|
||||
list-style-type: none;
|
||||
}
|
||||
|
||||
.multicode ul > li:before {
|
||||
background: none;
|
||||
border: none;
|
||||
}
|
||||
|
||||
.multicode a, a.current {
|
||||
color: black;
|
||||
background: #DFE2E7;
|
||||
border: 1px solid #DBDDE2;
|
||||
padding: 1em 1em 0 1em;
|
||||
margin: 0px;
|
||||
text-decoration: none; }
|
||||
|
||||
.multicode a.current {
|
||||
background: #fff;
|
||||
border-bottom: 1px solid #fff;
|
||||
color : black;
|
||||
}
|
||||
|
||||
.multicode a:hover {
|
||||
color: black;
|
||||
background: white;
|
||||
}
|
||||
|
||||
.multicode a.current:hover {}
|
||||
112
assets/css/landing.css
Normal file
@@ -0,0 +1,112 @@
|
||||
.page-template-template-dev-portal-php .main {
|
||||
border-left: 0;
|
||||
}
|
||||
|
||||
/************
|
||||
jumbotron
|
||||
*********** */
|
||||
|
||||
.jumbotron {
|
||||
margin-top: 50px;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.jumbotron p {
|
||||
font-size: 14px;
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
.main_callout {
|
||||
padding-top:10px;
|
||||
}
|
||||
|
||||
.join {
|
||||
font-weight: 500 !important;
|
||||
}
|
||||
|
||||
img.large_logo {
|
||||
padding: 10px 20px 10px 10px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
|
||||
.jumbotron p.api_btn {
|
||||
/* text-align: center;
|
||||
padding: 20px;*/
|
||||
}
|
||||
|
||||
.jumbotron h4 {
|
||||
font-weight: 800;
|
||||
}
|
||||
|
||||
@media (min-width: 992px) {
|
||||
|
||||
.jumbotron .col-md-6 {
|
||||
padding-left: 60px;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/************
|
||||
Main content
|
||||
*********** */
|
||||
|
||||
.main_title {
|
||||
font-size: 30px;
|
||||
font-weight: 300;
|
||||
margin-top:10px;
|
||||
}
|
||||
|
||||
.description h2{
|
||||
font-size: 24px;
|
||||
font-weight: 600;
|
||||
margin: 20px 0 15px 0;
|
||||
}
|
||||
|
||||
.build-index .top {
|
||||
background: #f4f6f7 none repeat scroll 0 0;
|
||||
}
|
||||
|
||||
.build-index ul {
|
||||
border-top-left-radius: 5px;
|
||||
border-top-right-radius: 5px;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.build-index ul li {
|
||||
border: 1px solid #ccc;
|
||||
border-top-width: 0;
|
||||
font-size: 14px;
|
||||
list-style: outside none none;
|
||||
padding: 5px;
|
||||
}
|
||||
|
||||
.build-index ul li.top {
|
||||
border-top-width: 1px;
|
||||
border-top-left-radius: 5px;
|
||||
border-top-right-radius: 5px;
|
||||
}
|
||||
|
||||
.build-index .dev_heading {
|
||||
font-family: "Open Sans",sans-serif;
|
||||
letter-spacing: 0.04em;
|
||||
font-weight: 600;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.last {
|
||||
margin-bottom: 40px;
|
||||
}
|
||||
|
||||
.description.highlight {
|
||||
background: #f5f5f5;
|
||||
padding-bottom: 15px;
|
||||
margin: 22px 0;
|
||||
}
|
||||
|
||||
@media (max-width: 992px) {
|
||||
.description.highlight {
|
||||
padding-top: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
23
assets/css/pdf.css
Executable file
@@ -0,0 +1,23 @@
|
||||
a[href^="#"]:after {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
.main code {
|
||||
color: black;
|
||||
}
|
||||
|
||||
.main .hljs {
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
.main pre {
|
||||
background: transparent;
|
||||
box-decoration-break: slice;
|
||||
}
|
||||
|
||||
/* Disable header numbering */
|
||||
.page-template-template-dev-portal.page-template-template-dev-portal-php h1:before,
|
||||
.page-template-template-dev-portal.page-template-template-dev-portal-php h2:before,
|
||||
.page-template-template-dev-portal.page-template-template-dev-portal-php h3:before {
|
||||
content: none !important;
|
||||
}
|
||||
8687
assets/css/ripple.css
Executable file
|
Before Width: | Height: | Size: 262 B After Width: | Height: | Size: 262 B |
BIN
assets/img/dev-logo.png
Normal file
|
After Width: | Height: | Size: 3.6 KiB |
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 15 KiB |
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 15 KiB |
|
Before Width: | Height: | Size: 36 KiB After Width: | Height: | Size: 36 KiB |
|
Before Width: | Height: | Size: 9.4 KiB After Width: | Height: | Size: 9.4 KiB |
BIN
assets/img/ripple-logo-color.png
Normal file
|
After Width: | Height: | Size: 2.9 KiB |
|
Before Width: | Height: | Size: 29 KiB After Width: | Height: | Size: 29 KiB |
BIN
assets/img/ripple_footer_v2.jpg
Normal file
|
After Width: | Height: | Size: 243 KiB |
|
Before Width: | Height: | Size: 20 KiB |
|
Before Width: | Height: | Size: 1.8 KiB |
369
assets/js/apitool-methods-data_v2.js
Normal file
@@ -0,0 +1,369 @@
|
||||
//---------- List of requests ------------------------//
|
||||
// Must be loaded after apitool-rest.js //
|
||||
//var DOC_BASE = "reference-data-api.html";
|
||||
//var URL_BASE = "https://data-staging.ripple.com";
|
||||
|
||||
var DEFAULT_ADDRESS_1 = "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn";
|
||||
var KRW_TRADER_ADDRESS = "rsyDrDi9Emy6vPU78qdxovmNpmj5Qh4NKw";
|
||||
var JPY_TRADER_ADDRESS = "rK5j9n8baXfL4gzUoZsfxBvvsv97P5swaV";
|
||||
var DEFAULT_HASH = "9D591B18EDDD34F0B6CF4223A2940AEA2C3CC778925BABF289E0011CD8FA056E";
|
||||
var DEFAULT_LEDGER = "3170DA37CE2B7F045F889594CBC323D88686D2E90E8FFD2BBCD9BAD12E416DB5";
|
||||
|
||||
// general methods -----------------------------------//
|
||||
|
||||
Request("GENERAL METHODS");
|
||||
|
||||
Request('Get Ledger', {
|
||||
method: GET,
|
||||
path: "/v2/ledgers/{:ledger_identifier}?{:query_params}",
|
||||
description: "Retrieve a ledger by its sequence number or identifying hash.",
|
||||
link: "#get-ledger",
|
||||
params: {
|
||||
"{:ledger_identifier}": DEFAULT_LEDGER,
|
||||
"{:query_params}": "transactions=true&binary=false&expand=true"
|
||||
}
|
||||
});
|
||||
|
||||
Request('Get Transaction', {
|
||||
method: GET,
|
||||
path: "/v2/transactions/{:hash}?{:query_params}",
|
||||
description: "Retrieve a transactions by its identifying hash.",
|
||||
link: "#get-transaction",
|
||||
params: {
|
||||
"{:hash}": DEFAULT_HASH,
|
||||
"{:query_params}": "binary=false"
|
||||
}
|
||||
});
|
||||
|
||||
Request('Get Transactions', {
|
||||
method: GET,
|
||||
path: "/v2/transactions/?{:query_params}",
|
||||
description: "Search through all transactions",
|
||||
link: "#get-transactions",
|
||||
params: {
|
||||
"{:query_params}": "descending=true&limit=3&result=tesSUCCESS&type=OfferCreate"
|
||||
}
|
||||
});
|
||||
|
||||
Request('Get Payments', {
|
||||
method: GET,
|
||||
path: "/v2/payments/{:currency}?{:query_params}",
|
||||
description: "Retrieve Payments over time, where Payments are defined as Payment-type transactions where the sender of the transaction is not also the destination. ",
|
||||
link: "#get-payments",
|
||||
params: {
|
||||
"{:currency}": "BTC+rMwjYedjc7qqtKYVLiAccJSmCwih4LnE2q",
|
||||
"{:query_params}": "limit=2"
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
Request('Get Exchanges', {
|
||||
method: GET,
|
||||
path: "/v2/exchanges/{:base}/{:counter}?{:query_params}",
|
||||
description: "Retrieve exchanges for a currency pair over time.",
|
||||
link: "#get-exchanges",
|
||||
params: {
|
||||
"{:base}": "USD+rMwjYedjc7qqtKYVLiAccJSmCwih4LnE2q",
|
||||
"{:counter}": "XRP",
|
||||
"{:query_params}": "descending=true&limit=3&result=tesSUCCESS&type=OfferCreate"
|
||||
}
|
||||
});
|
||||
|
||||
Request('Get Exchange Rates', {
|
||||
method: GET,
|
||||
path: "/v2/exchange_rates/{:base}/{:counter}?{:query_params}",
|
||||
description: "Retrieve an exchange rate for a given currency pair at a specific time.",
|
||||
link: "#get-exchange-rates",
|
||||
params: {
|
||||
"{:base}": "USD+rMwjYedjc7qqtKYVLiAccJSmCwih4LnE2q",
|
||||
"{:counter}": "XRP",
|
||||
"{:query_params}": "date=2015-11-13T00:00:00Z"
|
||||
}
|
||||
});
|
||||
|
||||
Request('Normalize', {
|
||||
method: GET,
|
||||
path: "/v2/normalize?{:query_params}",
|
||||
description: "Convert an amount from one currency and issuer to another, using the network exchange rates.",
|
||||
link: "#normalize",
|
||||
params: {
|
||||
"{:query_params}": "amount=100¤cy=XRP&exchange_currency=USD&exchange_issuer=rMwjYedjc7qqtKYVLiAccJSmCwih4LnE2q"
|
||||
}
|
||||
});
|
||||
|
||||
Request('Get Daily Reports', {
|
||||
method: GET,
|
||||
path: "/v2/reports/{:date}?{:query_params}",
|
||||
description: "Retrieve an aggregated summary of payments per account for one day.",
|
||||
link: "#get-daily-reports",
|
||||
params: {
|
||||
"{:date}": "2015-08-19T00:00:00Z",
|
||||
"{:query_params}": "accounts=true&payments=true"
|
||||
}
|
||||
});
|
||||
|
||||
Request('Get Stats', {
|
||||
method: GET,
|
||||
path: "/v2/stats/?{:query_params}",
|
||||
description: "Retrieve an aggregated summary of payments per account for one day.",
|
||||
link: "#get-daily-summary",
|
||||
params: {
|
||||
"{:query_params}": "start=2015-08-30&end=2015-08-31&interval=day&family=metric&metrics=accounts_created,exchanges_count,ledger_count,payments_count"
|
||||
}
|
||||
});
|
||||
|
||||
Request('Get Capitalization', {
|
||||
method: GET,
|
||||
path: "/v2/capitalization/{:currency}?{:query_params}",
|
||||
description: "Get capitalization data for a specific currency and issuer.",
|
||||
link: "#get-capitalization",
|
||||
params: {
|
||||
"{:currency}": "USD+rMwjYedjc7qqtKYVLiAccJSmCwih4LnE2q",
|
||||
"{:query_params}": "start=2015-01-01T00:00:00Z&end=2015-10-31&interval=month"
|
||||
}
|
||||
});
|
||||
|
||||
Request('Get Active Accounts', {
|
||||
method: GET,
|
||||
path: "/v2/active_accounts/{:base}/{:counter}?{:query_params}",
|
||||
description: "Get information on which accounts are actively trading in a specific currency pair.",
|
||||
link: "#get-active-accounts",
|
||||
params: {
|
||||
"{:base}": "USD+rMwjYedjc7qqtKYVLiAccJSmCwih4LnE2q",
|
||||
"{:counter}": "XRP",
|
||||
"{:query_params}": "period=7day"
|
||||
}
|
||||
});
|
||||
|
||||
Request('Get Exchange Volume', {
|
||||
method: GET,
|
||||
path: "/v2/network/exchange_volume?{:query_params}",
|
||||
description: "Get aggregated exchange volume for a given time period.",
|
||||
link: "#get-exchange-volume",
|
||||
params: {
|
||||
"{:query_params}": "start=2015-10-01T00:00:00&end=2015-11-15T00:00:00&interval=week&exchange_currency=USD&exchange_issuer=rMwjYedjc7qqtKYVLiAccJSmCwih4LnE2q"
|
||||
}
|
||||
});
|
||||
|
||||
Request('Get Payment Volume', {
|
||||
method: GET,
|
||||
path: "/v2/network/payment_volume?{:query_params}",
|
||||
description: "Get aggregated payment volume for a given time period.",
|
||||
link: "#get-exchange-volume",
|
||||
params: {
|
||||
"{:query_params}": "start=2015-10-01T00:00:00&end=2015-11-15T00:00:00&interval=week&exchange_currency=USD&exchange_issuer=rMwjYedjc7qqtKYVLiAccJSmCwih4LnE2q"
|
||||
}
|
||||
});
|
||||
|
||||
Request('Get Issued Value', {
|
||||
method: GET,
|
||||
path: "/v2/network/issued_value?{:query_params}",
|
||||
description: "Get aggregated payment volume for a given time period.",
|
||||
link: "#get-exchange-volume",
|
||||
params: {
|
||||
"{:query_params}": "start=2015-10-01T00:00:00&end=2015-11-15T00:00:00&exchange_currency=USD&exchange_issuer=rMwjYedjc7qqtKYVLiAccJSmCwih4LnE2q"
|
||||
}
|
||||
});
|
||||
|
||||
Request('Get Top Currencies', {
|
||||
method: GET,
|
||||
path: "/v2/network/top_currencies/{:date}",
|
||||
description: "Get most used currencies for a given date.",
|
||||
link: "#get-top-currencies",
|
||||
params: {
|
||||
"{:date}": "2016-04-14"
|
||||
}
|
||||
});
|
||||
|
||||
Request('Get Top Markets', {
|
||||
method: GET,
|
||||
path: "/v2/network/top_markets/{:date}",
|
||||
description: "Get most active markets for a given date.",
|
||||
link: "#get-top-currencies",
|
||||
params: {
|
||||
"{:date}": "2016-04-15"
|
||||
}
|
||||
});
|
||||
|
||||
Request('Get All Gateways', {
|
||||
method: GET,
|
||||
path: "/v2/gateways",
|
||||
description: "Get information about known gateways.",
|
||||
link: "#get-all-gateways",
|
||||
params: {}
|
||||
});
|
||||
|
||||
Request('Get Gateway', {
|
||||
method: GET,
|
||||
path: "/v2/gateways/{:gateway}",
|
||||
description: "Get information about a specific known gateway.",
|
||||
link: "#get-gateway",
|
||||
params: {
|
||||
"{:gateway}": "Gatehub"
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
// account methods -----------------------------------//
|
||||
|
||||
Request("ACCOUNT METHODS");
|
||||
|
||||
Request('Get Account', {
|
||||
method: GET,
|
||||
path: "/v2/accounts/{:address}",
|
||||
description: "Get creation info for a specific account.",
|
||||
link: "#get-account",
|
||||
params: {
|
||||
"{:address}": DEFAULT_ADDRESS_1
|
||||
}
|
||||
});
|
||||
|
||||
Request('Get Accounts', {
|
||||
method: GET,
|
||||
path: "/v2/accounts/?{:query_params}",
|
||||
description: "Get info for all account creations.",
|
||||
link: "#get-accounts",
|
||||
params: {
|
||||
"{:query_params}": "descending=true&parent=rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn"
|
||||
}
|
||||
});
|
||||
|
||||
Request('Get Account Balances', {
|
||||
method: GET,
|
||||
path: "/v2/accounts/{:address}/balances?{:query_params}",
|
||||
description: "Retrieve a given account's balances at a given time.",
|
||||
link: "#get-account-balances",
|
||||
params: {
|
||||
"{:address}": DEFAULT_ADDRESS_1,
|
||||
"{:query_params}": "currency=USD&date=2015-01-01T00:00:00Z&limit=3"
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
Request('Get Account Orders', {
|
||||
method: GET,
|
||||
path: "/v2/accounts/{:address}/orders?{:query_params}",
|
||||
description: "Get orders in the order books, placed by a specific account.",
|
||||
link: "#get-account-orders",
|
||||
params: {
|
||||
"{:address}": JPY_TRADER_ADDRESS,
|
||||
"{:query_params}": "limit=2&date=2015-11-11T00:00:00Z"
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
Request('Get Account Transaction History', {
|
||||
method: GET,
|
||||
path: "/v2/accounts/{:address}/transactions?{:query_params}",
|
||||
description: "Retrieve transactions that affected the given account.",
|
||||
link: "#get-account-transaction-history",
|
||||
params: {
|
||||
"{:address}": DEFAULT_ADDRESS_1,
|
||||
"{:query_params}": "type=Payment&result=tesSUCCESS&limit=3"
|
||||
}
|
||||
});
|
||||
|
||||
Request('Get Transaction By Account and Sequence', {
|
||||
method: GET,
|
||||
path: "/v2/accounts/{:address}/transactions/{:sequence}?{:query_params}",
|
||||
description: "Retrieve a transaction using the sending account and sequence number.",
|
||||
link: "#get-transaction-by-account-and-sequence",
|
||||
params: {
|
||||
"{:address}": DEFAULT_ADDRESS_1,
|
||||
"{:sequence}": 10,
|
||||
"{:query_params}": "binary=true"
|
||||
}
|
||||
});
|
||||
|
||||
Request('Get Account Payments', {
|
||||
method: GET,
|
||||
path: "/v2/accounts/{:address}/payments?{:query_params}",
|
||||
description: "Retrieve payments to and from a given account.",
|
||||
link: "#get-account-payments",
|
||||
params: {
|
||||
"{:address}": DEFAULT_ADDRESS_1,
|
||||
"{:query_params}": "currency=USD&limit=3"
|
||||
}
|
||||
});
|
||||
|
||||
Request('Get Account Exchanges - All', {
|
||||
method: GET,
|
||||
path: "/v2/accounts/{:address}/exchanges?{:query_params}",
|
||||
description: "Retrieve all currency changes in which a given account participated.",
|
||||
link: "#get-account-exchanges",
|
||||
params: {
|
||||
"{:address}": KRW_TRADER_ADDRESS,
|
||||
"{:query_params}": "start=2015-08-01T00:00:00Z&end=2015-08-31T00:00:00Z"
|
||||
}
|
||||
});
|
||||
|
||||
Request('Get Account Exchanges - Single Currency Pair', {
|
||||
method: GET,
|
||||
path: "/v2/accounts/{:address}/exchanges/{:base}/{:counter}?{:query_params}",
|
||||
description: "Retrieve exchanges of a specific currency pair in which a given account participated.",
|
||||
link: "#get-account-exchanges",
|
||||
params: {
|
||||
"{:address}": KRW_TRADER_ADDRESS,
|
||||
"{:base}": "KRW+rUkMKjQitpgAM5WTGk79xpjT38DEJY283d",
|
||||
"{:counter}": "XRP",
|
||||
"{:query_params}": "start=2015-08-08T00:00:00Z&end=2015-08-31T00:00:00Z&limit=2"
|
||||
}
|
||||
});
|
||||
|
||||
Request('Get Account Balance Changes', {
|
||||
method: GET,
|
||||
path: "/v2/accounts/{:address}/balance_changes?{:query_params}",
|
||||
description: "Retrieve detailed account of all changes to an account's balance.",
|
||||
link: "#get-account-balance-changes",
|
||||
params: {
|
||||
"{:address}": DEFAULT_ADDRESS_1,
|
||||
"{:query_params}": "descending=true&limit=3"
|
||||
}
|
||||
});
|
||||
|
||||
Request('Get Account Reports By Day', {
|
||||
method: GET,
|
||||
path: "/v2/accounts/{:address}/reports/{:date}?{:query_params}",
|
||||
description: "Retrieve summary of account activity for a given account on a certain day.",
|
||||
link: "#get-account-reports",
|
||||
params: {
|
||||
"{:address}": DEFAULT_ADDRESS_1,
|
||||
"{:date}": "2015-08-27T00:00:00",
|
||||
"{:query_params}": "accounts=true&payments=true&descending=true"
|
||||
}
|
||||
});
|
||||
|
||||
Request('Get Account Reports Range', {
|
||||
method: GET,
|
||||
path: "/v2/accounts/{:address}/reports?{:query_params}",
|
||||
description: "Retrieve multiple daily summaries of account activity.",
|
||||
link: "#get-account-reports",
|
||||
params: {
|
||||
"{:address}": DEFAULT_ADDRESS_1,
|
||||
"{:query_params}": "accounts=true&payments=true&descending=true"
|
||||
}
|
||||
});
|
||||
|
||||
Request('Get Account Transaction Stats', {
|
||||
method: GET,
|
||||
path: "/v2/accounts/{:address}/stats/transactions?{:query_params}",
|
||||
description: "Retrieve daily summaries of transaction activity for an account.",
|
||||
link: "#get-account-transaction-stats",
|
||||
params: {
|
||||
"{:address}": DEFAULT_ADDRESS_1,
|
||||
"{:query_params}": "limit=2&descending=true"
|
||||
}
|
||||
})
|
||||
|
||||
Request('Get Account Value Stats', {
|
||||
method: GET,
|
||||
path: "/v2/accounts/{:address}/stats/value?{:query_params}",
|
||||
description: "Retrieve daily summaries of the currency held by an account.",
|
||||
link: "#get-account-value-stats",
|
||||
params: {
|
||||
"{:address}": DEFAULT_ADDRESS_1,
|
||||
"{:query_params}": "limit=2&descending=true"
|
||||
}
|
||||
})
|
||||
|
||||
//---------- End req. List ---------------------------//
|
||||
34
assets/js/apitool-methods-jsonrpc.js
Normal file
@@ -0,0 +1,34 @@
|
||||
//---------- List of requests ------------------------//
|
||||
// Must be loaded after apitool-rest.js //
|
||||
//var DOC_BASE = "reference-rippled.html";
|
||||
//var URL_BASE = "https://s2.ripple.com:51234";
|
||||
|
||||
var DEFAULT_ADDRESS_1 = "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn";
|
||||
var KRW_TRADER_ADDRESS = "rsyDrDi9Emy6vPU78qdxovmNpmj5Qh4NKw";
|
||||
var JPY_TRADER_ADDRESS = "rK5j9n8baXfL4gzUoZsfxBvvsv97P5swaV";
|
||||
var DEFAULT_HASH = "9D591B18EDDD34F0B6CF4223A2940AEA2C3CC778925BABF289E0011CD8FA056E";
|
||||
var DEFAULT_LEDGER = "3170DA37CE2B7F045F889594CBC323D88686D2E90E8FFD2BBCD9BAD12E416DB5";
|
||||
|
||||
// general methods -----------------------------------//
|
||||
|
||||
Request("ACCOUNT INFORMATION");
|
||||
|
||||
Request('account_currencies', {
|
||||
method: POST,
|
||||
path: "/",
|
||||
description: "Retrieves a simple list of currencies that an account can send or receive, based on its trust lines.",
|
||||
link: "#account-currencies",
|
||||
params: {},
|
||||
body: {
|
||||
"method": "account_currencies",
|
||||
"params": [
|
||||
{
|
||||
"account": "r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59",
|
||||
"account_index": 0,
|
||||
"ledger_index": "validated",
|
||||
"strict": true
|
||||
}
|
||||
]
|
||||
}
|
||||
});
|
||||
|
||||
297
assets/js/apitool-rest.js
Normal file
@@ -0,0 +1,297 @@
|
||||
var commandlist = $("#command_list");
|
||||
var request_body = $("#request_body");
|
||||
var request_button = $("#request_button");
|
||||
var response_body = $("#response_body");
|
||||
var response_code = $("#rest_responsecode");
|
||||
var rest_url = $('#rest_url');
|
||||
var rest_method = $("#rest_method");
|
||||
var selected_command = $("#selected_command");
|
||||
var spinner = $(".loader");
|
||||
var reminders = $("#rest_url_wrapper .rest_reminders");
|
||||
var test_warning = $("#test_warning");
|
||||
|
||||
var GET = "GET";
|
||||
var POST = "POST";
|
||||
var PUT = "PUT";
|
||||
var DELETE = "DELETE";
|
||||
|
||||
|
||||
function slugify(str) {
|
||||
str = str.replace(/^\s+|\s+$/g, ''); // trim
|
||||
str = str.toLowerCase();
|
||||
|
||||
// remove accents, swap ñ for n, etc
|
||||
var from = "àáäâèéëêìíïîòóöôùúüûñç·/_,:;";
|
||||
var to = "aaaaeeeeiiiioooouuuunc------";
|
||||
for (var i=0, l=from.length ; i<l ; i++) {
|
||||
str = str.replace(new RegExp(from.charAt(i), 'g'), to.charAt(i));
|
||||
}
|
||||
|
||||
str = str.replace(/[^a-z0-9 -]/g, '') // remove invalid chars
|
||||
.replace(/\s+/g, '-') // collapse whitespace and replace by -
|
||||
.replace(/-+/g, '-'); // collapse dashes
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
//Build requests
|
||||
var requests = { };
|
||||
var requestlist = [];
|
||||
function Request(name, obj) {
|
||||
if (obj === undefined) {
|
||||
requestlist.push({slug: null,name: name});//separator
|
||||
return null;
|
||||
}
|
||||
|
||||
obj.name = name;
|
||||
obj.slug = slugify(name);
|
||||
requests[obj.slug] = obj;
|
||||
requestlist.push(obj);
|
||||
|
||||
return obj;
|
||||
};
|
||||
|
||||
function generate_table_of_contents() {
|
||||
$.each(requestlist, function(i, req) {
|
||||
if (req.slug === null) {
|
||||
commandlist.append("<li class='separator'>"+req.name+"</li>");
|
||||
} else {
|
||||
commandlist.append("<li><a href='#"+req.slug+"'>"+req.name+"</a></li>");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function make_commands_clickable() {
|
||||
commandlist.children("li").click(function() {
|
||||
var cmd = slugify($(this).text().trim());
|
||||
|
||||
if (!requests[cmd]) return;
|
||||
|
||||
select_request(cmd, true);
|
||||
window.location.hash = cmd;
|
||||
|
||||
$(this).siblings().removeClass('selected');
|
||||
$(this).addClass('selected');
|
||||
});
|
||||
}
|
||||
|
||||
var cm_request = CodeMirror(request_body.get(0), {
|
||||
mode: 'javascript',
|
||||
json: true,
|
||||
smartIndent: false
|
||||
});
|
||||
|
||||
var cm_response = CodeMirror(response_body.get(0), {
|
||||
mode: 'javascript',
|
||||
json: true,
|
||||
smartIndent: false,
|
||||
readOnly: true
|
||||
});
|
||||
|
||||
function update_method(el) {
|
||||
if (el === undefined) {
|
||||
method = $(this).val();
|
||||
} else {
|
||||
method = $(el).val();
|
||||
}
|
||||
|
||||
if (method == GET) {
|
||||
request_body.hide();
|
||||
} else {
|
||||
request_body.show();
|
||||
cm_request.refresh();
|
||||
}
|
||||
}
|
||||
|
||||
function change_path(command) {
|
||||
rest_url.empty();
|
||||
reminders.html(" ");
|
||||
|
||||
var re = /(\{:[^}]+\})/g; // match stuff like {:address}
|
||||
params = command.path.split(re);
|
||||
|
||||
//console.log(params);
|
||||
for (i=0; i<params.length; i++) {
|
||||
if (params[i].match(/\{:[^}]+\}/) !== null) {
|
||||
if (command.params === undefined || command.params[params[i]] === undefined) {
|
||||
var default_val = params[i];
|
||||
} else {
|
||||
var default_val = command.params[params[i]];
|
||||
}
|
||||
//rest_url.append("<span class='editable' contenteditable='true' id='resturl_"+params[i]+"'>"+default_val+"</span>");
|
||||
|
||||
var new_div = $("<div>").appendTo(rest_url);
|
||||
var new_param = $("<input type='text' id='resturl_"+params[i]+"' value='"+default_val+"' class='editable' title='"+params[i]+"' />").appendTo(new_div);
|
||||
new_param.autosizeInput({"space": 0});
|
||||
//var new_label = $("<label class='reminder' for='resturl_"+params[i]+"'>"+params[i]+"</label>").appendTo(new_div);
|
||||
|
||||
|
||||
} else {
|
||||
rest_url.append("<span class='non_editable'>"+params[i]+"</span>");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function select_request(request) {
|
||||
if (request === undefined) {
|
||||
var el = commandlist.children("li:not(.separator)").eq(0);
|
||||
request = slugify(el.text());
|
||||
|
||||
/* var keys = Object.keys(requests);
|
||||
var index = keys.indexOf(cmd);
|
||||
if (index === -1) return;*/
|
||||
} else {
|
||||
var el = commandlist.find("li a[href='#"+request+"']").parent();
|
||||
}
|
||||
$(el).siblings().removeClass('selected');
|
||||
$(el).addClass('selected');
|
||||
|
||||
command = requests[request];
|
||||
|
||||
if (command.test_only === true) {
|
||||
test_warning.show();
|
||||
} else {
|
||||
test_warning.hide();
|
||||
}
|
||||
|
||||
if (command.description) {
|
||||
$(description).html(command.description);
|
||||
|
||||
if (command.link) {
|
||||
$(description).append(" <a class='button btn btn-primary' href='" +
|
||||
DOC_BASE+command.link+"'>Read more</a>");
|
||||
}
|
||||
|
||||
$(description).show();
|
||||
} else if (command.link) {
|
||||
$(description).html("<a class='link_underline' href='" + DOC_BASE+
|
||||
command.link+"'>Read more</a>");
|
||||
} else {
|
||||
$(description).hide();
|
||||
}
|
||||
|
||||
selected_command.html($('<a>')
|
||||
.attr('href', DOC_BASE+command.link)
|
||||
.text(command.name));
|
||||
|
||||
change_path(command);
|
||||
|
||||
request_button.val(command.method);
|
||||
request_button.text(command.method+" request");
|
||||
update_method(request_button);
|
||||
|
||||
if (command.hasOwnProperty("body")) {
|
||||
cm_request.setValue(JSON.stringify(command.body, null, 2));
|
||||
} else {
|
||||
//No body, so wipe out the current contents.
|
||||
cm_request.setValue("");
|
||||
}
|
||||
cm_request.refresh();
|
||||
|
||||
reset_response_area();
|
||||
};
|
||||
|
||||
function get_path() {
|
||||
s = "";
|
||||
rest_url.find(".non_editable, .editable").each(function() {
|
||||
if (this.tagName == "INPUT") {
|
||||
s += $(this).val();
|
||||
} else {
|
||||
s += $(this).text();
|
||||
}
|
||||
});
|
||||
return s;
|
||||
}
|
||||
|
||||
function send_request() {
|
||||
//var method = rest_method.val();
|
||||
var method = request_button.val();
|
||||
if (method != GET && method != POST && method != PUT && method != DELETE) {
|
||||
console.log("ERROR: unrecognized http method");
|
||||
return;
|
||||
}
|
||||
//var path = rest_url.val();
|
||||
var path = get_path();
|
||||
|
||||
$(this).addClass('depressed');
|
||||
response_body.addClass('obscured');
|
||||
|
||||
var original_cmd = requests[slugify(selected_command.text())];
|
||||
|
||||
if (original_cmd.hasOwnProperty("body")) {
|
||||
var body = cm_request.getValue();
|
||||
$.ajax({
|
||||
type: method,
|
||||
url: URL_BASE + path,
|
||||
data: body,
|
||||
contentType: 'application/json',
|
||||
processData: false
|
||||
}).done(success_output).fail(error_output).always(reset_sending_status);
|
||||
} else {
|
||||
$.ajax({
|
||||
type: method,
|
||||
url: URL_BASE + path
|
||||
}).done(success_output).fail(error_output).always(reset_sending_status);
|
||||
}
|
||||
|
||||
spinner.show();
|
||||
}
|
||||
|
||||
function error_output(xhr,status,statusText) {
|
||||
response_code.text(xhr.status+" "+xhr.statusText);
|
||||
cm_response.setValue(xhr.responseText);
|
||||
}
|
||||
|
||||
function success_output(body,status,xhr) {
|
||||
response_code.text(xhr.status+" "+xhr.statusText);
|
||||
cm_response.setValue(JSON.stringify(body, null, 2));
|
||||
}
|
||||
|
||||
function reset_sending_status() {
|
||||
response_body.removeClass('obscured');
|
||||
request_button.removeClass('depressed');
|
||||
spinner.hide();
|
||||
}
|
||||
|
||||
function reset_response_area() {
|
||||
cm_response.setValue("");
|
||||
response_code.text("");
|
||||
}
|
||||
|
||||
function change_base_url(u) {
|
||||
window.URL_BASE = u;
|
||||
$("#rest_host").text(u);
|
||||
}
|
||||
|
||||
$(document).ready(function() {
|
||||
//wait for the Requests to be populated by another file
|
||||
generate_table_of_contents();
|
||||
make_commands_clickable();
|
||||
|
||||
if (window.location.hash) {
|
||||
var cmd = window.location.hash.slice(1).toLowerCase();
|
||||
select_request(cmd);
|
||||
} else {
|
||||
select_request();
|
||||
}
|
||||
|
||||
if (urlParams["base_url"]) {
|
||||
change_base_url(urlParams["base_url"]);
|
||||
}
|
||||
|
||||
request_button.click(send_request);
|
||||
|
||||
});
|
||||
|
||||
var urlParams;
|
||||
(window.onpopstate = function () {
|
||||
var match,
|
||||
pl = /\+/g, // Regex for replacing addition symbol with a space
|
||||
search = /([^&=]+)=?([^&]*)/g,
|
||||
decode = function (s) { return decodeURIComponent(s.replace(pl, " ")); },
|
||||
query = window.location.search.substring(1);
|
||||
|
||||
urlParams = {};
|
||||
while (match = search.exec(query))
|
||||
urlParams[decode(match[1])] = decode(match[2]);
|
||||
})();
|
||||
@@ -1,21 +1,36 @@
|
||||
var urlParams;
|
||||
(window.onpopstate = function () {
|
||||
var match,
|
||||
pl = /\+/g, // Regex for replacing addition symbol with a space
|
||||
search = /([^&=]+)=?([^&]*)/g,
|
||||
decode = function (s) { return decodeURIComponent(s.replace(pl, " ")); },
|
||||
query = window.location.search.substring(1);
|
||||
|
||||
urlParams = {};
|
||||
while (match = search.exec(query))
|
||||
urlParams[decode(match[1])] = decode(match[2]);
|
||||
})();
|
||||
|
||||
;(function() {
|
||||
var DOC_BASE = 'reference-rippled.html';
|
||||
|
||||
var request_button = $('#request_button');
|
||||
var online_state = $('#online_state');
|
||||
var command_wrapper = $('#command_wrapper');
|
||||
var command_list = $(command_wrapper).find('#command_list');
|
||||
var command_list = $('#command_list');
|
||||
var commands = $(command_list).find('li');
|
||||
var command_table = $(command_wrapper).find('#command_table');
|
||||
var input = $(command_wrapper).find('#input');
|
||||
var command_table = $('#command_table');
|
||||
var input = $('#input');
|
||||
var description = $(input).find('#description');
|
||||
var options = $(input).find('#options');
|
||||
var output = $(command_wrapper).find('#output');
|
||||
var response = $(command_wrapper).find('#response');
|
||||
var request = $(command_wrapper).find('#request');
|
||||
var status = $(command_wrapper).find('#status');
|
||||
var info = $(command_wrapper).find('#info');
|
||||
var output = $('#output');
|
||||
var response = $('#response');
|
||||
var request = $('#request');
|
||||
var status = $('#status');
|
||||
var info = $('#info');
|
||||
var spinner = $(".loader");
|
||||
|
||||
var BASE_HOST_DEFAULT = 's2.ripple.com';
|
||||
var BASE_PORT_DEFAULT = 443;
|
||||
|
||||
var remote = new ripple.Remote({
|
||||
trusted: true,
|
||||
@@ -23,12 +38,16 @@
|
||||
local_fee: false,
|
||||
servers: [
|
||||
{
|
||||
host: 's1.ripple.com',
|
||||
port: 443,
|
||||
host: BASE_HOST_DEFAULT,
|
||||
port: BASE_PORT_DEFAULT,
|
||||
secure: true
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
function new_remote(options) {
|
||||
remote = new ripple.Remote(options);
|
||||
}
|
||||
|
||||
function set_online_state(state) {
|
||||
var state = state.toLowerCase();
|
||||
@@ -42,7 +61,13 @@
|
||||
});
|
||||
|
||||
remote.on('connect', function() {
|
||||
set_online_state('connected');
|
||||
var msg = "connected";
|
||||
if (remote._servers.length === 1) {
|
||||
msg = "connected to "+remote._servers[0].getHostID();
|
||||
} else if (remote._servers.length > 1) {
|
||||
msg = "connected to "+remote._servers.length+" servers";
|
||||
}
|
||||
set_online_state(msg);
|
||||
});
|
||||
|
||||
/* ---- ---- ---- ---- ---- */
|
||||
@@ -87,23 +112,24 @@
|
||||
};
|
||||
|
||||
var sample_address = 'r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59';
|
||||
var sample_address_2 = 'ra5nK24KXen9AHvsdFTKHSANinZseWnPcX';
|
||||
var sample_tx = 'E08D6E9754025BA2534A78707605E0601F03ACE063687A0CA1BDDACFCD1698C7';
|
||||
|
||||
/* ---- ---- */
|
||||
|
||||
Request('server_info', {
|
||||
_description: 'Returns information about the state of the server for human consumption. Results are subject to change without notice.',
|
||||
_link: 'rippled-apis.html#server-info'
|
||||
_description: 'Get information about the state of the server for human consumption. Results are subject to change without notice.',
|
||||
_link: DOC_BASE + '#server-info'
|
||||
});
|
||||
|
||||
Request('server_state', {
|
||||
_description: 'Returns information about the state of the server for machine consumption.',
|
||||
_link: 'rippled-apis.html#server-state'
|
||||
_description: 'Get information about the state of the server for machine consumption.',
|
||||
_link: DOC_BASE + '#server-state'
|
||||
});
|
||||
|
||||
Request('ping', {
|
||||
_description: 'This command is used to check connectivity for clients. Websocket clients can use this to determine turn around time and actively discover loss of connectivity to a server.',
|
||||
_link: 'rippled-apis.html#ping'
|
||||
_description: 'Check connectivity to the server.',
|
||||
_link: DOC_BASE + '#ping'
|
||||
});
|
||||
|
||||
/* ---- ---- */
|
||||
@@ -112,7 +138,7 @@
|
||||
accounts: [ ],
|
||||
streams: [ 'server', 'ledger' ],
|
||||
_description: 'Start receiving selected streams from the server.',
|
||||
_link: 'rippled-apis.html#subscribe',
|
||||
_link: DOC_BASE + '#subscribe',
|
||||
_stream: true
|
||||
});
|
||||
|
||||
@@ -120,7 +146,7 @@
|
||||
accounts: [ ],
|
||||
streams: [ 'server', 'ledger' ],
|
||||
_description: 'Stop receiving selected streams from the server.',
|
||||
_link: 'rippled-apis.html#unsubscribe',
|
||||
_link: DOC_BASE + '#unsubscribe',
|
||||
_stream: true
|
||||
});
|
||||
|
||||
@@ -134,7 +160,7 @@
|
||||
transactions: true,
|
||||
accounts: true,
|
||||
_description: 'Returns ledger information.',
|
||||
_link: 'rippled-apis.html#ledger'
|
||||
_link: DOC_BASE + '#ledger'
|
||||
});
|
||||
|
||||
Request('ledger_entry', {
|
||||
@@ -142,42 +168,42 @@
|
||||
account_root: sample_address,
|
||||
ledger_index: 'validated',
|
||||
ledger_hash: void(0),
|
||||
_description: 'Returns a ledger entry. For untrusted servers, the index option provides raw access to ledger entries and proof.',
|
||||
_link: 'rippled-apis.html#ledger-entry'
|
||||
_description: 'Get a single node from the ledger',
|
||||
_link: DOC_BASE + '#ledger-entry'
|
||||
});
|
||||
|
||||
Request('ledger_closed', {
|
||||
_description: 'Returns the most recent closed ledger index. If a validation list has been provided, then validations should be available.',
|
||||
_link: 'rippled-apis.html#ledger-closed'
|
||||
_description: 'Get the most recent closed ledger index.',
|
||||
_link: DOC_BASE + '#ledger-closed'
|
||||
});
|
||||
|
||||
Request('ledger_current', {
|
||||
_description: 'Returns the current proposed ledger index. Proof is not possible for the current ledger. This command is primarily useful for testing.',
|
||||
_link: 'rippled-apis.html#ledger-current'
|
||||
_description: 'Get the current in-progress ledger index.',
|
||||
_link: DOC_BASE + '#ledger-current'
|
||||
});
|
||||
|
||||
/* ---- ---- */
|
||||
|
||||
Request('account_info', {
|
||||
account: sample_address,
|
||||
_description: 'Returns information about the specified account.',
|
||||
_link: 'rippled-apis.html#account-info'
|
||||
_description: 'Get information about the specified account.',
|
||||
_link: DOC_BASE + '#account-info'
|
||||
});
|
||||
|
||||
Request('account_lines', {
|
||||
account: sample_address,
|
||||
account_index: void(0),
|
||||
ledger: 'current',
|
||||
_description: 'Returns information about the ripple credit lines for the specified account.',
|
||||
_link: 'rippled-apis.html#account-lines'
|
||||
_description: "Get a list of trust lines connected to an account.",
|
||||
_link: DOC_BASE + '#account-lines'
|
||||
});
|
||||
|
||||
Request('account_offers', {
|
||||
account: sample_address,
|
||||
account_index: void(0),
|
||||
ledger: 'current',
|
||||
_description: 'Returns the outstanding offers for a specified account.',
|
||||
_link: 'rippled-apis.html#account-offers'
|
||||
_description: 'Get a list of offers created by an account.',
|
||||
_link: DOC_BASE + '#account-offers'
|
||||
});
|
||||
|
||||
Request('account_tx', {
|
||||
@@ -189,8 +215,27 @@
|
||||
limit: 10,
|
||||
forward: false,
|
||||
marker: void(0),
|
||||
_description: 'Returns a list of transactions that applied to a specified account.',
|
||||
_link: 'rippled-apis.html#account-tx'
|
||||
_description: 'Get a list of transactions that applied to a specified account.',
|
||||
_link: DOC_BASE + '#account-tx'
|
||||
});
|
||||
|
||||
Request('account_currencies', {
|
||||
account: sample_address,
|
||||
strict: true,
|
||||
ledger_index: "validated",
|
||||
account_index: 0,
|
||||
_description: 'Returns a list of currencies the account can send or receive.',
|
||||
_link: DOC_BASE + '#account-currencies'
|
||||
});
|
||||
|
||||
Request('gateway_balances', {
|
||||
account: sample_address,
|
||||
strict: true,
|
||||
hotwallet: [],
|
||||
ledger_index: "validated",
|
||||
account_index: 0,
|
||||
_description: 'Returns a list of currencies the account can send or receive.',
|
||||
_link: DOC_BASE + '#gateway-balances'
|
||||
});
|
||||
|
||||
/* ---- ---- */
|
||||
@@ -199,20 +244,20 @@
|
||||
tx_hash: sample_tx,
|
||||
ledger_index: 348734,
|
||||
ledger_hash: void(0),
|
||||
_description: 'Returns information about a specified transaction.',
|
||||
_link: 'rippled-apis.html#transaction-entry'
|
||||
_description: 'Get information about a specified transaction.',
|
||||
_link: DOC_BASE + '#transaction-entry'
|
||||
});
|
||||
|
||||
Request('tx', {
|
||||
transaction: sample_tx,
|
||||
_description: 'Returns information about a specified transaction.',
|
||||
_link: 'rippled-apis.html#tx'
|
||||
_link: DOC_BASE + '#tx'
|
||||
});
|
||||
|
||||
Request('tx_history', {
|
||||
start: 10,
|
||||
_description: 'Returns the last N transactions starting from start index, in descending order, by ledger sequence number. Server sets N.',
|
||||
_link: 'rippled-apis.html#tx-history'
|
||||
_link: DOC_BASE + '#tx-history'
|
||||
});
|
||||
|
||||
Request('book_offers', {
|
||||
@@ -228,16 +273,20 @@
|
||||
},
|
||||
limit: 10,
|
||||
_description: 'Returns a snapshot of the offers for an order book.',
|
||||
_link: 'rippled-apis.html#book-offers'
|
||||
_link: DOC_BASE + '#book-offers'
|
||||
});
|
||||
|
||||
Request('path_find', {
|
||||
subcommand: 'create',
|
||||
source_account: sample_address,
|
||||
destination_account: 'r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59',
|
||||
destination_amount: ripple.Amount.from_json('0.001/USD/rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B').to_json(),
|
||||
destination_account: sample_address_2,
|
||||
destination_amount: {
|
||||
"currency": "USD",
|
||||
"value": "0.01",
|
||||
"issuer": sample_address_2
|
||||
},
|
||||
_description: 'Start or stop searching for payment paths between specified accounts.',
|
||||
_link: 'rippled-apis.html#path-find',
|
||||
_link: DOC_BASE + '#path-find',
|
||||
_stream: true
|
||||
});
|
||||
|
||||
@@ -246,24 +295,28 @@
|
||||
ledger_index : void(0),
|
||||
source_account : sample_address,
|
||||
source_currencies : [ { currency : 'USD' } ],
|
||||
destination_account : 'r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59',
|
||||
destination_amount : ripple.Amount.from_json('0.001/USD/rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B').to_json(),
|
||||
destination_account : sample_address_2,
|
||||
destination_amount : {
|
||||
"currency": "USD",
|
||||
"value": "0.01",
|
||||
"issuer": sample_address_2
|
||||
},
|
||||
_description: 'Find a path between specified accounts once. For repeated usage, call <strong>path_find</strong> instead.',
|
||||
_link: 'rippled-apis.html#ripple-path-find'
|
||||
_link: DOC_BASE + '#ripple-path-find'
|
||||
});
|
||||
|
||||
Request('submit', {
|
||||
secret: 'sssssssssssssssssssssssssssss',
|
||||
secret: 'sn3nxiW7v8KXzPzAqzyHXbSSKNuN9',
|
||||
tx_json: {
|
||||
Flags: 0,
|
||||
TransactionType: 'AccountSet',
|
||||
Account: 'rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn',
|
||||
Sequence: void(0),
|
||||
Fee: '15',
|
||||
Fee: '10000',
|
||||
Flags: 0
|
||||
},
|
||||
_description: 'Submits a transaction to the network.',
|
||||
_link: 'rippled-apis.html#submit',
|
||||
_link: DOC_BASE + '#submit',
|
||||
_takes_secret: true
|
||||
});
|
||||
|
||||
@@ -278,10 +331,11 @@
|
||||
"issuer" : "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn"
|
||||
}
|
||||
},
|
||||
secret : "sssssssssssssssssssssssssssss",
|
||||
secret : "sn3nxiW7v8KXzPzAqzyHXbSSKNuN9",
|
||||
offline: false,
|
||||
fee_mult_max: 1000,
|
||||
_description: 'Sends a transaction to be signed by the server.',
|
||||
_link: 'rippled-apis.html#sign',
|
||||
_link: DOC_BASE + '#sign',
|
||||
_takes_secret: true
|
||||
});
|
||||
|
||||
@@ -326,7 +380,7 @@
|
||||
if (command._description) {
|
||||
//$(description).html(command._description).show();
|
||||
$(description).html(command._description);
|
||||
$(description).append(" <a class='btn btn-primary' href='"+command._link+"'>Read more</a>");
|
||||
$(description).append(" <a class='button btn btn-primary' href='"+command._link+"'>Read more</a>");
|
||||
} else {
|
||||
$(description).hide();
|
||||
}
|
||||
@@ -629,6 +683,37 @@
|
||||
|
||||
$(function() {
|
||||
set_online_state('connecting');
|
||||
|
||||
if (urlParams["base_url"]) {
|
||||
base_url = urlParams["base_url"].split(":");
|
||||
if (base_url.length == 2) {
|
||||
base_host = base_url[0];
|
||||
base_port = base_url[1];
|
||||
} else {
|
||||
base_host = base_url[0];
|
||||
base_port = BASE_PORT_DEFAULT;
|
||||
}
|
||||
|
||||
if (urlParams["use_wss"]
|
||||
&& urlParams["use_wss"].toLowerCase() === "false") {
|
||||
use_wss = false;
|
||||
} else {
|
||||
use_wss = true;
|
||||
}
|
||||
|
||||
new_remote({
|
||||
trusted: true,
|
||||
local_signing: true,
|
||||
local_fee: false,
|
||||
servers: [
|
||||
{
|
||||
host: base_host,
|
||||
port: base_port,
|
||||
secure: use_wss
|
||||
}
|
||||
]
|
||||
});
|
||||
}
|
||||
|
||||
remote.connect(init);
|
||||
|
||||
37
assets/js/expandcode.js
Normal file
@@ -0,0 +1,37 @@
|
||||
var toggle_cs = function(eo) {
|
||||
//eo = $("#"+id);
|
||||
var wrapper = $(eo.target).parent();
|
||||
var code_el = wrapper.find("code");
|
||||
code_el.toggleClass('expanded');
|
||||
var placeholders = wrapper.find(".code-placeholder");
|
||||
if (placeholders.length) {
|
||||
placeholders.remove();
|
||||
} else {
|
||||
code_el.after("<div class='code-placeholder' style='width:"
|
||||
+ code_el.width()
|
||||
+ "px; height:"
|
||||
+ code_el.height()
|
||||
+ "px;'> </div>");
|
||||
}
|
||||
current_button_text = wrapper.find(".code_toggler").val();
|
||||
$(eo.target).val(current_button_text == 'Expand' ? "Collapse" : "Expand");
|
||||
}
|
||||
|
||||
function make_code_expandable() {
|
||||
var newid = 0;
|
||||
$(".content > pre > code").parent().wrap(function() {
|
||||
newid = newid+1;
|
||||
return "<div class='code_sample' id='code_autoid_"+newid+"'>";
|
||||
});
|
||||
|
||||
var cs = $('.code_sample');
|
||||
cs.find("code").dblclick(toggle_cs);
|
||||
cs.find("code").attr('title', 'Double-click to expand/collapse');
|
||||
var newbtn = $("<input type='button' class='code_toggler' value='Expand' />");
|
||||
newbtn.appendTo(cs);
|
||||
$(".code_toggler").click(toggle_cs);
|
||||
|
||||
/* fix expand/collapse and tab click hierarchy */
|
||||
cs.css("position","relative");
|
||||
$(".multicode .code_sample").css("position","static");
|
||||
}
|
||||
9
assets/js/fixsidebarscroll.js
Normal file
@@ -0,0 +1,9 @@
|
||||
$(window).scroll(function() {
|
||||
var footerpos = parseInt($("footer").offset().top);
|
||||
var scrollpos = $(window).scrollTop() + $(window).height();
|
||||
if(scrollpos - footerpos > 0) {
|
||||
$("aside.sidebar .dev_nav_wrapper").css("bottom", (scrollpos-footerpos)+"px");
|
||||
} else {
|
||||
$("aside.sidebar .dev_nav_wrapper").css("bottom", 0);
|
||||
}
|
||||
});
|
||||
13
assets/js/jquery.gensidebar.js
Normal file
@@ -0,0 +1,13 @@
|
||||
$(document).ready(function() {
|
||||
tableOfContents = $("<ul class='dev_nav_sidebar'>").appendTo(".sidebar #cont")
|
||||
$("h1, h2, h3").each(function() {
|
||||
indent_level = this.tagName.toLowerCase().substr(1);
|
||||
if (this.id) { //only show headers with IDs. which should be all of them.
|
||||
href = "#"+this.id;
|
||||
$("<li class='level-"+indent_level+"'><a href='"+href+"'>"+
|
||||
$(this).text()+"</a></li>").appendTo(tableOfContents);
|
||||
}
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,46 +1,11 @@
|
||||
// Original code to adapt the markup for tabs.
|
||||
// Expects markup in the form of:
|
||||
// <div class='multicode'>
|
||||
// <em>tab 1 title</em>
|
||||
// <code>tab 1 code block</code>
|
||||
// <em>tab 2 title</em>
|
||||
// <code>tab 2 code block</code>
|
||||
// <p><em>tab 1 title</em></p>
|
||||
// <pre><code>tab 1 code block</code></pre>
|
||||
// <p><em>tab 2 title</em></p>
|
||||
// <pre><code>tab 2 code block</code></pre>
|
||||
// </div>
|
||||
jQuery.fn.multicode_tabs = function() {
|
||||
$('.multicode').each(function(index,el) {
|
||||
cb_area = $(el);
|
||||
cb_area.attr('id', "code-"+index);
|
||||
// make a ul to house the tab headers
|
||||
cb_area.prepend("<ul class='codetabs'></ul>");
|
||||
|
||||
// for each code, give it a unique ID and wrap it in a pre
|
||||
cb_area.children('code').each(function(index2,el2) {
|
||||
var linkid = 'code-'+index+'-'+index2;
|
||||
$(el2).wrap("<div id='"+linkid+"'><pre>");
|
||||
//also put in a link to this in the tab header ul
|
||||
$('ul', cb_area).append("<li><a href='#"+linkid+"'></a></li>");
|
||||
});
|
||||
|
||||
//use the ems to fill in the tab headers for each block
|
||||
$(el).children('em').each(function(index2, el2) {
|
||||
$('ul li:eq('+index2+') a', cb_area).text($(el2).text());
|
||||
});
|
||||
});
|
||||
$('.multicode em').hide();
|
||||
|
||||
$('.multicode').minitabs();
|
||||
}
|
||||
|
||||
|
||||
// Variant version for the HTML that Pandoc generates
|
||||
// Expects markup in the form of:
|
||||
// <div class='multicode'>
|
||||
// <p><em>tab 1 title</em></p>
|
||||
// <pre><code>tab 1 code block</code></pre>
|
||||
// <p><em>tab 2 title</em></p>
|
||||
// <pre><code>tab 2 code block</code></pre>
|
||||
// </div>
|
||||
jQuery.fn.multicode_tabs_pandoc = function() {
|
||||
$('.multicode').each(function(index,el) {
|
||||
cb_area = $(el);
|
||||
cb_area.attr('id', "code-"+index);
|
||||
@@ -49,7 +14,7 @@ jQuery.fn.multicode_tabs_pandoc = function() {
|
||||
|
||||
cb_area.children('pre').each(function(index2,el2) {
|
||||
var linkid = 'code-'+index+'-'+index2;
|
||||
$(el2).wrap("<div id='"+linkid+"'>");
|
||||
$(el2).wrap("<div id='"+linkid+"' class='code_sample'>");
|
||||
//also put in a link to this in the tab header ul
|
||||
$('ul', cb_area).append("<li><a href='#"+linkid+"'></a></li>");
|
||||
});
|
||||
@@ -59,6 +24,7 @@ jQuery.fn.multicode_tabs_pandoc = function() {
|
||||
});
|
||||
});
|
||||
$('.multicode p').hide();
|
||||
$('.multicode .code_sample').css("position","static");
|
||||
|
||||
$('.multicode').minitabs();
|
||||
}
|
||||
12
assets/js/ripple-0.11.0-min.js
vendored
Normal file
11
circle.yml
Normal file
@@ -0,0 +1,11 @@
|
||||
general:
|
||||
build_dir: tool/
|
||||
dependencies:
|
||||
pre:
|
||||
- pyenv global 3.4.0
|
||||
override:
|
||||
- pip3 install -r packages.txt
|
||||
test:
|
||||
override:
|
||||
- ./dactyl_build.py
|
||||
- ./dactyl_link_checker.py
|
||||
391
concept-amendments.html
Normal file
@@ -0,0 +1,391 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
|
||||
<meta name="viewport" content="width=device-width">
|
||||
|
||||
<title>Amendments - Ripple Developer Portal</title>
|
||||
|
||||
<!-- favicon -->
|
||||
<link rel="icon" href="favicon.ico" type="image/x-icon">
|
||||
<link rel="shortcut icon" href="favicon.ico" type="image/x-icon">
|
||||
|
||||
<!-- jQuery -->
|
||||
<script src="assets/vendor/jquery-1.11.1.min.js"></script>
|
||||
|
||||
<!-- Custom Stylesheets. ripple.css includes bootstrap, font stuff -->
|
||||
<link href="assets/css/ripple.css" rel="stylesheet" />
|
||||
<link href="assets/css/devportal.css" rel="stylesheet" />
|
||||
|
||||
<!-- Bootstrap JS -->
|
||||
<script src="assets/vendor/bootstrap.min.js"></script>
|
||||
|
||||
|
||||
<!-- syntax highlighting -->
|
||||
<link rel="stylesheet" href="assets/vendor/docco.min.css">
|
||||
<script src="assets/vendor/highlight.min.js"></script>
|
||||
|
||||
<!-- syntax selection js -->
|
||||
<script src="assets/js/multicodetab.js"></script>
|
||||
<script>
|
||||
$(document).ready(function() {
|
||||
$().multicode_tabs();
|
||||
hljs.initHighlighting();
|
||||
make_code_expandable();
|
||||
});
|
||||
</script>
|
||||
|
||||
<script src="assets/js/expandcode.js"></script>
|
||||
<script src="assets/js/fixsidebarscroll.js"></script>
|
||||
|
||||
</head>
|
||||
|
||||
<body class="page page-template page-template-template-dev-portal page-template-template-dev-portal-php sidebar-primary wpb-js-composer js-comp-ver-3.6.2 vc_responsive">
|
||||
<header role="banner" class="banner navbar navbar-default navbar-fixed-top initial_header">
|
||||
<div class="container">
|
||||
<div class="navbar-header">
|
||||
<a href="index.html" class="navbar-brand"><img src="assets/img/ripple-logo-color.png" class="logo"></a>
|
||||
</div><!-- /.navbar-header -->
|
||||
<div class="nav">
|
||||
<div class="draft-warning">DRAFT PAGE</div>
|
||||
</div><!-- /.nav -->
|
||||
|
||||
</div><!-- /.container -->
|
||||
|
||||
<div class="subnav dev_nav">
|
||||
<div class="container">
|
||||
<ul id="menu-dev-menu" class="menu">
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">References <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="reference-rippled.html">rippled</a></li>
|
||||
<li><a href="reference-transaction-format.html">Transaction Format</a></li>
|
||||
<li><a href="reference-ledger-format.html">Ledger Format</a></li>
|
||||
<li><a href="reference-rippleapi.html">RippleAPI</a></li>
|
||||
<li><a href="reference-data-api.html">Ripple Data API v2</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Tutorials <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="tutorial-rippleapi-beginners-guide.html">RippleAPI Beginners Guide</a></li>
|
||||
<li><a href="tutorial-rippled-setup.html">rippled Setup</a></li>
|
||||
<li><a href="tutorial-reliable-transaction-submission.html">Reliable Transaction Submission</a></li>
|
||||
<li><a href="tutorial-multisign.html">How to Multi-Sign</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Concepts <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="concept-paths.html">Paths</a></li>
|
||||
<li><a href="concept-fees.html">Fees (Disambiguation)</a></li>
|
||||
<li><a href="concept-transfer-fees.html">Transfer Fees</a></li>
|
||||
<li><a href="concept-transaction-cost.html">Transaction Cost</a></li>
|
||||
<li><a href="concept-fee-voting.html">Fee Voting</a></li>
|
||||
<li><a href="concept-reserves.html">Reserves</a></li>
|
||||
<li><a href="concept-freeze.html">Freeze</a></li>
|
||||
<li><a href="concept-amendments.html">Amendments</a></li>
|
||||
<li><a href="concept-stand-alone-mode.html">Stand-Alone Mode</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Best Practices <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="concept-issuing-and-operational-addresses.html">Issuing and Operational Addresses</a></li>
|
||||
<li><a href="tutorial-gateway-guide.html">Gateway Guide</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">API Tools <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="ripple-api-tool.html">WebSocket API Tool</a></li>
|
||||
<li><a href="data-api-v2-tool.html">Data API v2 Tool</a></li>
|
||||
<li><a href="tool-jsonrpc.html">rippled JSON-RPC Tool</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Resources <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="https://forum.ripple.com/viewforum.php?f=2">Forums</a></li>
|
||||
<li><a href="https://www.bountysource.com/teams/ripple/bounties">Bounties</a></li>
|
||||
<li><a href="https://ripplelabs.atlassian.net/">Bug Tracking</a></li>
|
||||
<li><a href="https://ripple.com/category/dev-blog/">Dev Blog</a></li>
|
||||
<li><a href="https://ripple.com/press-releases/">Press Center</a></li>
|
||||
<li><a href="https://ripple.com/brand-guidelines/">Brand Guidelines</a></li>
|
||||
</ul>
|
||||
<li><a href="https://github.com/ripple/ripple-dev-portal" title="GitHub">Site Source</a></li>
|
||||
</ul><!-- /#dev-menu -->
|
||||
</div><!-- /.subnav .container -->
|
||||
</div><!-- /.subnav -->
|
||||
</header>
|
||||
|
||||
|
||||
<div class="wrap container" role="document">
|
||||
<aside class="sidebar" role="complementary">
|
||||
<div class="dev_nav_wrapper">
|
||||
<div id="cont">
|
||||
<ul class="dev_nav_sidebar">
|
||||
<li class="level-1"><a href="index.html">Category: Concepts</a></li>
|
||||
<li class="level-2"><a href="concept-paths.html">Paths</a></li>
|
||||
<li class="level-2"><a href="concept-fees.html">Fees (Disambiguation)</a></li>
|
||||
<li class="level-2"><a href="concept-transfer-fees.html">Transfer Fees</a></li>
|
||||
<li class="level-2"><a href="concept-transaction-cost.html">Transaction Cost</a></li>
|
||||
<li class="level-2"><a href="concept-fee-voting.html">Fee Voting</a></li>
|
||||
<li class="level-2"><a href="concept-reserves.html">Reserves</a></li>
|
||||
<li class="level-2"><a href="concept-freeze.html">Freeze</a></li>
|
||||
<li class="level-2"><a href="concept-amendments.html">Amendments</a></li>
|
||||
<li class="level-2"><a href="concept-stand-alone-mode.html">Stand-Alone Mode</a></li>
|
||||
</ul>
|
||||
<hr />
|
||||
<h5>In this page:</h5>
|
||||
</div>
|
||||
<script type="text/javascript" src="assets/js/jquery.gensidebar.js"></script>
|
||||
</div>
|
||||
</aside>
|
||||
<main class="main" role="main">
|
||||
<div class='content'>
|
||||
<h1 id="amendments">Amendments</h1>
|
||||
<p><em>(New in <a href="https://wiki.ripple.com/Rippled-0.31.0">version 0.31.0</a>)</em></p>
|
||||
<p>The Amendments system provides a means of introducing new features to the decentralized Ripple consensus network without causing disruptions. The amendments system works by utilizing the core consensus process of the network to approve any changes by showing continuous support before those changes go into effect. An amendment normally requires <strong>80% support for two weeks</strong> before it can apply.</p>
|
||||
<p>When an Amendment has been enabled, it applies permanently to all ledger versions after the one that included it. You cannot disable an Amendment, unless you introduce a new Amendment to do so.</p>
|
||||
<h2 id="background">Background</h2>
|
||||
<p>Any changes to transaction processing could cause servers to build a different ledger with the same set of transactions. If only a portion of <em>validators</em> (<code>rippled</code> servers <a href="tutorial-rippled-setup.html#reasons-to-run-a-validator">participating in consensus</a>) have upgraded to a new version of the software, this could cause anything from minor inconveniences to full outages. In the minor case, a minority of servers spend more time and bandwidth fetching the actual consensus ledger because they cannot build it using the transaction processing rules they already know. In the worst case, <a href="https://ripple.com/knowledge_center/the-ripple-ledger-consensus-process/">the consensus process</a> might be unable to validate new ledger versions because servers with different rules could not reach a consensus on the exact ledger to build.</p>
|
||||
<p>Amendments provide a solution to this problem, so that new features can be enabled only when enough validators support those features.</p>
|
||||
<p>Users and businesses who rely on the Ripple Consensus Ledger can also use Amendments to provide advance notice of changes in transaction processing that might affect their business. However, API changes that do not impact transaction processing or <a href="https://ripple.com/knowledge_center/the-ripple-ledger-consensus-process/">the consensus process</a> do not require Amendments.</p>
|
||||
<h2 id="about-amendments">About Amendments</h2>
|
||||
<p>An amendment is a fully-functional feature or change, waiting to be enabled by the peer-to-peer network as a part of the consensus process. A <code>rippled</code> server that wants to use an amendment has code for two modes: without the amendment (previous behavior) and with the amendment (new behavior).</p>
|
||||
<p>Every amendment has a unique identifying hex value and a short name. The short name is for human use, and is not used in the amendment process. Two servers can support the same amendment ID while using different names to describe it. An amendment's name is not guaranteed to be unique.</p>
|
||||
<p>See also: <a href="#known-amendments">Known Amendments</a></p>
|
||||
<h2 id="amendment-process">Amendment Process</h2>
|
||||
<p>Every 256th ledger is called a "flag" ledger. The process of approving an amendment starts in the ledger version immediately before the flag ledger. When <code>rippled</code> validator servers send validation messages for that ledger, those servers also submit votes in favor of specific amendments. (<a href="concept-fee-voting.html">Fee Voting</a> also occurs around flag ledgers.)</p>
|
||||
<p>The flag ledger itself has no special contents. However, during that time, the servers look at the votes of the validators they trust, and decide whether to insert an <a href="reference-transaction-format.html#enableamendment"><code>EnableAmendment</code> pseudo-transaction</a> into the following ledger. The flags of an EnableAmendment pseudo-transaction indicate what the server thinks happened:</p>
|
||||
<ul>
|
||||
<li>The <code>tfGotMajority</code> flag means that support for the amendment has increased to at least 80% of trusted validators.</li>
|
||||
<li>The <code>tfLostMajority</code> flag means that support for the amendment has decreased to less than 80% of trusted validators.</li>
|
||||
<li>An EnableAmendment pseudo-transaction with no flags means that support for the amendment has been enabled. (The change in transaction processing applies to every ledger after this one.)</li>
|
||||
</ul>
|
||||
<p>A server only inserts the pseudo-transaction to enable an amendment if all of the following conditions are met:</p>
|
||||
<ul>
|
||||
<li>The amendment has not already been enabled.</li>
|
||||
<li>A previous ledger includes an EnableAmendment pseudo-transaction for this amendment with the <code>tfGotMajority</code> flag enabled.</li>
|
||||
<li>The previous ledger in question is an ancestor of the current ledger.</li>
|
||||
<li>The previous ledger in question has a close time that is at least <strong>two weeks</strong> before the close time of the latest flag ledger.</li>
|
||||
<li>There are no EnableAmendment pseudo-transactions for this amendment with the <code>tfLostMajority</code> flag enabled in the consensus ledgers between the <code>tfGotMajority</code> pseudo-transaction and the current ledger.</li>
|
||||
</ul>
|
||||
<p>It is theoretically possible (but extremely unlikely) that a <code>tfLostMajority</code> EnableAmendment pseudo-transaction could be included in the same ledger as the pseudo-transaction to enable an amendment. In this case, the pseudo-transaction with the <code>tfLostMajority</code> pseudo-transaction has no effect.</p>
|
||||
<h2 id="amendment-voting">Amendment Voting</h2>
|
||||
<p>Operators of <code>rippled</code> validators can choose which amendments to support or reject using the <a href="reference-rippled.html#feature"><code>feature</code> command</a>. This decides which amendments the validator votes for in the <a href="#amendment-process">amendment process</a>. By default, <code>rippled</code> votes in favor of every amendment it knows about.</p>
|
||||
<p>The operator of a <code>rippled</code> validator can "veto" an amendment. In this case, that validator never sends a vote in favor of the amendment. If enough servers veto an amendment, that prevents it from reaching consistent 80% support, so the amendment does not apply.</p>
|
||||
<p>As with all aspects of the consensus process, amendment votes are only taken into account by servers that trust the validators sending those votes. Currently, Ripple (the company) recommends only trusting the 5 default validators that Ripple (the company) operates. For now, trusting only those validators is sufficient to coordinate with Ripple (the company) on releasing new features.</p>
|
||||
<h3 id="configuring-amendment-voting">Configuring Amendment Voting</h3>
|
||||
<p>You can temporarily configure an amendment using the <a href="reference-rippled.html#feature"><code>feature</code> command</a>. To make a persistent change to your server's support for an amendment, modify your server's <code>rippled.cfg</code> file.</p>
|
||||
<p>Use the <code>[veto_amendments]</code> stanza to list amendments you do not want the server to vote for. Each line should contain one amendment's unique ID, optionally followed by the short name for the amendment. For example:</p>
|
||||
<pre><code>[veto_amendments]
|
||||
C1B8D934087225F509BEB5A8EC24447854713EE447D277F69545ABFA0E0FD490 Tickets
|
||||
DA1BD556B42D85EA9C84066D028D355B52416734D3283F85E216EA5DA6DB7E13 SusPay
|
||||
</code></pre>
|
||||
<p>Use the <code>[amendments]</code> stanza to list amendments you want to vote for. (Even if you do not list them here, by default a server votes for all the amendments it knows how to apply.) Each line should contain one amendment's unique ID, optionally followed by the short name for the amendment. For example:</p>
|
||||
<pre><code>[amendments]
|
||||
4C97EBA926031A7CF7D7B36FDE3ED66DDA5421192D63DE53FFB46E43B9DC8373 MultiSign
|
||||
42426C4D4F1009EE67080A9B7965B44656D7714D104A72F9B4369F97ABF044EE FeeEscalation
|
||||
</code></pre>
|
||||
<h2 id="testing-amendments">Testing Amendments</h2>
|
||||
<p>If you want to see how <code>rippled</code> behaves with an amendment enabled, before that amendment gets enabled on the production network, you can run use <code>rippled</code>'s configuration file to forcibly enable a feature. This is intended for development purposes only.</p>
|
||||
<p>Because other members of the consensus network probably do not have the feature enabled, you should not use this feature while connecting to the production network. While testing with features forcibly enabled, you should run <code>rippled</code> in <a href="concept-stand-alone-mode.html">Stand-Alone Mode</a>.</p>
|
||||
<p>To forcibly enable a feature, add a <code>[features]</code> stanza to your <code>rippled.cfg</code> file. In this stanza, add the short names of the features to enable, one per line. For example:</p>
|
||||
<pre><code>[features]
|
||||
MultiSign
|
||||
TrustSetAuth
|
||||
</code></pre>
|
||||
<h1 id="known-amendments">Known Amendments</h1>
|
||||
<p>The following is a comprehensive list of all known amendments and their status on the production Ripple Consensus Ledger:</p>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Name</th>
|
||||
<th>Introduced</th>
|
||||
<th>Enabled</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td><a href="#tickets">Tickets</a></td>
|
||||
<td>v0.31.0</td>
|
||||
<td>TBD</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="#suspay">SusPay</a></td>
|
||||
<td>v0.31.0</td>
|
||||
<td>TBD</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="#trustsetauth">TrustSetAuth</a></td>
|
||||
<td>v0.30.0</td>
|
||||
<td>TBD</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="#multisign">MultiSign</a></td>
|
||||
<td>v0.31.0</td>
|
||||
<td>TBD</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="#feeescalation">FeeEscalation</a></td>
|
||||
<td>v0.31.0</td>
|
||||
<td>TBD</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<p><strong>Note:</strong> In many cases, an incomplete version of the code for an amendment is present in previous versions of the software. The "Introduced" version in the table above is the first stable version.</p>
|
||||
<h2 id="feeescalation">FeeEscalation</h2>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Amendment ID</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>42426C4D4F1009EE67080A9B7965B44656D7714D104A72F9B4369F97ABF044EE</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<p>Changes the way the <a href="concept-transaction-cost.html">transaction cost</a> applies to proposed transactions. Modifies the consensus process to prioritize transactions that pay a higher transaction cost.</p>
|
||||
<p>This amendment introduces a fixed-size transaction queue for transactions that were not able to be included in the previous consensus round. If the <code>rippled</code> servers in the consensus network are under heavy load, they queue the transactions with the lowest transaction cost for later ledgers. Each consensus round prioritizes transactions from the queue with the largest transaction cost (<code>Fee</code> value), and includes as many transactions as the consensus network can process. If the transaction queue is full, transactions drop from the queue entirely, starting with the ones that have the lowest transaction cost.</p>
|
||||
<p>While the consensus network is under heavy load, legitimate users can pay a higher transaction cost to make sure their transactions get processed. The situation persists until the entire backlog of cheap transactions is processed or discarded.</p>
|
||||
<p>A transaction remains in the queue until one of the following happens:</p>
|
||||
<ul>
|
||||
<li>It gets applied to a validated ledger (regardless of success or failure)</li>
|
||||
<li>It becomes invalid (for example, the <a href="reference-transaction-format.html#lastledgersequence"><code>LastLedgerSequence</code></a> causes it to expire)</li>
|
||||
<li>It gets dropped because there are too many transactions in the queue with a higher transaction cost.</li>
|
||||
</ul>
|
||||
<h2 id="multisign">MultiSign</h2>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Amendment ID</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>4C97EBA926031A7CF7D7B36FDE3ED66DDA5421192D63DE53FFB46E43B9DC8373</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<p>Introduces simple <a href="reference-transaction-format.html#multi-signing">multi-signing</a> as a way to authorize transactions. Creates the <a href="reference-ledger-format.html#signerlist"><code>SignerList</code> ledger node type</a> and the <a href="reference-transaction-format.html#signerlistset"><code>SignerListSet</code> transaction type</a>. Adds the optional <code>Signers</code> field to all transaction types. Modifies some transaction result codes.</p>
|
||||
<p>This amendment allows addresses to have a list of signers who can authorize transactions from that address in a multi-signature. The list has a quorum and 1 to 8 weighted signers. This allows various configurations, such as "any 3-of-5" or "signature from A plus any other two signatures."</p>
|
||||
<p>Signers can be funded or unfunded addresses. Funded addresses in a signer list can sign using a regular key (if defined) or master key (unless disabled). Unfunded addresses can sign with a master key. Multi-signed transactions have the same permissions as transactions signed with a regular key.</p>
|
||||
<p>An address with a SignerList can disable the master key even if a regular key is not defined. An address with a SignerList can also remove a regular key even if the master key is disabled. Therefore, the <code>tecMASTER_DISABLED</code> transaction result code is renamed <code>tecNO_ALTERNATIVE_KEY</code>. The <code>tecNO_REGULAR_KEY</code> transaction result is retired and replaced with <code>tecNO_ALTERNATIVE_KEY</code>. Additionally, this amendment adds the following new <a href="reference-transaction-format.html#result-categories">transaction result codes</a>:</p>
|
||||
<ul>
|
||||
<li><code>temBAD_SIGNER</code></li>
|
||||
<li><code>temBAD_QUORUM</code></li>
|
||||
<li><code>temBAD_WEIGHT</code></li>
|
||||
<li><code>tefBAD_SIGNATURE</code></li>
|
||||
<li><code>tefBAD_QUORUM</code></li>
|
||||
<li><code>tefNOT_MULTI_SIGNING</code></li>
|
||||
<li><code>tefBAD_AUTH_MASTER</code></li>
|
||||
</ul>
|
||||
<h2 id="suspay">SusPay</h2>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Amendment ID</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>DA1BD556B42D85EA9C84066D028D355B52416734D3283F85E216EA5DA6DB7E13</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<p>Provides "Suspended Payments" for XRP as a means of escrow within the Ripple Consensus Ledger. Creates the <code>SuspendedPayment</code> ledger node type and the new transaction types <code>SuspendedPaymentCreate</code>, <code>SuspendedPaymentFinish</code>, and <code>SuspendedPaymentCancel</code>.</p>
|
||||
<p>This amendment is still in development. The current version is enabled on the <a href="https://ripple.com/build/ripple-test-net/">Ripple Test Net</a>.</p>
|
||||
<h2 id="trustsetauth">TrustSetAuth</h2>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Amendment ID</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>6781F8368C4771B83E8B821D88F580202BCB4228075297B19E4FDC5233F1EFDC</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<p>Allows pre-authorization of accounting relationships (zero-balance trust lines) when using <a href="tutorial-gateway-guide.html#authorized-accounts">Authorized Accounts</a>.</p>
|
||||
<p>With this amendment enabled, a <code>TrustSet</code> transaction with <a href="reference-transaction-format.html#trustset-flags"><code>tfSetfAuth</code> enabled</a> can create a new <a href="reference-ledger-format.html#ripplestate"><code>RippleState</code> ledger node</a> even if it keeps all the other values of the <code>RippleState</code> node in their default state. The new <code>RippleState</code> node has the <a href="reference-ledger-format.html#ripplestate-flags"><code>lsfLowAuth</code> or <code>lsfHighAuth</code> flag</a> enabled accordingly. The sender of the transaction must have <a href="reference-ledger-format.html#accountroot-flags"><code>lsfRequireAuth</code> enabled</a>.</p>
|
||||
<h2 id="tickets">Tickets</h2>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Amendment ID</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>C1B8D934087225F509BEB5A8EC24447854713EE447D277F69545ABFA0E0FD490</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<p>Introduces Tickets as a way to reserve a transaction sequence number for later execution. Creates the <code>Ticket</code> ledger node type and the transaction types <code>TicketCreate</code> and <code>TicketCancel</code>.</p>
|
||||
<p>This amendment is still in development.</p>
|
||||
</div>
|
||||
</main>
|
||||
</div>
|
||||
|
||||
<footer class="content-info" role="contentinfo">
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
|
||||
<section class="col-sm-3 widget nav_menu-3 widget_nav_menu">
|
||||
<h4>Resources<hr></h4>
|
||||
<ul id="menu-resources" class="menu">
|
||||
<li class="menu-insights"><a href="https://ripple.com/insights/">Insights</a></li>
|
||||
<li class="menu-press-center"><a href="https://ripple.com/press-center/">Press Center</a></li>
|
||||
<li class="menu-media-resources"><a href="https://ripple.com/media-resources/">Media Resources</a></li>
|
||||
<li class="menu-videos"><a href="https://ripple.com/videos/">Videos</a></li>
|
||||
<li class="menu-whitepapers-reports"><a href="https://ripple.com/whitepapers-reports/">Whitepapers & Reports</a></li>
|
||||
<li class="menu-xrp-portal"><a href="https://ripple.com/xrp-portal/">XRP Portal</a></li>
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
<section class="col-sm-3 widget nav_menu-5 widget_nav_menu">
|
||||
<h4>Regulators<hr></h4>
|
||||
<ul id="menu-compliance-regulatory-relations" class="menu"><li class="menu-compliance"><a href="https://ripple.com/compliance/">Compliance</a></li>
|
||||
<li class="menu-policy-framework"><a href="https://ripple.com/policy-framework/">Policy Framework</a></li>
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
<section class="col-sm-3 widget nav_menu-4 widget_nav_menu">
|
||||
<h4>Support<hr></h4>
|
||||
<ul id="menu-dev-footer-menu" class="menu">
|
||||
<li class="menu-contact-us"><a href="https://ripple.com/contact/">Contact Us</a></li>
|
||||
<li class="active menu-developer-center"><a href="https://ripple.com/build/">Developer Center</a></li>
|
||||
<li class="menu-knowledge-center"><a href="https://ripple.com/learn/">Knowledge Center</a></li>
|
||||
<li class="menu-ripple-forum"><a target="_blank" href="https://forum.ripple.com/">Ripple Forum</a></li>
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
<section class="col-sm-3 widget nav_menu-2 widget_nav_menu">
|
||||
<h4>About<hr></h4>
|
||||
<ul id="menu-company-footer" class="menu">
|
||||
<li class="menu-our-company"><a href="https://ripple.com/company/">Our Company</a></li>
|
||||
<li class="menu-careers"><a href="https://ripple.com/company/careers/">Careers</a></li>
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
<div class="col-sm-12 absolute_bottom_footer">
|
||||
<div class="col-sm-8">
|
||||
<span>© 2013-2015 Ripple Labs, Inc. All Rights Reserved.</span>
|
||||
<span><a href="https://ripple.com/terms-of-use/">Terms</a></span>
|
||||
<span><a href="https://ripple.com/privacy-policy/">Privacy</a></span>
|
||||
</div>
|
||||
</div><!-- /.absolute_bottom_footer -->
|
||||
|
||||
</div><!-- /.row -->
|
||||
</div><!-- /.container -->
|
||||
</footer>
|
||||
</body>
|
||||
</html>
|
||||
246
concept-fee-voting.html
Normal file
@@ -0,0 +1,246 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
|
||||
<meta name="viewport" content="width=device-width">
|
||||
|
||||
<title>Fee Voting - Ripple Developer Portal</title>
|
||||
|
||||
<!-- favicon -->
|
||||
<link rel="icon" href="favicon.ico" type="image/x-icon">
|
||||
<link rel="shortcut icon" href="favicon.ico" type="image/x-icon">
|
||||
|
||||
<!-- jQuery -->
|
||||
<script src="assets/vendor/jquery-1.11.1.min.js"></script>
|
||||
|
||||
<!-- Custom Stylesheets. ripple.css includes bootstrap, font stuff -->
|
||||
<link href="assets/css/ripple.css" rel="stylesheet" />
|
||||
<link href="assets/css/devportal.css" rel="stylesheet" />
|
||||
|
||||
<!-- Bootstrap JS -->
|
||||
<script src="assets/vendor/bootstrap.min.js"></script>
|
||||
|
||||
|
||||
<!-- syntax highlighting -->
|
||||
<link rel="stylesheet" href="assets/vendor/docco.min.css">
|
||||
<script src="assets/vendor/highlight.min.js"></script>
|
||||
|
||||
<!-- syntax selection js -->
|
||||
<script src="assets/js/multicodetab.js"></script>
|
||||
<script>
|
||||
$(document).ready(function() {
|
||||
$().multicode_tabs();
|
||||
hljs.initHighlighting();
|
||||
make_code_expandable();
|
||||
});
|
||||
</script>
|
||||
|
||||
<script src="assets/js/expandcode.js"></script>
|
||||
<script src="assets/js/fixsidebarscroll.js"></script>
|
||||
|
||||
</head>
|
||||
|
||||
<body class="page page-template page-template-template-dev-portal page-template-template-dev-portal-php sidebar-primary wpb-js-composer js-comp-ver-3.6.2 vc_responsive">
|
||||
<header role="banner" class="banner navbar navbar-default navbar-fixed-top initial_header">
|
||||
<div class="container">
|
||||
<div class="navbar-header">
|
||||
<a href="index.html" class="navbar-brand"><img src="assets/img/ripple-logo-color.png" class="logo"></a>
|
||||
</div><!-- /.navbar-header -->
|
||||
<div class="nav">
|
||||
<div class="draft-warning">DRAFT PAGE</div>
|
||||
</div><!-- /.nav -->
|
||||
|
||||
</div><!-- /.container -->
|
||||
|
||||
<div class="subnav dev_nav">
|
||||
<div class="container">
|
||||
<ul id="menu-dev-menu" class="menu">
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">References <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="reference-rippled.html">rippled</a></li>
|
||||
<li><a href="reference-transaction-format.html">Transaction Format</a></li>
|
||||
<li><a href="reference-ledger-format.html">Ledger Format</a></li>
|
||||
<li><a href="reference-rippleapi.html">RippleAPI</a></li>
|
||||
<li><a href="reference-data-api.html">Ripple Data API v2</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Tutorials <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="tutorial-rippleapi-beginners-guide.html">RippleAPI Beginners Guide</a></li>
|
||||
<li><a href="tutorial-rippled-setup.html">rippled Setup</a></li>
|
||||
<li><a href="tutorial-reliable-transaction-submission.html">Reliable Transaction Submission</a></li>
|
||||
<li><a href="tutorial-multisign.html">How to Multi-Sign</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Concepts <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="concept-paths.html">Paths</a></li>
|
||||
<li><a href="concept-fees.html">Fees (Disambiguation)</a></li>
|
||||
<li><a href="concept-transfer-fees.html">Transfer Fees</a></li>
|
||||
<li><a href="concept-transaction-cost.html">Transaction Cost</a></li>
|
||||
<li><a href="concept-fee-voting.html">Fee Voting</a></li>
|
||||
<li><a href="concept-reserves.html">Reserves</a></li>
|
||||
<li><a href="concept-freeze.html">Freeze</a></li>
|
||||
<li><a href="concept-amendments.html">Amendments</a></li>
|
||||
<li><a href="concept-stand-alone-mode.html">Stand-Alone Mode</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Best Practices <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="concept-issuing-and-operational-addresses.html">Issuing and Operational Addresses</a></li>
|
||||
<li><a href="tutorial-gateway-guide.html">Gateway Guide</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">API Tools <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="ripple-api-tool.html">WebSocket API Tool</a></li>
|
||||
<li><a href="data-api-v2-tool.html">Data API v2 Tool</a></li>
|
||||
<li><a href="tool-jsonrpc.html">rippled JSON-RPC Tool</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Resources <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="https://forum.ripple.com/viewforum.php?f=2">Forums</a></li>
|
||||
<li><a href="https://www.bountysource.com/teams/ripple/bounties">Bounties</a></li>
|
||||
<li><a href="https://ripplelabs.atlassian.net/">Bug Tracking</a></li>
|
||||
<li><a href="https://ripple.com/category/dev-blog/">Dev Blog</a></li>
|
||||
<li><a href="https://ripple.com/press-releases/">Press Center</a></li>
|
||||
<li><a href="https://ripple.com/brand-guidelines/">Brand Guidelines</a></li>
|
||||
</ul>
|
||||
<li><a href="https://github.com/ripple/ripple-dev-portal" title="GitHub">Site Source</a></li>
|
||||
</ul><!-- /#dev-menu -->
|
||||
</div><!-- /.subnav .container -->
|
||||
</div><!-- /.subnav -->
|
||||
</header>
|
||||
|
||||
|
||||
<div class="wrap container" role="document">
|
||||
<aside class="sidebar" role="complementary">
|
||||
<div class="dev_nav_wrapper">
|
||||
<div id="cont">
|
||||
<ul class="dev_nav_sidebar">
|
||||
<li class="level-1"><a href="index.html">Category: Concepts</a></li>
|
||||
<li class="level-2"><a href="concept-paths.html">Paths</a></li>
|
||||
<li class="level-2"><a href="concept-fees.html">Fees (Disambiguation)</a></li>
|
||||
<li class="level-2"><a href="concept-transfer-fees.html">Transfer Fees</a></li>
|
||||
<li class="level-2"><a href="concept-transaction-cost.html">Transaction Cost</a></li>
|
||||
<li class="level-2"><a href="concept-fee-voting.html">Fee Voting</a></li>
|
||||
<li class="level-2"><a href="concept-reserves.html">Reserves</a></li>
|
||||
<li class="level-2"><a href="concept-freeze.html">Freeze</a></li>
|
||||
<li class="level-2"><a href="concept-amendments.html">Amendments</a></li>
|
||||
<li class="level-2"><a href="concept-stand-alone-mode.html">Stand-Alone Mode</a></li>
|
||||
</ul>
|
||||
<hr />
|
||||
<h5>In this page:</h5>
|
||||
</div>
|
||||
<script type="text/javascript" src="assets/js/jquery.gensidebar.js"></script>
|
||||
</div>
|
||||
</aside>
|
||||
<main class="main" role="main">
|
||||
<div class='content'>
|
||||
<h1 id="fee-voting">Fee Voting</h1>
|
||||
<p>Validators can vote for changes to basic <a href="concept-transaction-cost.html">transaction cost</a> as well as <a href="concept-reserves.html">reserve requirements</a>. If the preferences in a validator's configuration are different than the network's current settings, the validator expresses its preferences to the network periodically. If a quorum of validators agrees on a change, they can apply a change that takes effect thereafter. Validators may do this for various reasons, especially to reflect long-term changes in the value of XRP.</p>
|
||||
<p>Operators of <a href="tutorial-rippled-setup.html#running-a-validator"><code>rippled</code> validators</a> can set their preferences for the transaction cost and reserve requirements in the <code>[voting]</code> stanza of the <code>rippled.cfg</code> file. <strong>Caution:</strong> insufficient requirements could expose the Ripple peer-to-peer network to denial-of-service attacks. The parameters you can set are as follows:</p>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Parameter</th>
|
||||
<th>Description</th>
|
||||
<th>Recommended Value</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>reference_fee</td>
|
||||
<td>Amount of XRP, in <em>drops</em>, that must be destroyed to send the reference transaction, the cheapest possible transaction. (1 XRP = 1 million drops.) The actual transaction cost is a multiple of this value, scaled dynamically based on the load of individual servers.</td>
|
||||
<td><code>10</code> (0.00001 XRP)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>account_reserve</td>
|
||||
<td>Minimum amount of XRP, in <em>drops</em>, that an account must have on reserve. This is the smallest amount that can be sent to fund a new account in the ledger.</td>
|
||||
<td><code>20000000</code> (20 XRP)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>owner_reserve</td>
|
||||
<td>Additional amount of XRP, in <em>drops</em>, that an account must have on reserve for <em>each</em> object it owns in the ledger.</td>
|
||||
<td><code>5000000</code> (5 XRP)</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<h3 id="voting-process">Voting Process</h3>
|
||||
<p>Every 256th ledger is called a "flag" ledger. (A flag ledger is defined such that the <code>ledger_index</code> <a href="https://en.wikipedia.org/wiki/Modulo_operation">modulo</a> <code>256</code> is equal to <code>0</code>.) In the ledger immediately before the flag ledger, each validator whose account reserve or transaction cost preferences are different than the current network setting distributes a "vote" message alongside its ledger validation, indicating the values that validator prefers.</p>
|
||||
<p>In the flag ledger itself, nothing happens, but validators receive and take note of the votes from other validators they trust. </p>
|
||||
<p>After counting the votes of other validators, each validator attempts to compromise between its own preferences and the preferences of a majority of validators it trusts. (For example, if one validator wants to raise the minimum transaction cost from 10 to 100, but most validators only want to raise it from 10 to 20, the one validator settles on the change to raise the cost to 20. However, the one validator never settles on a value lower than 10 or higher than 100.) If a compromise is possible, the validator inserts a <a href="reference-transaction-format.html#setfee">SetFee pseudo-transaction</a> into its proposal for the ledger following the flag ledger. Other validators who want the same change insert an identical SetFee pseudo-transaction into their proposals for the same ledger. (Validators whose preferences match the existing network settings do nothing.) If a SetFee psuedo-transaction survives the consensus process to be included in a validated ledger, then the new transaction cost and reserve settings denoted by the SetFee pseudo-transaction take effect starting with the following ledger.</p>
|
||||
<p>In short:</p>
|
||||
<ul>
|
||||
<li><strong>Flag ledger -1</strong>: Validators submit votes.</li>
|
||||
<li><strong>Flag ledger</strong>: Validators tally votes and decide what SetFee to include, if any.</li>
|
||||
<li><strong>Flag ledger +1</strong>: Validators insert SetFee pseudo-transaction into their proposed ledgers.</li>
|
||||
<li><strong>Flag ledger +2</strong>: New settings take effect, if a SetFee psuedotransaction achieved consensus.</li>
|
||||
</ul>
|
||||
</div>
|
||||
</main>
|
||||
</div>
|
||||
|
||||
<footer class="content-info" role="contentinfo">
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
|
||||
<section class="col-sm-3 widget nav_menu-3 widget_nav_menu">
|
||||
<h4>Resources<hr></h4>
|
||||
<ul id="menu-resources" class="menu">
|
||||
<li class="menu-insights"><a href="https://ripple.com/insights/">Insights</a></li>
|
||||
<li class="menu-press-center"><a href="https://ripple.com/press-center/">Press Center</a></li>
|
||||
<li class="menu-media-resources"><a href="https://ripple.com/media-resources/">Media Resources</a></li>
|
||||
<li class="menu-videos"><a href="https://ripple.com/videos/">Videos</a></li>
|
||||
<li class="menu-whitepapers-reports"><a href="https://ripple.com/whitepapers-reports/">Whitepapers & Reports</a></li>
|
||||
<li class="menu-xrp-portal"><a href="https://ripple.com/xrp-portal/">XRP Portal</a></li>
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
<section class="col-sm-3 widget nav_menu-5 widget_nav_menu">
|
||||
<h4>Regulators<hr></h4>
|
||||
<ul id="menu-compliance-regulatory-relations" class="menu"><li class="menu-compliance"><a href="https://ripple.com/compliance/">Compliance</a></li>
|
||||
<li class="menu-policy-framework"><a href="https://ripple.com/policy-framework/">Policy Framework</a></li>
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
<section class="col-sm-3 widget nav_menu-4 widget_nav_menu">
|
||||
<h4>Support<hr></h4>
|
||||
<ul id="menu-dev-footer-menu" class="menu">
|
||||
<li class="menu-contact-us"><a href="https://ripple.com/contact/">Contact Us</a></li>
|
||||
<li class="active menu-developer-center"><a href="https://ripple.com/build/">Developer Center</a></li>
|
||||
<li class="menu-knowledge-center"><a href="https://ripple.com/learn/">Knowledge Center</a></li>
|
||||
<li class="menu-ripple-forum"><a target="_blank" href="https://forum.ripple.com/">Ripple Forum</a></li>
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
<section class="col-sm-3 widget nav_menu-2 widget_nav_menu">
|
||||
<h4>About<hr></h4>
|
||||
<ul id="menu-company-footer" class="menu">
|
||||
<li class="menu-our-company"><a href="https://ripple.com/company/">Our Company</a></li>
|
||||
<li class="menu-careers"><a href="https://ripple.com/company/careers/">Careers</a></li>
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
<div class="col-sm-12 absolute_bottom_footer">
|
||||
<div class="col-sm-8">
|
||||
<span>© 2013-2015 Ripple Labs, Inc. All Rights Reserved.</span>
|
||||
<span><a href="https://ripple.com/terms-of-use/">Terms</a></span>
|
||||
<span><a href="https://ripple.com/privacy-policy/">Privacy</a></span>
|
||||
</div>
|
||||
</div><!-- /.absolute_bottom_footer -->
|
||||
|
||||
</div><!-- /.row -->
|
||||
</div><!-- /.container -->
|
||||
</footer>
|
||||
</body>
|
||||
</html>
|
||||
219
concept-fees.html
Normal file
@@ -0,0 +1,219 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
|
||||
<meta name="viewport" content="width=device-width">
|
||||
|
||||
<title>Fees (Disambiguation) - Ripple Developer Portal</title>
|
||||
|
||||
<!-- favicon -->
|
||||
<link rel="icon" href="favicon.ico" type="image/x-icon">
|
||||
<link rel="shortcut icon" href="favicon.ico" type="image/x-icon">
|
||||
|
||||
<!-- jQuery -->
|
||||
<script src="assets/vendor/jquery-1.11.1.min.js"></script>
|
||||
|
||||
<!-- Custom Stylesheets. ripple.css includes bootstrap, font stuff -->
|
||||
<link href="assets/css/ripple.css" rel="stylesheet" />
|
||||
<link href="assets/css/devportal.css" rel="stylesheet" />
|
||||
|
||||
<!-- Bootstrap JS -->
|
||||
<script src="assets/vendor/bootstrap.min.js"></script>
|
||||
|
||||
|
||||
<!-- syntax highlighting -->
|
||||
<link rel="stylesheet" href="assets/vendor/docco.min.css">
|
||||
<script src="assets/vendor/highlight.min.js"></script>
|
||||
|
||||
<!-- syntax selection js -->
|
||||
<script src="assets/js/multicodetab.js"></script>
|
||||
<script>
|
||||
$(document).ready(function() {
|
||||
$().multicode_tabs();
|
||||
hljs.initHighlighting();
|
||||
make_code_expandable();
|
||||
});
|
||||
</script>
|
||||
|
||||
<script src="assets/js/expandcode.js"></script>
|
||||
<script src="assets/js/fixsidebarscroll.js"></script>
|
||||
|
||||
</head>
|
||||
|
||||
<body class="page page-template page-template-template-dev-portal page-template-template-dev-portal-php sidebar-primary wpb-js-composer js-comp-ver-3.6.2 vc_responsive">
|
||||
<header role="banner" class="banner navbar navbar-default navbar-fixed-top initial_header">
|
||||
<div class="container">
|
||||
<div class="navbar-header">
|
||||
<a href="index.html" class="navbar-brand"><img src="assets/img/ripple-logo-color.png" class="logo"></a>
|
||||
</div><!-- /.navbar-header -->
|
||||
<div class="nav">
|
||||
<div class="draft-warning">DRAFT PAGE</div>
|
||||
</div><!-- /.nav -->
|
||||
|
||||
</div><!-- /.container -->
|
||||
|
||||
<div class="subnav dev_nav">
|
||||
<div class="container">
|
||||
<ul id="menu-dev-menu" class="menu">
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">References <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="reference-rippled.html">rippled</a></li>
|
||||
<li><a href="reference-transaction-format.html">Transaction Format</a></li>
|
||||
<li><a href="reference-ledger-format.html">Ledger Format</a></li>
|
||||
<li><a href="reference-rippleapi.html">RippleAPI</a></li>
|
||||
<li><a href="reference-data-api.html">Ripple Data API v2</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Tutorials <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="tutorial-rippleapi-beginners-guide.html">RippleAPI Beginners Guide</a></li>
|
||||
<li><a href="tutorial-rippled-setup.html">rippled Setup</a></li>
|
||||
<li><a href="tutorial-reliable-transaction-submission.html">Reliable Transaction Submission</a></li>
|
||||
<li><a href="tutorial-multisign.html">How to Multi-Sign</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Concepts <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="concept-paths.html">Paths</a></li>
|
||||
<li><a href="concept-fees.html">Fees (Disambiguation)</a></li>
|
||||
<li><a href="concept-transfer-fees.html">Transfer Fees</a></li>
|
||||
<li><a href="concept-transaction-cost.html">Transaction Cost</a></li>
|
||||
<li><a href="concept-fee-voting.html">Fee Voting</a></li>
|
||||
<li><a href="concept-reserves.html">Reserves</a></li>
|
||||
<li><a href="concept-freeze.html">Freeze</a></li>
|
||||
<li><a href="concept-amendments.html">Amendments</a></li>
|
||||
<li><a href="concept-stand-alone-mode.html">Stand-Alone Mode</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Best Practices <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="concept-issuing-and-operational-addresses.html">Issuing and Operational Addresses</a></li>
|
||||
<li><a href="tutorial-gateway-guide.html">Gateway Guide</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">API Tools <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="ripple-api-tool.html">WebSocket API Tool</a></li>
|
||||
<li><a href="data-api-v2-tool.html">Data API v2 Tool</a></li>
|
||||
<li><a href="tool-jsonrpc.html">rippled JSON-RPC Tool</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Resources <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="https://forum.ripple.com/viewforum.php?f=2">Forums</a></li>
|
||||
<li><a href="https://www.bountysource.com/teams/ripple/bounties">Bounties</a></li>
|
||||
<li><a href="https://ripplelabs.atlassian.net/">Bug Tracking</a></li>
|
||||
<li><a href="https://ripple.com/category/dev-blog/">Dev Blog</a></li>
|
||||
<li><a href="https://ripple.com/press-releases/">Press Center</a></li>
|
||||
<li><a href="https://ripple.com/brand-guidelines/">Brand Guidelines</a></li>
|
||||
</ul>
|
||||
<li><a href="https://github.com/ripple/ripple-dev-portal" title="GitHub">Site Source</a></li>
|
||||
</ul><!-- /#dev-menu -->
|
||||
</div><!-- /.subnav .container -->
|
||||
</div><!-- /.subnav -->
|
||||
</header>
|
||||
|
||||
|
||||
<div class="wrap container" role="document">
|
||||
<aside class="sidebar" role="complementary">
|
||||
<div class="dev_nav_wrapper">
|
||||
<div id="cont">
|
||||
<ul class="dev_nav_sidebar">
|
||||
<li class="level-1"><a href="index.html">Category: Concepts</a></li>
|
||||
<li class="level-2"><a href="concept-paths.html">Paths</a></li>
|
||||
<li class="level-2"><a href="concept-fees.html">Fees (Disambiguation)</a></li>
|
||||
<li class="level-2"><a href="concept-transfer-fees.html">Transfer Fees</a></li>
|
||||
<li class="level-2"><a href="concept-transaction-cost.html">Transaction Cost</a></li>
|
||||
<li class="level-2"><a href="concept-fee-voting.html">Fee Voting</a></li>
|
||||
<li class="level-2"><a href="concept-reserves.html">Reserves</a></li>
|
||||
<li class="level-2"><a href="concept-freeze.html">Freeze</a></li>
|
||||
<li class="level-2"><a href="concept-amendments.html">Amendments</a></li>
|
||||
<li class="level-2"><a href="concept-stand-alone-mode.html">Stand-Alone Mode</a></li>
|
||||
</ul>
|
||||
<hr />
|
||||
<h5>In this page:</h5>
|
||||
</div>
|
||||
<script type="text/javascript" src="assets/js/jquery.gensidebar.js"></script>
|
||||
</div>
|
||||
</aside>
|
||||
<main class="main" role="main">
|
||||
<div class='content'>
|
||||
<h1 id="fees-disambiguation">Fees (Disambiguation)</h1>
|
||||
<p>The Ripple Consensus Ledger is a decentralized ledger, secured by cryptography and operated by a distributed peer-to-peer network of servers. This means that no one party, not even Ripple, can require a fee for access to the network.</p>
|
||||
<p>However, the rules of the Ripple Consensus Ledger include several types of fees, including neutral fees which protect the ledger against abuse. These neutral fees are not paid to anyone. There are also several optional ways that users can collect fees from each other, both inside and outside the Ripple Consensus Ledger.</p>
|
||||
<h2 id="in-the-ledger">In the Ledger</h2>
|
||||
<h3 id="neutral-fees">Neutral Fees</h3>
|
||||
<p>The <em><strong>transaction cost</strong></em> (sometimes called the transaction fee) is a miniscule amount of XRP destroyed in order to send a transaction. This cost scales with the load of the network, which protects the peer-to-peer network from spam. See <a href="concept-transaction-cost.html">Transaction Cost</a> for more information.</p>
|
||||
<p>The <em><strong>account reserve</strong></em> is a minimum amount of XRP that an account must possess. It scales with the number of objects the account owns in the ledger. This disincentivizes users from increasing the size of the ledger carelessly or maliciously. See <a href="concept-reserves.html">Reserves</a> for more information.</p>
|
||||
<h3 id="optional-fees">Optional Fees</h3>
|
||||
<p><em><strong>Transfer fees</strong></em> are optional percentage fees that gateways can charge to transfer the currencies they issue to other accounts within the Ripple Consensus Ledger. See <a href="concept-transfer-fees.html">Transfer Fees</a> for more information.</p>
|
||||
<p><em><strong>Trust line quality</strong></em> is a setting that allows an account to value balances on a trust line at higher or lower than face value. This can lead to situations that are similar to charging a fee. Trust line quality does not apply to XRP, which is not tied to a trust line.</p>
|
||||
<h2 id="outside-the-ledger">Outside the Ledger</h2>
|
||||
<p>Although the fees described above are the only fees built into the Ripple Consensus Ledger, people can still invent ways to charge fees associated with the ledger. For example, gateways commonly charge their customers to send money into and out of the Ripple Consensus Ledger.</p>
|
||||
<p>Many other fees are also possible. Businesses might charge for access to a client application, maintenance of non-Ripple accounts, exchange services (especially when buying XRP on a private market instead of directly within the Ripple Consensus Ledger) and any number of other services. Always be aware of the fee schedule before doing business with any gateway or other financial institution.</p>
|
||||
</div>
|
||||
</main>
|
||||
</div>
|
||||
|
||||
<footer class="content-info" role="contentinfo">
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
|
||||
<section class="col-sm-3 widget nav_menu-3 widget_nav_menu">
|
||||
<h4>Resources<hr></h4>
|
||||
<ul id="menu-resources" class="menu">
|
||||
<li class="menu-insights"><a href="https://ripple.com/insights/">Insights</a></li>
|
||||
<li class="menu-press-center"><a href="https://ripple.com/press-center/">Press Center</a></li>
|
||||
<li class="menu-media-resources"><a href="https://ripple.com/media-resources/">Media Resources</a></li>
|
||||
<li class="menu-videos"><a href="https://ripple.com/videos/">Videos</a></li>
|
||||
<li class="menu-whitepapers-reports"><a href="https://ripple.com/whitepapers-reports/">Whitepapers & Reports</a></li>
|
||||
<li class="menu-xrp-portal"><a href="https://ripple.com/xrp-portal/">XRP Portal</a></li>
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
<section class="col-sm-3 widget nav_menu-5 widget_nav_menu">
|
||||
<h4>Regulators<hr></h4>
|
||||
<ul id="menu-compliance-regulatory-relations" class="menu"><li class="menu-compliance"><a href="https://ripple.com/compliance/">Compliance</a></li>
|
||||
<li class="menu-policy-framework"><a href="https://ripple.com/policy-framework/">Policy Framework</a></li>
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
<section class="col-sm-3 widget nav_menu-4 widget_nav_menu">
|
||||
<h4>Support<hr></h4>
|
||||
<ul id="menu-dev-footer-menu" class="menu">
|
||||
<li class="menu-contact-us"><a href="https://ripple.com/contact/">Contact Us</a></li>
|
||||
<li class="active menu-developer-center"><a href="https://ripple.com/build/">Developer Center</a></li>
|
||||
<li class="menu-knowledge-center"><a href="https://ripple.com/learn/">Knowledge Center</a></li>
|
||||
<li class="menu-ripple-forum"><a target="_blank" href="https://forum.ripple.com/">Ripple Forum</a></li>
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
<section class="col-sm-3 widget nav_menu-2 widget_nav_menu">
|
||||
<h4>About<hr></h4>
|
||||
<ul id="menu-company-footer" class="menu">
|
||||
<li class="menu-our-company"><a href="https://ripple.com/company/">Our Company</a></li>
|
||||
<li class="menu-careers"><a href="https://ripple.com/company/careers/">Careers</a></li>
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
<div class="col-sm-12 absolute_bottom_footer">
|
||||
<div class="col-sm-8">
|
||||
<span>© 2013-2015 Ripple Labs, Inc. All Rights Reserved.</span>
|
||||
<span><a href="https://ripple.com/terms-of-use/">Terms</a></span>
|
||||
<span><a href="https://ripple.com/privacy-policy/">Privacy</a></span>
|
||||
</div>
|
||||
</div><!-- /.absolute_bottom_footer -->
|
||||
|
||||
</div><!-- /.row -->
|
||||
</div><!-- /.container -->
|
||||
</footer>
|
||||
</body>
|
||||
</html>
|
||||
890
concept-freeze.html
Normal file
@@ -0,0 +1,890 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
|
||||
<meta name="viewport" content="width=device-width">
|
||||
|
||||
<title>Freeze - Ripple Developer Portal</title>
|
||||
|
||||
<!-- favicon -->
|
||||
<link rel="icon" href="favicon.ico" type="image/x-icon">
|
||||
<link rel="shortcut icon" href="favicon.ico" type="image/x-icon">
|
||||
|
||||
<!-- jQuery -->
|
||||
<script src="assets/vendor/jquery-1.11.1.min.js"></script>
|
||||
|
||||
<!-- Custom Stylesheets. ripple.css includes bootstrap, font stuff -->
|
||||
<link href="assets/css/ripple.css" rel="stylesheet" />
|
||||
<link href="assets/css/devportal.css" rel="stylesheet" />
|
||||
|
||||
<!-- Bootstrap JS -->
|
||||
<script src="assets/vendor/bootstrap.min.js"></script>
|
||||
|
||||
|
||||
<!-- syntax highlighting -->
|
||||
<link rel="stylesheet" href="assets/vendor/docco.min.css">
|
||||
<script src="assets/vendor/highlight.min.js"></script>
|
||||
|
||||
<!-- syntax selection js -->
|
||||
<script src="assets/js/multicodetab.js"></script>
|
||||
<script>
|
||||
$(document).ready(function() {
|
||||
$().multicode_tabs();
|
||||
hljs.initHighlighting();
|
||||
make_code_expandable();
|
||||
});
|
||||
</script>
|
||||
|
||||
<script src="assets/js/expandcode.js"></script>
|
||||
<script src="assets/js/fixsidebarscroll.js"></script>
|
||||
|
||||
</head>
|
||||
|
||||
<body class="page page-template page-template-template-dev-portal page-template-template-dev-portal-php sidebar-primary wpb-js-composer js-comp-ver-3.6.2 vc_responsive">
|
||||
<header role="banner" class="banner navbar navbar-default navbar-fixed-top initial_header">
|
||||
<div class="container">
|
||||
<div class="navbar-header">
|
||||
<a href="index.html" class="navbar-brand"><img src="assets/img/ripple-logo-color.png" class="logo"></a>
|
||||
</div><!-- /.navbar-header -->
|
||||
<div class="nav">
|
||||
<div class="draft-warning">DRAFT PAGE</div>
|
||||
</div><!-- /.nav -->
|
||||
|
||||
</div><!-- /.container -->
|
||||
|
||||
<div class="subnav dev_nav">
|
||||
<div class="container">
|
||||
<ul id="menu-dev-menu" class="menu">
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">References <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="reference-rippled.html">rippled</a></li>
|
||||
<li><a href="reference-transaction-format.html">Transaction Format</a></li>
|
||||
<li><a href="reference-ledger-format.html">Ledger Format</a></li>
|
||||
<li><a href="reference-rippleapi.html">RippleAPI</a></li>
|
||||
<li><a href="reference-data-api.html">Ripple Data API v2</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Tutorials <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="tutorial-rippleapi-beginners-guide.html">RippleAPI Beginners Guide</a></li>
|
||||
<li><a href="tutorial-rippled-setup.html">rippled Setup</a></li>
|
||||
<li><a href="tutorial-reliable-transaction-submission.html">Reliable Transaction Submission</a></li>
|
||||
<li><a href="tutorial-multisign.html">How to Multi-Sign</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Concepts <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="concept-paths.html">Paths</a></li>
|
||||
<li><a href="concept-fees.html">Fees (Disambiguation)</a></li>
|
||||
<li><a href="concept-transfer-fees.html">Transfer Fees</a></li>
|
||||
<li><a href="concept-transaction-cost.html">Transaction Cost</a></li>
|
||||
<li><a href="concept-fee-voting.html">Fee Voting</a></li>
|
||||
<li><a href="concept-reserves.html">Reserves</a></li>
|
||||
<li><a href="concept-freeze.html">Freeze</a></li>
|
||||
<li><a href="concept-amendments.html">Amendments</a></li>
|
||||
<li><a href="concept-stand-alone-mode.html">Stand-Alone Mode</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Best Practices <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="concept-issuing-and-operational-addresses.html">Issuing and Operational Addresses</a></li>
|
||||
<li><a href="tutorial-gateway-guide.html">Gateway Guide</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">API Tools <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="ripple-api-tool.html">WebSocket API Tool</a></li>
|
||||
<li><a href="data-api-v2-tool.html">Data API v2 Tool</a></li>
|
||||
<li><a href="tool-jsonrpc.html">rippled JSON-RPC Tool</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Resources <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="https://forum.ripple.com/viewforum.php?f=2">Forums</a></li>
|
||||
<li><a href="https://www.bountysource.com/teams/ripple/bounties">Bounties</a></li>
|
||||
<li><a href="https://ripplelabs.atlassian.net/">Bug Tracking</a></li>
|
||||
<li><a href="https://ripple.com/category/dev-blog/">Dev Blog</a></li>
|
||||
<li><a href="https://ripple.com/press-releases/">Press Center</a></li>
|
||||
<li><a href="https://ripple.com/brand-guidelines/">Brand Guidelines</a></li>
|
||||
</ul>
|
||||
<li><a href="https://github.com/ripple/ripple-dev-portal" title="GitHub">Site Source</a></li>
|
||||
</ul><!-- /#dev-menu -->
|
||||
</div><!-- /.subnav .container -->
|
||||
</div><!-- /.subnav -->
|
||||
</header>
|
||||
|
||||
|
||||
<div class="wrap container" role="document">
|
||||
<aside class="sidebar" role="complementary">
|
||||
<div class="dev_nav_wrapper">
|
||||
<div id="cont">
|
||||
<ul class="dev_nav_sidebar">
|
||||
<li class="level-1"><a href="index.html">Category: Concepts</a></li>
|
||||
<li class="level-2"><a href="concept-paths.html">Paths</a></li>
|
||||
<li class="level-2"><a href="concept-fees.html">Fees (Disambiguation)</a></li>
|
||||
<li class="level-2"><a href="concept-transfer-fees.html">Transfer Fees</a></li>
|
||||
<li class="level-2"><a href="concept-transaction-cost.html">Transaction Cost</a></li>
|
||||
<li class="level-2"><a href="concept-fee-voting.html">Fee Voting</a></li>
|
||||
<li class="level-2"><a href="concept-reserves.html">Reserves</a></li>
|
||||
<li class="level-2"><a href="concept-freeze.html">Freeze</a></li>
|
||||
<li class="level-2"><a href="concept-amendments.html">Amendments</a></li>
|
||||
<li class="level-2"><a href="concept-stand-alone-mode.html">Stand-Alone Mode</a></li>
|
||||
</ul>
|
||||
<hr />
|
||||
<h5>In this page:</h5>
|
||||
</div>
|
||||
<script type="text/javascript" src="assets/js/jquery.gensidebar.js"></script>
|
||||
</div>
|
||||
</aside>
|
||||
<main class="main" role="main">
|
||||
<div class='content'>
|
||||
<h1 id="freeze-features">Freeze Features</h1>
|
||||
<p>The Ripple Consensus Ledger gives accounts the ability to freeze non-XRP balances, which can be useful to comply with regulatory requirements, or while investigating suspicious activity. There are three settings related to freezes:</p>
|
||||
<ul>
|
||||
<li><a href="#individual-freeze"><strong>Individual Freeze</strong></a> - Freeze one counterparty.</li>
|
||||
<li><a href="#global-freeze"><strong>Global Freeze</strong></a> - Freeze all counterparties.</li>
|
||||
<li><a href="#no-freeze"><strong>No Freeze</strong></a> - Permanently give up the ability to freeze individual counterparties, as well as the ability to end a global freeze.</li>
|
||||
</ul>
|
||||
<p>Because no party has a privileged place in the Ripple Consensus Ledger, the freeze feature cannot prevent a counterparty from conducting transactions in XRP or funds issued by other counterparties. No one can freeze XRP.</p>
|
||||
<p>All freeze settings can be enacted regardless of whether the balance(s) to be frozen are positive or negative. Either the currency issuer or the currency holder can freeze a trust line; however, the effect of a currency holder freezing an issuer is minimal.</p>
|
||||
<h2 id="individual-freeze">Individual Freeze</h2>
|
||||
<p>The <strong>Individual Freeze</strong> feature is a setting on a trust line. When an issuing account enables the Individual Freeze setting, the following rules apply:</p>
|
||||
<ul>
|
||||
<li>Payments can still occur directly between the two parties of the frozen trust line.</li>
|
||||
<li>The counterparty of that trust line can no longer decrease its balance on the frozen trust line, except in direct payments to the issuer. The counterparty can only send the frozen issuances directly to the issuer.</li>
|
||||
<li>The counterparty can still receive payments from others on the frozen trust line.</li>
|
||||
<li>The counterparty's offers to sell the currency issued on the frozen trust line are <a href="reference-transaction-format.html#lifecycle-of-an-offer">considered unfunded</a>.</li>
|
||||
</ul>
|
||||
<p>A gateway can freeze the trust line linking it to a counterparty if that counterparty shows suspicious activity or violates the gateway's terms of use. The gateway should also freeze the counterparty in any other systems the gateway operates that are connected to the Ripple Consensus Ledger. (Otherwise, an account might still be able to engage in undesired activity by sending payments through the gateway.)</p>
|
||||
<p>An individual account can freeze its trust line to a gateway. This has no effect on transactions between the gateway and other users. It does, however, prevent other accounts, including <a href="concept-issuing-and-operational-addresses.html">operational addresses</a>, from sending that gateway's issued currency to the individual account. This type of individual freeze has no effect on offers.</p>
|
||||
<p>The Individual Freeze applies to a single currency only. In order to freeze multiple currencies with a particular counterparty, the account must enable Individual Freeze on the trust lines for each currency individually.</p>
|
||||
<p>An account cannot enable the Individual Freeze setting if it has previously enabled the <a href="#no-freeze">No Freeze</a> setting.</p>
|
||||
<h2 id="global-freeze">Global Freeze</h2>
|
||||
<p>The <strong>Global Freeze</strong> feature is a setting on an account. When an issuing account enables the Global Freeze feature, the following rules apply:</p>
|
||||
<ul>
|
||||
<li>All counterparties of the frozen issuing account can no longer decrease the balances in their trust lines to the frozen account, except in direct payments to the issuer. (This also affects any <a href="concept-issuing-and-operational-addresses.html">operational addresses</a>.)</li>
|
||||
<li>Counterparties of the frozen issuing account can still send and receive payments directly to and from the issuing account.</li>
|
||||
<li>All offers to sell currencies issued by the frozen account are <a href="reference-transaction-format.html#lifecycle-of-an-offer">considered unfunded</a>.</li>
|
||||
</ul>
|
||||
<p>It can be useful to enable Global Freeze on a gateway's <a href="concept-issuing-and-operational-addresses.html">issuing account</a> if the secret key to an operational address is compromised, or immediately after regaining control of a such an address. This stops the flow of funds, preventing attackers from getting away with any more money or at least making it easier to track what happened. In addition to enacting a Global Freeze in the Ripple Consensus Ledger, a financial institution should also suspend activities in its connectors to outside systems.</p>
|
||||
<p>It can also be useful to enable Global Freeze if a gateway intends to migrate to a new <a href="concept-issuing-and-operational-addresses.html">issuing account</a>, or if the gateway intends to cease doing business. This locks the funds at a specific point in time, so users cannot trade them away for other currencies.</p>
|
||||
<p>Global Freeze applies to <em>all</em> currencies issued and held by the account. You cannot enable Global Freeze for only one currency. If you want to have the ability to freeze some currencies and not others, you should use different accounts for each currency.</p>
|
||||
<p>An account can always enable the Global Freeze setting. However, if the account has previously enabled the <a href="#no-freeze">No Freeze</a> setting, it can never <em>disable</em> Global Freeze.</p>
|
||||
<h2 id="no-freeze">No Freeze</h2>
|
||||
<p>The <strong>No Freeze</strong> feature is a setting on an account that permanently gives up the ability to freeze counterparties. A business can use this feature to treat its issued funds as "more like physical money" in the sense that the business cannot interfere with customers trading it among themselves. The NoFreeze setting has two effects:</p>
|
||||
<ul>
|
||||
<li>The issuing account can no longer enable Individual Freeze on trust lines to any counterparty.</li>
|
||||
<li>The issuing account can still enable Global Freeze to enact a global freeze, but the account cannot <em>disable</em> Global Freeze.</li>
|
||||
</ul>
|
||||
<p>The Ripple Consensus Ledger cannot force a gateway to honor the obligations that its issued funds represent, so giving up the ability to enable a Global Freeze cannot protect customers. However, giving up the ability to <em>disable</em> a Global Freeze ensures that the Global Freeze feature is not used unfairly against some customers.</p>
|
||||
<p>The No Freeze setting applies to all currencies issued to and from an account. If you want to be able to freeze some currencies but not others, you should use different accounts for each currency.</p>
|
||||
<p>You can only enable the No Freeze setting with a transaction signed by your account's master key. You cannot use a <a href="reference-transaction-format.html#setregularkey">Regular Key</a> or a <a href="reference-transaction-format.html#multi-signing">multi-signed transaction</a> to enable No Freeze.</p>
|
||||
<h1 id="technical-details">Technical Details</h1>
|
||||
<h2 id="enabling-or-disabling-individual-freeze">Enabling or Disabling Individual Freeze</h2>
|
||||
<h3 id="using-rippled">Using <code>rippled</code></h3>
|
||||
<p>To enable or disable Individual Freeze on a specific trust line, send a <code>TrustSet</code> transaction. Use the <a href="reference-transaction-format.html#trustset-flags"><code>tfSetFreeze</code> flag</a> to enable a freeze, and the <code>tfClearFreeze</code> flag to disable it. The fields of the transaction should be as follows:</p>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Field</th>
|
||||
<th>Value</th>
|
||||
<th>Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>Account</td>
|
||||
<td>String</td>
|
||||
<td>The address of your Ripple account.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>TransactionType</td>
|
||||
<td>String</td>
|
||||
<td><code>TrustSet</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>LimitAmount</td>
|
||||
<td>Object</td>
|
||||
<td>Object defining the trust line to freeze.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>LimitAmount.currency</td>
|
||||
<td>String</td>
|
||||
<td>Currency of the trust line</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>LimitAmount.issuer</td>
|
||||
<td>String</td>
|
||||
<td>The Ripple address of the counterparty to freeze</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>LimitAmount.value</td>
|
||||
<td>String</td>
|
||||
<td>The amount of currency you trust this counterparty to issue to you, as a quoted number. From the perspective of a gateway, this is typically <code>"0"</code>.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Flags</td>
|
||||
<td>Number</td>
|
||||
<td>To enable a freeze, use a value with the bit <code>0x00100000</code> (tfSetFreeze) enabled. To disable a freeze, use a value with the bit <code>0x00200000</code> (tfClearFreeze) enabled instead.</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<p>Set the <code>Fee</code>, <code>Sequence</code>, and <code>LastLedgerSequence</code> parameters <a href="reference-transaction-format.html#signing-and-submitting-transactions">in the typical way</a>.</p>
|
||||
<p>Example of submitting a TrustSet transaction to enable an individual freeze using the <a href="reference-rippled.html#websocket-api">WebSocket API</a>:</p>
|
||||
<pre><code>{
|
||||
"id": 12,
|
||||
"command": "submit",
|
||||
"tx_json": {
|
||||
"TransactionType": "TrustSet",
|
||||
"Account": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn",
|
||||
"Fee": "12000",
|
||||
"Flags": 1048576,
|
||||
"LastLedgerSequence": 18103014,
|
||||
"LimitAmount": {
|
||||
"currency": "USD",
|
||||
"issuer": "rsA2LpzuawewSBQXkiju3YQTMzW13pAAdW",
|
||||
"value": "110"
|
||||
},
|
||||
"Sequence": 340
|
||||
},
|
||||
"secret": "s████████████████████████████",
|
||||
"offline": false,
|
||||
"fee_mult_max": 1000
|
||||
}
|
||||
</code></pre>
|
||||
<p>(<strong>Reminder</strong>: Never transmit your account secret to an untrusted server or over an insecure channel.)</p>
|
||||
<h3 id="using-rippleapi">Using RippleAPI</h3>
|
||||
<p>To enable or disable Individual Freeze on a specific trust line, prepare a <em>Trustline</em> transaction using the <a href="reference-rippleapi.html#preparetrustline">prepareTrustline</a> method. The fields of the <code>trustline</code> parameter should be set as follows:</p>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Field</th>
|
||||
<th>Value</th>
|
||||
<th>Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>currency</td>
|
||||
<td>String</td>
|
||||
<td>The <a href="reference-rippleapi.html#currency">currency</a> of the trust line to freeze</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>counterparty</td>
|
||||
<td>String</td>
|
||||
<td>The <a href="reference-rippleapi.html#ripple-address">Ripple address</a> of the counterparty</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>limit</td>
|
||||
<td>String</td>
|
||||
<td>The amount of currency you trust this counterparty to issue to you, as a quoted number. From the perspective of a gateway, this is typically <code>"0"</code>.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>frozen</td>
|
||||
<td>Boolean</td>
|
||||
<td><code>true</code> to enable Individual Freeze on this trust line. <code>false</code> to disable Individual Freeze.</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<p>The rest of the <a href="reference-rippleapi.html#transaction-flow">transaction flow</a> is the same as any other transaction.</p>
|
||||
<p>Example JavaScript (ECMAScript 6) code to enable Individual Freeze on a trust line:</p>
|
||||
<pre><code class="js">const {RippleAPI} = require('ripple-lib');
|
||||
|
||||
const api = new RippleAPI({
|
||||
server: 'wss://s1.ripple.com' // Public rippled server
|
||||
});
|
||||
api.on('error', (errorCode, errorMessage) => {
|
||||
console.log(errorCode + ': ' + errorMessage);
|
||||
});
|
||||
|
||||
const issuing_address = 'rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn';
|
||||
const issuing_secret = 's████████████████████████████';
|
||||
// Best practice: get your secret from an encrypted
|
||||
// config file instead
|
||||
const address_to_freeze = 'rUpy3eEg8rqjqfUoLeBnZkscbKbFsKXC3v';
|
||||
const currency_to_freeze = 'USD';
|
||||
|
||||
api.connect().then(() => {
|
||||
|
||||
// Look up current state of trust line
|
||||
const options = {counterparty: address_to_freeze,
|
||||
currency: currency_to_freeze};
|
||||
console.log('looking up', currency_to_freeze, 'trust line from',
|
||||
issuing_address, 'to', address_to_freeze);
|
||||
return api.getTrustlines(issuing_address, options);
|
||||
|
||||
}).then(data => {
|
||||
|
||||
// Prepare a trustline transaction to enable freeze
|
||||
let trustline = {};
|
||||
if (data.length !== 1) {
|
||||
console.log('trustline not found, making a default one');
|
||||
trustline = {
|
||||
currency: currency_to_freeze,
|
||||
counterparty: address_to_freeze,
|
||||
limit: 0
|
||||
};
|
||||
} else {
|
||||
trustline = data[0].specification;
|
||||
console.log('trustline found. previous state:', trustline);
|
||||
}
|
||||
|
||||
trustline.frozen = true;
|
||||
|
||||
console.log('preparing trustline transaction for line:', trustline);
|
||||
return api.prepareTrustline(issuing_address, trustline);
|
||||
|
||||
}).then(prepared_tx => {
|
||||
|
||||
// Sign and submit the trustline transaction
|
||||
console.log('signing tx:', prepared_tx.txJSON);
|
||||
const signed1 = api.sign(prepared_tx.txJSON, issuing_secret);
|
||||
console.log('submitting tx:', signed1.id);
|
||||
|
||||
return api.submit(signed1.signedTransaction);
|
||||
}).then(() => {
|
||||
return api.disconnect();
|
||||
}).catch(console.error);
|
||||
</code></pre>
|
||||
<h2 id="enabling-or-disabling-global-freeze">Enabling or Disabling Global Freeze</h2>
|
||||
<h3 id="using-rippled-1">Using <code>rippled</code></h3>
|
||||
<p>To enable Global Freeze on an account, send an <code>AccountSet</code> transaction with the <a href="reference-transaction-format.html#accountset-flags">asfGlobalFreeze flag value</a> in the <code>SetFlag</code> field. To disable Global Freeze, put the asfGlobalFreeze flag value in the <code>ClearFlag</code> field instead.</p>
|
||||
<p>Example of submitting an AccountSet transaction to enable Global Freeze using the <a href="reference-rippled.html#websocket-api">WebSocket API</a>:</p>
|
||||
<pre><code>{
|
||||
"id": 12,
|
||||
"command": "submit",
|
||||
"tx_json": {
|
||||
"TransactionType": "AccountSet",
|
||||
"Account": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn",
|
||||
"Fee": "12000",
|
||||
"Flags": 0,
|
||||
"SetFlag": 7,
|
||||
"LastLedgerSequence": 18122753,
|
||||
"Sequence": 349
|
||||
},
|
||||
"secret": "s████████████████████████████",
|
||||
"offline": false,
|
||||
"fee_mult_max": 1000
|
||||
}
|
||||
</code></pre>
|
||||
<p>(<strong>Reminder</strong>: Never transmit your account secret to an untrusted server or over an insecure channel.)</p>
|
||||
<h3 id="using-rippleapi-1">Using RippleAPI</h3>
|
||||
<p>To enable or disable Global Freeze on an account, prepare a <strong>Settings</strong> transaction using the <a href="reference-rippleapi.html#preparesettings">prepareSettings</a> method. The <code>settings</code> parameter should be an object set as follows:</p>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Field</th>
|
||||
<th>Value</th>
|
||||
<th>Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>globalFreeze</td>
|
||||
<td>Boolean</td>
|
||||
<td><code>true</code> to enable a Global Freeze on this account. <code>false</code> to disable Global Freeze.</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<p>The rest of the <a href="reference-rippleapi.html#transaction-flow">transaction flow</a> is the same as any other transaction.</p>
|
||||
<p>Example JavaScript (ECMAScript 6) code to enable Global Freeze on an account:</p>
|
||||
<pre><code class="js">const {RippleAPI} = require('ripple-lib');
|
||||
|
||||
const api = new RippleAPI({
|
||||
server: 'wss://s1.ripple.com' // Public rippled server
|
||||
});
|
||||
api.on('error', (errorCode, errorMessage) => {
|
||||
console.log(errorCode + ': ' + errorMessage);
|
||||
});
|
||||
|
||||
const issuing_address = 'rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn';
|
||||
const issuing_secret = 's████████████████████████████';
|
||||
// Best practice: get your secret from an encrypted
|
||||
// config file instead
|
||||
|
||||
api.connect().then(() => {
|
||||
|
||||
// Prepare a settings transaction to enable global freeze
|
||||
const settings = {
|
||||
'globalFreeze': true
|
||||
};
|
||||
|
||||
console.log('preparing settings transaction for account:',
|
||||
issuing_address);
|
||||
return api.prepareSettings(issuing_address, settings);
|
||||
|
||||
}).then(prepared_tx => {
|
||||
|
||||
// Sign and submit the settings transaction
|
||||
console.log('signing tx:', prepared_tx.txJSON);
|
||||
const signed1 = api.sign(prepared_tx.txJSON, issuing_secret);
|
||||
console.log('submitting tx:', signed1.id);
|
||||
|
||||
return api.submit(signed1.signedTransaction);
|
||||
|
||||
}).then(() => {
|
||||
return api.disconnect();
|
||||
}).catch(console.error);
|
||||
</code></pre>
|
||||
<h2 id="enabling-no-freeze">Enabling No Freeze</h2>
|
||||
<h3 id="using-rippled-2">Using <code>rippled</code></h3>
|
||||
<p>To enable No Freeze on an account, send an <code>AccountSet</code> transaction with the <a href="reference-transaction-format.html#accountset-flags">asfNoFreeze flag value</a> in the <code>SetFlag</code> field. You must sign this transaction using the master key. Once enabled, you cannot disable No Freeze.</p>
|
||||
<p>Example of submitting an AccountSet transaction to enable No Freeze using the <a href="reference-rippled.html#websocket-api">WebSocket API</a>:</p>
|
||||
<p>WebSocket request:</p>
|
||||
<pre><code>{
|
||||
"id": 12,
|
||||
"command": "submit",
|
||||
"tx_json": {
|
||||
"TransactionType": "AccountSet",
|
||||
"Account": "raKEEVSGnKSD9Zyvxu4z6Pqpm4ABH8FS6n",
|
||||
"Fee": "12000",
|
||||
"Flags": 0,
|
||||
"SetFlag": 6,
|
||||
"LastLedgerSequence": 18124917,
|
||||
"Sequence": 4
|
||||
},
|
||||
"secret": "s████████████████████████████",
|
||||
"offline": false,
|
||||
"fee_mult_max": 1000
|
||||
}
|
||||
</code></pre>
|
||||
<p>(<strong>Reminder</strong>: Never transmit your account secret to an untrusted server or over an insecure channel.)</p>
|
||||
<h3 id="using-rippleapi-2">Using RippleAPI</h3>
|
||||
<p>To enable No Freeze on an account, prepare a <strong>Settings</strong> transaction using the <a href="reference-rippleapi.html#preparesettings">prepareSettings</a> method. Once enabled, you cannot disable No Freeze. The <code>settings</code> parameter should be an object set as follows:</p>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Field</th>
|
||||
<th>Value</th>
|
||||
<th>Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>noFreeze</td>
|
||||
<td>Boolean</td>
|
||||
<td><code>true</code></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<p>You must <a href="reference-rippleapi.html#sign">sign</a> this transaction using the master key. The rest of the <a href="reference-rippleapi.html#transaction-flow">transaction flow</a> is the same as any other transaction.</p>
|
||||
<p>Example JavaScript (ECMAScript 6) code to enable No Freeze on an account:</p>
|
||||
<pre><code class="js">const {RippleAPI} = require('ripple-lib');
|
||||
|
||||
const api = new RippleAPI({
|
||||
server: 'wss://s1.ripple.com' // Public rippled server
|
||||
});
|
||||
api.on('error', (errorCode, errorMessage) => {
|
||||
console.log(errorCode + ': ' + errorMessage);
|
||||
});
|
||||
|
||||
const issuing_address = 'rUpy3eEg8rqjqfUoLeBnZkscbKbFsKXC3v';
|
||||
const issuing_secret = 'snnDVkSW3aV6jvMJTPdCiE2Qxv1RW';
|
||||
// Best practice: get your secret from an encrypted
|
||||
// config file instead
|
||||
|
||||
api.connect().then(() => {
|
||||
|
||||
// Prepare a settings transaction to enable no freeze
|
||||
const settings = {
|
||||
'noFreeze': true
|
||||
};
|
||||
|
||||
console.log('preparing settings transaction for account:',
|
||||
issuing_address);
|
||||
return api.prepareSettings(issuing_address, settings);
|
||||
|
||||
}).then(prepared_tx => {
|
||||
|
||||
// Sign and submit the settings transaction
|
||||
console.log('signing tx:', prepared_tx.txJSON);
|
||||
const signed1 = api.sign(prepared_tx.txJSON, issuing_secret);
|
||||
console.log('submitting tx:', signed1.id);
|
||||
|
||||
return api.submit(signed1.signedTransaction);
|
||||
}).then(() => {
|
||||
return api.disconnect();
|
||||
}).catch(console.error);
|
||||
</code></pre>
|
||||
<h2 id="checking-for-individual-freeze">Checking for Individual Freeze</h2>
|
||||
<h3 id="using-rippled-3">Using <code>rippled</code></h3>
|
||||
<p>To see if a trust line has an Individual Freeze enabled, use the <a href="reference-rippled.html#account-lines"><code>account_lines</code> method</a> with the following parameters:</p>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Field</th>
|
||||
<th>Value</th>
|
||||
<th>Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>account</td>
|
||||
<td>String</td>
|
||||
<td>The Ripple address of the issuing account</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>peer</td>
|
||||
<td>String</td>
|
||||
<td>The Ripple address of the counterparty account</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>ledger_index</td>
|
||||
<td>String</td>
|
||||
<td>Use <code>validated</code> to get the most recently validated information.</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<p>The response contains an array of trust lines, for each currency in which the issuing account and the counterparty are linked. Look for the following fields in each trust line object:</p>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Field</th>
|
||||
<th>Value</th>
|
||||
<th>Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>freeze</td>
|
||||
<td>Boolean</td>
|
||||
<td>(May be omitted) <code>true</code> if the issuing account has frozen this trust line. If omitted, that is the same as <code>false</code>.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>freeze_peer</td>
|
||||
<td>Boolean</td>
|
||||
<td>(May be omitted) <code>true</code> if the counterparty has frozen this trust line. If omitted, that is the same as <code>false</code>.</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<p>Example WebSocket request to check for individual freeze:</p>
|
||||
<pre><code>{
|
||||
"id": 15,
|
||||
"command": "account_lines",
|
||||
"account": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn",
|
||||
"ledger": "validated",
|
||||
"peer": "rsA2LpzuawewSBQXkiju3YQTMzW13pAAdW"
|
||||
}
|
||||
</code></pre>
|
||||
<p>Example WebSocket response:</p>
|
||||
<pre><code>{
|
||||
"id": 15,
|
||||
"status": "success",
|
||||
"type": "response",
|
||||
"result": {
|
||||
"account": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn",
|
||||
"lines": [
|
||||
{
|
||||
"account": "rsA2LpzuawewSBQXkiju3YQTMzW13pAAdW",
|
||||
"balance": "10",
|
||||
"currency": "USD",
|
||||
"freeze": true,
|
||||
"limit": "110",
|
||||
"limit_peer": "0",
|
||||
"peer_authorized": true,
|
||||
"quality_in": 0,
|
||||
"quality_out": 0
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
</code></pre>
|
||||
<p>The field <code>"freeze": true</code> indicates that rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn has enabled Individual Freeze on the USD trust line to rsA2LpzuawewSBQXkiju3YQTMzW13pAAdW. The lack of a field <code>"freeze_peer": true</code> indicates that the counterparty has <em>not</em> frozen the trust line.</p>
|
||||
<h3 id="using-rippleapi-3">Using RippleAPI</h3>
|
||||
<p>To see if a trust line has an Individual Freeze enabled, use the <a href="reference-rippleapi.html#gettrustlines"><code>getTrustlines</code> method</a> with the following parameters:</p>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Field</th>
|
||||
<th>Value</th>
|
||||
<th>Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>address</td>
|
||||
<td>String</td>
|
||||
<td>The Ripple address of the issuing account</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>options.counterparty</td>
|
||||
<td>String</td>
|
||||
<td>The Ripple address of the counterparty account</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<p>The response contains an array of trust lines, for each currency in which the issuing account and the counterparty are linked. Look for the following fields in each trust line object:</p>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Field</th>
|
||||
<th>Value</th>
|
||||
<th>Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>specification.frozen</td>
|
||||
<td>Boolean</td>
|
||||
<td>(May be omitted) <code>true</code> if the issuing account has frozen the trust line.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>counterparty.frozen</td>
|
||||
<td>Boolean</td>
|
||||
<td>(May be omitted) <code>true</code> if the counterparty has frozen the trust line.</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<p>Example JavaScript (ECMAScript 6) code to check whether a trust line is frozen:</p>
|
||||
<pre><code class="js">const {RippleAPI} = require('ripple-lib');
|
||||
|
||||
const api = new RippleAPI({
|
||||
server: 'wss://s1.ripple.com' // Public rippled server
|
||||
});
|
||||
api.on('error', (errorCode, errorMessage) => {
|
||||
console.log(errorCode + ': ' + errorMessage);
|
||||
});
|
||||
|
||||
const my_address = 'rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn';
|
||||
const counterparty_address = 'rUpy3eEg8rqjqfUoLeBnZkscbKbFsKXC3v';
|
||||
const frozen_currency = 'USD';
|
||||
|
||||
api.connect().then(() => {
|
||||
|
||||
// Look up current state of trust line
|
||||
const options = {counterparty: counterparty_address,
|
||||
currency: frozen_currency};
|
||||
console.log('looking up', frozen_currency, 'trust line from',
|
||||
my_address, 'to', counterparty_address);
|
||||
return api.getTrustlines(my_address, options);
|
||||
|
||||
}).then(data => {
|
||||
|
||||
if (data.length !== 1) {
|
||||
throw 'should only be 1 trust line per counterparty+currency pair';
|
||||
}
|
||||
|
||||
const trustline = data[0];
|
||||
console.log('Trust line frozen from our side?',
|
||||
trustline.specification.frozen === true);
|
||||
console.log('Trust line frozen from counterparty\'s side?',
|
||||
trustline.counterparty.frozen === true);
|
||||
|
||||
}).then(() => {
|
||||
return api.disconnect();
|
||||
}).catch(console.error);
|
||||
</code></pre>
|
||||
<h2 id="checking-for-global-freeze-and-no-freeze">Checking for Global Freeze and No Freeze</h2>
|
||||
<h3 id="using-rippled-4">Using <code>rippled</code></h3>
|
||||
<p>To see if an account has Global Freeze and/or No Freeze enabled, use the <a href="reference-rippled.html#account-lines"><code>account_info</code> method</a> with the following parameters:</p>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Field</th>
|
||||
<th>Value</th>
|
||||
<th>Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>account</td>
|
||||
<td>String</td>
|
||||
<td>The Ripple address of the issuing account</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>ledger_index</td>
|
||||
<td>String</td>
|
||||
<td>Use <code>validated</code> to get the most recently validated information.</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<p>Check the value of the <code>account_data.Flags</code> field of the response using the <a href="https://en.wikipedia.org/wiki/Bitwise_operation#AND">bitwise-AND</a> operator:</p>
|
||||
<ul>
|
||||
<li>If <code>Flags</code> AND <code>0x00400000</code> (<a href="reference-ledger-format.html#accountroot-flags">lsfGlobalFreeze</a>) is <em>nonzero</em>: Global Freeze is enabled.</li>
|
||||
<li>If <code>Flags</code> AND <code>0x00200000</code> (<a href="reference-ledger-format.html#accountroot-flags">lsfNoFreeze</a>) is <em>nonzero</em>: No Freeze is enabled.</li>
|
||||
</ul>
|
||||
<p>Example WebSocket request:</p>
|
||||
<pre><code>{
|
||||
"id": 1,
|
||||
"command": "account_info",
|
||||
"account": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn",
|
||||
"ledger_index": "validated"
|
||||
}
|
||||
</code></pre>
|
||||
<p>WebSocket response:</p>
|
||||
<pre><code>{
|
||||
"id": 4,
|
||||
"status": "success",
|
||||
"type": "response",
|
||||
"result": {
|
||||
"account_data": {
|
||||
"Account": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn",
|
||||
"AccountTxnID": "41320138CA9837B34E82B3B3D6FB1E581D5DE2F0A67B3D62B5B8A8C9C8D970D0",
|
||||
"Balance": "100258663",
|
||||
"Domain": "6D64756F31332E636F6D",
|
||||
"EmailHash": "98B4375E1D753E5B91627516F6D70977",
|
||||
"Flags": 12582912,
|
||||
"LedgerEntryType": "AccountRoot",
|
||||
"MessageKey": "0000000000000000000000070000000300",
|
||||
"OwnerCount": 4,
|
||||
"PreviousTxnID": "41320138CA9837B34E82B3B3D6FB1E581D5DE2F0A67B3D62B5B8A8C9C8D970D0",
|
||||
"PreviousTxnLgrSeq": 18123095,
|
||||
"Sequence": 352,
|
||||
"TransferRate": 1004999999,
|
||||
"index": "13F1A95D7AAB7108D5CE7EEAF504B2894B8C674E6D68499076441C4837282BF8",
|
||||
"urlgravatar": "http://www.gravatar.com/avatar/98b4375e1d753e5b91627516f6d70977"
|
||||
},
|
||||
"ledger_hash": "A777B05A293A73E511669B8A4A45A298FF89AD9C9394430023008DB4A6E7FDD5",
|
||||
"ledger_index": 18123249,
|
||||
"validated": true
|
||||
}
|
||||
}
|
||||
</code></pre>
|
||||
<p>In the above example, the <code>Flags</code> value is 12582912. This indicates that has the following flags enabled: lsfGlobalFreeze, lsfDefaultRipple, as demonstrated by the following JavaScript code:</p>
|
||||
<pre><code class="js">var lsfGlobalFreeze = 0x00400000;
|
||||
var lsfNoFreeze = 0x00200000;
|
||||
|
||||
var currentFlags = 12582912;
|
||||
|
||||
console.log(currentFlags & lsfGlobalFreeze); //4194304
|
||||
//therefore, Global Freeze is enabled
|
||||
|
||||
console.log(currentFlags & lsfNoFreeze); //0
|
||||
//therefore, No Freeze is not enabled
|
||||
</code></pre>
|
||||
<h3 id="using-rippleapi-4">Using RippleAPI</h3>
|
||||
<p>To see if an account has Global Freeze and/or No Freeze enabled, use the <a href="reference-rippleapi.html#getsettings"><code>getSettings</code> method</a> with the following parameters:</p>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Field</th>
|
||||
<th>Value</th>
|
||||
<th>Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>address</td>
|
||||
<td>String</td>
|
||||
<td>The Ripple address of the issuing account</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<p>Look for the following values in the response object:</p>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Field</th>
|
||||
<th>Value</th>
|
||||
<th>Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>noFreeze</td>
|
||||
<td>Boolean</td>
|
||||
<td>(May be omitted) <code>true</code> if No Freeze is enabled.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>globalFreeze</td>
|
||||
<td>Boolean</td>
|
||||
<td>(May be omitted) <code>true</code> if Global Freeze is enabled.</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<p>Example JavaScript (ECMAScript 6) code to check whether an account has Global Freeze or No Freeze enabled:</p>
|
||||
<pre><code class="js">const {RippleAPI} = require('ripple-lib');
|
||||
|
||||
const api = new RippleAPI({
|
||||
server: 'wss://s1.ripple.com' // Public rippled server
|
||||
});
|
||||
api.on('error', (errorCode, errorMessage) => {
|
||||
console.log(errorCode + ': ' + errorMessage);
|
||||
});
|
||||
|
||||
const my_address = 'rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn';
|
||||
|
||||
api.connect().then(() => {
|
||||
// Look up settings object
|
||||
return api.getSettings(my_address);
|
||||
}).then(settings => {
|
||||
console.log('Got settings for address', my_address);
|
||||
console.log('Global Freeze enabled?',
|
||||
(settings.globalFreeze === true));
|
||||
console.log('No Freeze enabled?', (settings.noFreeze === true));
|
||||
|
||||
}).then(() => {
|
||||
return api.disconnect();
|
||||
}).catch(console.error);
|
||||
</code></pre>
|
||||
<h1 id="see-also">See Also</h1>
|
||||
<ul>
|
||||
<li><a href="https://ripple.com/files/GB-2014-02.pdf">Gateway Bulletin GB-2014-02 New Feature: Balance Freeze</a></li>
|
||||
<li><a href="https://github.com/ripple/ripple-dev-portal/tree/gh-pages/content/code_samples/freeze">Freeze Code Samples</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</main>
|
||||
</div>
|
||||
|
||||
<footer class="content-info" role="contentinfo">
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
|
||||
<section class="col-sm-3 widget nav_menu-3 widget_nav_menu">
|
||||
<h4>Resources<hr></h4>
|
||||
<ul id="menu-resources" class="menu">
|
||||
<li class="menu-insights"><a href="https://ripple.com/insights/">Insights</a></li>
|
||||
<li class="menu-press-center"><a href="https://ripple.com/press-center/">Press Center</a></li>
|
||||
<li class="menu-media-resources"><a href="https://ripple.com/media-resources/">Media Resources</a></li>
|
||||
<li class="menu-videos"><a href="https://ripple.com/videos/">Videos</a></li>
|
||||
<li class="menu-whitepapers-reports"><a href="https://ripple.com/whitepapers-reports/">Whitepapers & Reports</a></li>
|
||||
<li class="menu-xrp-portal"><a href="https://ripple.com/xrp-portal/">XRP Portal</a></li>
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
<section class="col-sm-3 widget nav_menu-5 widget_nav_menu">
|
||||
<h4>Regulators<hr></h4>
|
||||
<ul id="menu-compliance-regulatory-relations" class="menu"><li class="menu-compliance"><a href="https://ripple.com/compliance/">Compliance</a></li>
|
||||
<li class="menu-policy-framework"><a href="https://ripple.com/policy-framework/">Policy Framework</a></li>
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
<section class="col-sm-3 widget nav_menu-4 widget_nav_menu">
|
||||
<h4>Support<hr></h4>
|
||||
<ul id="menu-dev-footer-menu" class="menu">
|
||||
<li class="menu-contact-us"><a href="https://ripple.com/contact/">Contact Us</a></li>
|
||||
<li class="active menu-developer-center"><a href="https://ripple.com/build/">Developer Center</a></li>
|
||||
<li class="menu-knowledge-center"><a href="https://ripple.com/learn/">Knowledge Center</a></li>
|
||||
<li class="menu-ripple-forum"><a target="_blank" href="https://forum.ripple.com/">Ripple Forum</a></li>
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
<section class="col-sm-3 widget nav_menu-2 widget_nav_menu">
|
||||
<h4>About<hr></h4>
|
||||
<ul id="menu-company-footer" class="menu">
|
||||
<li class="menu-our-company"><a href="https://ripple.com/company/">Our Company</a></li>
|
||||
<li class="menu-careers"><a href="https://ripple.com/company/careers/">Careers</a></li>
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
<div class="col-sm-12 absolute_bottom_footer">
|
||||
<div class="col-sm-8">
|
||||
<span>© 2013-2015 Ripple Labs, Inc. All Rights Reserved.</span>
|
||||
<span><a href="https://ripple.com/terms-of-use/">Terms</a></span>
|
||||
<span><a href="https://ripple.com/privacy-policy/">Privacy</a></span>
|
||||
</div>
|
||||
</div><!-- /.absolute_bottom_footer -->
|
||||
|
||||
</div><!-- /.row -->
|
||||
</div><!-- /.container -->
|
||||
</footer>
|
||||
</body>
|
||||
</html>
|
||||
228
concept-issuing-and-operational-addresses.html
Normal file
@@ -0,0 +1,228 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
|
||||
<meta name="viewport" content="width=device-width">
|
||||
|
||||
<title>Issuing and Operational Addresses - Ripple Developer Portal</title>
|
||||
|
||||
<!-- favicon -->
|
||||
<link rel="icon" href="favicon.ico" type="image/x-icon">
|
||||
<link rel="shortcut icon" href="favicon.ico" type="image/x-icon">
|
||||
|
||||
<!-- jQuery -->
|
||||
<script src="assets/vendor/jquery-1.11.1.min.js"></script>
|
||||
|
||||
<!-- Custom Stylesheets. ripple.css includes bootstrap, font stuff -->
|
||||
<link href="assets/css/ripple.css" rel="stylesheet" />
|
||||
<link href="assets/css/devportal.css" rel="stylesheet" />
|
||||
|
||||
<!-- Bootstrap JS -->
|
||||
<script src="assets/vendor/bootstrap.min.js"></script>
|
||||
|
||||
|
||||
<!-- syntax highlighting -->
|
||||
<link rel="stylesheet" href="assets/vendor/docco.min.css">
|
||||
<script src="assets/vendor/highlight.min.js"></script>
|
||||
|
||||
<!-- syntax selection js -->
|
||||
<script src="assets/js/multicodetab.js"></script>
|
||||
<script>
|
||||
$(document).ready(function() {
|
||||
$().multicode_tabs();
|
||||
hljs.initHighlighting();
|
||||
make_code_expandable();
|
||||
});
|
||||
</script>
|
||||
|
||||
<script src="assets/js/expandcode.js"></script>
|
||||
<script src="assets/js/fixsidebarscroll.js"></script>
|
||||
|
||||
</head>
|
||||
|
||||
<body class="page page-template page-template-template-dev-portal page-template-template-dev-portal-php sidebar-primary wpb-js-composer js-comp-ver-3.6.2 vc_responsive">
|
||||
<header role="banner" class="banner navbar navbar-default navbar-fixed-top initial_header">
|
||||
<div class="container">
|
||||
<div class="navbar-header">
|
||||
<a href="index.html" class="navbar-brand"><img src="assets/img/ripple-logo-color.png" class="logo"></a>
|
||||
</div><!-- /.navbar-header -->
|
||||
<div class="nav">
|
||||
<div class="draft-warning">DRAFT PAGE</div>
|
||||
</div><!-- /.nav -->
|
||||
|
||||
</div><!-- /.container -->
|
||||
|
||||
<div class="subnav dev_nav">
|
||||
<div class="container">
|
||||
<ul id="menu-dev-menu" class="menu">
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">References <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="reference-rippled.html">rippled</a></li>
|
||||
<li><a href="reference-transaction-format.html">Transaction Format</a></li>
|
||||
<li><a href="reference-ledger-format.html">Ledger Format</a></li>
|
||||
<li><a href="reference-rippleapi.html">RippleAPI</a></li>
|
||||
<li><a href="reference-data-api.html">Ripple Data API v2</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Tutorials <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="tutorial-rippleapi-beginners-guide.html">RippleAPI Beginners Guide</a></li>
|
||||
<li><a href="tutorial-rippled-setup.html">rippled Setup</a></li>
|
||||
<li><a href="tutorial-reliable-transaction-submission.html">Reliable Transaction Submission</a></li>
|
||||
<li><a href="tutorial-multisign.html">How to Multi-Sign</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Concepts <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="concept-paths.html">Paths</a></li>
|
||||
<li><a href="concept-fees.html">Fees (Disambiguation)</a></li>
|
||||
<li><a href="concept-transfer-fees.html">Transfer Fees</a></li>
|
||||
<li><a href="concept-transaction-cost.html">Transaction Cost</a></li>
|
||||
<li><a href="concept-fee-voting.html">Fee Voting</a></li>
|
||||
<li><a href="concept-reserves.html">Reserves</a></li>
|
||||
<li><a href="concept-freeze.html">Freeze</a></li>
|
||||
<li><a href="concept-amendments.html">Amendments</a></li>
|
||||
<li><a href="concept-stand-alone-mode.html">Stand-Alone Mode</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Best Practices <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="concept-issuing-and-operational-addresses.html">Issuing and Operational Addresses</a></li>
|
||||
<li><a href="tutorial-gateway-guide.html">Gateway Guide</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">API Tools <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="ripple-api-tool.html">WebSocket API Tool</a></li>
|
||||
<li><a href="data-api-v2-tool.html">Data API v2 Tool</a></li>
|
||||
<li><a href="tool-jsonrpc.html">rippled JSON-RPC Tool</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Resources <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="https://forum.ripple.com/viewforum.php?f=2">Forums</a></li>
|
||||
<li><a href="https://www.bountysource.com/teams/ripple/bounties">Bounties</a></li>
|
||||
<li><a href="https://ripplelabs.atlassian.net/">Bug Tracking</a></li>
|
||||
<li><a href="https://ripple.com/category/dev-blog/">Dev Blog</a></li>
|
||||
<li><a href="https://ripple.com/press-releases/">Press Center</a></li>
|
||||
<li><a href="https://ripple.com/brand-guidelines/">Brand Guidelines</a></li>
|
||||
</ul>
|
||||
<li><a href="https://github.com/ripple/ripple-dev-portal" title="GitHub">Site Source</a></li>
|
||||
</ul><!-- /#dev-menu -->
|
||||
</div><!-- /.subnav .container -->
|
||||
</div><!-- /.subnav -->
|
||||
</header>
|
||||
|
||||
|
||||
<div class="wrap container" role="document">
|
||||
<aside class="sidebar" role="complementary">
|
||||
<div class="dev_nav_wrapper">
|
||||
<div id="cont">
|
||||
<ul class="dev_nav_sidebar">
|
||||
<li class="level-1"><a href="index.html">Category: Best Practices</a></li>
|
||||
<li class="level-2"><a href="concept-issuing-and-operational-addresses.html">Issuing and Operational Addresses</a></li>
|
||||
<li class="level-2"><a href="tutorial-gateway-guide.html">Gateway Guide</a></li>
|
||||
</ul>
|
||||
<hr />
|
||||
<h5>In this page:</h5>
|
||||
</div>
|
||||
<script type="text/javascript" src="assets/js/jquery.gensidebar.js"></script>
|
||||
</div>
|
||||
</aside>
|
||||
<main class="main" role="main">
|
||||
<div class='content'>
|
||||
<h1 id="issuing-and-operational-addresses">Issuing and Operational Addresses</h1>
|
||||
<p>All non-XRP currency balances (issuances) in the Ripple Consensus Ledger (RCL) are tied to accounting relationships between two Ripple addresses. To control an address in the RCL, you only need the secret key mathematically connected to that address. Since no party can unilaterally prevent transactions or correct the ledger, financial institutions typically use multiple Ripple ledger addresses to minimize the risk associated with a compromised secret key. Ripple strongly recommends the following separation of roles:</p>
|
||||
<ul>
|
||||
<li>One <strong>issuing address</strong>, also known as a "cold wallet." This address is the hub of the financial institution's accounting relationships in the ledger, but sends as few transactions as possible.</li>
|
||||
<li>One or more <strong>operational addresses</strong>, also known as "hot wallets." Automated, internet-connected systems use the secret keys to these addresses to conduct day-to-day business like transfers to customers and partners.</li>
|
||||
<li>Optional <strong>standby addresses</strong>, also known as "warm wallets." Trusted human operators use these addresses to transfer money to the operational addresses.</li>
|
||||
</ul>
|
||||
<h2 id="funds-lifecycle">Funds Lifecycle</h2>
|
||||
<p><a href="img/funds_flow_diagram.png"><img alt="Diagram: Funds flow from the issuing address to standby addresses, to operational addresses, to customer and partner addresses, and finally back to the issuing address." src="img/funds_flow_diagram.png"/></a></p>
|
||||
<p>Funds in the Ripple Consensus Ledger tend to flow in a cycle. When the issuing address sends payments, it creates balances in the accounting relationships in the Ripple Consensus Ledger. Within the RCL, users can exchange balances across different accounting relationships, so we use the term <em>issuances</em> to describe any non-XRP balance. Issuances have positive value from the perspective of the customers, partners, operational addresses, and standby addresses. The same issuances are negative balances from the perspective of the issuing address, since they represent obligations. When the issuing address receives a payment, this reduces its obligations, effectively "destroying" the issuances that were sent.</p>
|
||||
<p>The issuing address sends issuances to a standby address, or directly to an operational address. The standby addresses send those issuances to operational addresses. Operational addresses send payments to liquidity providers or other customers and partners. Because all issuances are tied to accounting relationships with the issuing address, payments and exchanges of issuances "ripple through" the issuing address. The payment debits the sender's balance in its accounting relationship with the issuing address and credits the recipient's balance in the recipient's accounting relationship with the issuing address. The Ripple Consensus Ledger also supports more complicated <a href="concept-paths.html">paths</a> that connect multiple issuers through order books and <a href="https://ripple.com/knowledge_center/understanding-the-noripple-flag/">liquidity providers who allow their funds to ripple</a>.</p>
|
||||
<h2 id="issuing-address">Issuing Address</h2>
|
||||
<p>The issuing address is like a vault. Partners, customers, and operational addresses create accounting relationships (trust lines) to the issuing address, but this address sends as few transactions as possible. Periodically, a human operator creates and signs a transaction from the issuing address in order to refill the balances of a standby or operational address. Ideally, the secret key used to sign these transactions should never be accessible from any internet-connected computer.</p>
|
||||
<p>Unlike a vault, the issuing address can receive payments directly from customers and partners. Since all transactions in the Ripple Consensus Ledger are public, automated systems can monitor for payments to the issuing address without needing a secret key.</p>
|
||||
<h3 id="issuing-address-compromise">Issuing Address Compromise</h3>
|
||||
<p>If a malicious actor learns the secret key behind a institution's issuing address, that actor can create new issuances without limit and trade them in the decentralized exchange. This would make it difficult for the financial institution to distinguish legitimately-obtained issuances and redeem them fairly. If a financial institution loses control of its issuing address, the institution must create a new issuing address, and all users who have accounting relationships with the old issuing address must create new accounting relationships with the new address.</p>
|
||||
<h3 id="multiple-issuing-addresses">Multiple Issuing Addresses</h3>
|
||||
<p>A financial institution can issue more than one currency in the Ripple Consensus Ledger from a single issuing address. However, there are some settings that apply equally to all currencies issued from an address, including the percentage for <a href="concept-transfer-fees.html">transfer fees</a> and the <a href="concept-freeze.html">global freeze</a> status. If the financial institution wants the flexibility to manage settings differently for each currency, the institution must use a different issuing address for each currency.</p>
|
||||
<h2 id="operational-addresses">Operational Addresses</h2>
|
||||
<p>An operational address is like a cash register. It makes payments on behalf of the institution by transferring issuances to customers and partners. In order to sign transactions automatically, the secret key for an operational address must be stored on a server that is connected to the internet. (The secret key can be stored encrypted, but the server must decrypt it in order to sign transactions.) Customers and partners do not, and should not, create accounting relationships with an operational address.</p>
|
||||
<p>Each operational address has a limited balance of issuances. When the balance of an operational address gets low, the financial institution refills it by sending a payment from the issuing address or a standby address.</p>
|
||||
<h3 id="operational-address-compromise">Operational Address Compromise</h3>
|
||||
<p>If a malicious actor learns the secret key behind an operational address, the financial institution can only lose as much currency as that operational address holds. The institution can switch to a new operational address with no action from customers and partners.</p>
|
||||
<h2 id="standby-addresses">Standby Addresses</h2>
|
||||
<p>Another optional step that an institution can take to balance risk and convenience is to use "standby addresses" as an intermediate step between the issuing address and operational addresses. The institution can fund additional Ripple addresses as standby addresses, whose keys are not stored online, but are entrusted to different trusted users.</p>
|
||||
<p>When an operational address is running low on funds, a trusted user can use a standby address to refill the operational address's balance. When a standby addresses run low on funds, the institution can use the issuing address to send more currency to a standby address in a single transaction, and the standby addresses can distribute that currency among themselves if necessary. This improves security of the issuing address, allowing it to make fewer total transactions, without leaving too much money in the control of a single automated system.</p>
|
||||
<p>As with operational addresses, a standby address must have an accounting relationship with the issuing address, and not with customers or partners. All precautions that apply to operational addresses also apply to standby addresses.</p>
|
||||
<h3 id="standby-address-compromise">Standby Address Compromise</h3>
|
||||
<p>If a standby address is compromised, the results are similar to an operational address being compromised. A malicious actor can steal any balances possessed by the standby address, and the financial institution can change to a new standby address with no action from customers and partners.</p>
|
||||
</div>
|
||||
</main>
|
||||
</div>
|
||||
|
||||
<footer class="content-info" role="contentinfo">
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
|
||||
<section class="col-sm-3 widget nav_menu-3 widget_nav_menu">
|
||||
<h4>Resources<hr></h4>
|
||||
<ul id="menu-resources" class="menu">
|
||||
<li class="menu-insights"><a href="https://ripple.com/insights/">Insights</a></li>
|
||||
<li class="menu-press-center"><a href="https://ripple.com/press-center/">Press Center</a></li>
|
||||
<li class="menu-media-resources"><a href="https://ripple.com/media-resources/">Media Resources</a></li>
|
||||
<li class="menu-videos"><a href="https://ripple.com/videos/">Videos</a></li>
|
||||
<li class="menu-whitepapers-reports"><a href="https://ripple.com/whitepapers-reports/">Whitepapers & Reports</a></li>
|
||||
<li class="menu-xrp-portal"><a href="https://ripple.com/xrp-portal/">XRP Portal</a></li>
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
<section class="col-sm-3 widget nav_menu-5 widget_nav_menu">
|
||||
<h4>Regulators<hr></h4>
|
||||
<ul id="menu-compliance-regulatory-relations" class="menu"><li class="menu-compliance"><a href="https://ripple.com/compliance/">Compliance</a></li>
|
||||
<li class="menu-policy-framework"><a href="https://ripple.com/policy-framework/">Policy Framework</a></li>
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
<section class="col-sm-3 widget nav_menu-4 widget_nav_menu">
|
||||
<h4>Support<hr></h4>
|
||||
<ul id="menu-dev-footer-menu" class="menu">
|
||||
<li class="menu-contact-us"><a href="https://ripple.com/contact/">Contact Us</a></li>
|
||||
<li class="active menu-developer-center"><a href="https://ripple.com/build/">Developer Center</a></li>
|
||||
<li class="menu-knowledge-center"><a href="https://ripple.com/learn/">Knowledge Center</a></li>
|
||||
<li class="menu-ripple-forum"><a target="_blank" href="https://forum.ripple.com/">Ripple Forum</a></li>
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
<section class="col-sm-3 widget nav_menu-2 widget_nav_menu">
|
||||
<h4>About<hr></h4>
|
||||
<ul id="menu-company-footer" class="menu">
|
||||
<li class="menu-our-company"><a href="https://ripple.com/company/">Our Company</a></li>
|
||||
<li class="menu-careers"><a href="https://ripple.com/company/careers/">Careers</a></li>
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
<div class="col-sm-12 absolute_bottom_footer">
|
||||
<div class="col-sm-8">
|
||||
<span>© 2013-2015 Ripple Labs, Inc. All Rights Reserved.</span>
|
||||
<span><a href="https://ripple.com/terms-of-use/">Terms</a></span>
|
||||
<span><a href="https://ripple.com/privacy-policy/">Privacy</a></span>
|
||||
</div>
|
||||
</div><!-- /.absolute_bottom_footer -->
|
||||
|
||||
</div><!-- /.row -->
|
||||
</div><!-- /.container -->
|
||||
</footer>
|
||||
</body>
|
||||
</html>
|
||||
315
concept-paths.html
Normal file
@@ -0,0 +1,315 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
|
||||
<meta name="viewport" content="width=device-width">
|
||||
|
||||
<title>Paths - Ripple Developer Portal</title>
|
||||
|
||||
<!-- favicon -->
|
||||
<link rel="icon" href="favicon.ico" type="image/x-icon">
|
||||
<link rel="shortcut icon" href="favicon.ico" type="image/x-icon">
|
||||
|
||||
<!-- jQuery -->
|
||||
<script src="assets/vendor/jquery-1.11.1.min.js"></script>
|
||||
|
||||
<!-- Custom Stylesheets. ripple.css includes bootstrap, font stuff -->
|
||||
<link href="assets/css/ripple.css" rel="stylesheet" />
|
||||
<link href="assets/css/devportal.css" rel="stylesheet" />
|
||||
|
||||
<!-- Bootstrap JS -->
|
||||
<script src="assets/vendor/bootstrap.min.js"></script>
|
||||
|
||||
|
||||
<!-- syntax highlighting -->
|
||||
<link rel="stylesheet" href="assets/vendor/docco.min.css">
|
||||
<script src="assets/vendor/highlight.min.js"></script>
|
||||
|
||||
<!-- syntax selection js -->
|
||||
<script src="assets/js/multicodetab.js"></script>
|
||||
<script>
|
||||
$(document).ready(function() {
|
||||
$().multicode_tabs();
|
||||
hljs.initHighlighting();
|
||||
make_code_expandable();
|
||||
});
|
||||
</script>
|
||||
|
||||
<script src="assets/js/expandcode.js"></script>
|
||||
<script src="assets/js/fixsidebarscroll.js"></script>
|
||||
|
||||
</head>
|
||||
|
||||
<body class="page page-template page-template-template-dev-portal page-template-template-dev-portal-php sidebar-primary wpb-js-composer js-comp-ver-3.6.2 vc_responsive">
|
||||
<header role="banner" class="banner navbar navbar-default navbar-fixed-top initial_header">
|
||||
<div class="container">
|
||||
<div class="navbar-header">
|
||||
<a href="index.html" class="navbar-brand"><img src="assets/img/ripple-logo-color.png" class="logo"></a>
|
||||
</div><!-- /.navbar-header -->
|
||||
<div class="nav">
|
||||
<div class="draft-warning">DRAFT PAGE</div>
|
||||
</div><!-- /.nav -->
|
||||
|
||||
</div><!-- /.container -->
|
||||
|
||||
<div class="subnav dev_nav">
|
||||
<div class="container">
|
||||
<ul id="menu-dev-menu" class="menu">
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">References <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="reference-rippled.html">rippled</a></li>
|
||||
<li><a href="reference-transaction-format.html">Transaction Format</a></li>
|
||||
<li><a href="reference-ledger-format.html">Ledger Format</a></li>
|
||||
<li><a href="reference-rippleapi.html">RippleAPI</a></li>
|
||||
<li><a href="reference-data-api.html">Ripple Data API v2</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Tutorials <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="tutorial-rippleapi-beginners-guide.html">RippleAPI Beginners Guide</a></li>
|
||||
<li><a href="tutorial-rippled-setup.html">rippled Setup</a></li>
|
||||
<li><a href="tutorial-reliable-transaction-submission.html">Reliable Transaction Submission</a></li>
|
||||
<li><a href="tutorial-multisign.html">How to Multi-Sign</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Concepts <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="concept-paths.html">Paths</a></li>
|
||||
<li><a href="concept-fees.html">Fees (Disambiguation)</a></li>
|
||||
<li><a href="concept-transfer-fees.html">Transfer Fees</a></li>
|
||||
<li><a href="concept-transaction-cost.html">Transaction Cost</a></li>
|
||||
<li><a href="concept-fee-voting.html">Fee Voting</a></li>
|
||||
<li><a href="concept-reserves.html">Reserves</a></li>
|
||||
<li><a href="concept-freeze.html">Freeze</a></li>
|
||||
<li><a href="concept-amendments.html">Amendments</a></li>
|
||||
<li><a href="concept-stand-alone-mode.html">Stand-Alone Mode</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Best Practices <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="concept-issuing-and-operational-addresses.html">Issuing and Operational Addresses</a></li>
|
||||
<li><a href="tutorial-gateway-guide.html">Gateway Guide</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">API Tools <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="ripple-api-tool.html">WebSocket API Tool</a></li>
|
||||
<li><a href="data-api-v2-tool.html">Data API v2 Tool</a></li>
|
||||
<li><a href="tool-jsonrpc.html">rippled JSON-RPC Tool</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Resources <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="https://forum.ripple.com/viewforum.php?f=2">Forums</a></li>
|
||||
<li><a href="https://www.bountysource.com/teams/ripple/bounties">Bounties</a></li>
|
||||
<li><a href="https://ripplelabs.atlassian.net/">Bug Tracking</a></li>
|
||||
<li><a href="https://ripple.com/category/dev-blog/">Dev Blog</a></li>
|
||||
<li><a href="https://ripple.com/press-releases/">Press Center</a></li>
|
||||
<li><a href="https://ripple.com/brand-guidelines/">Brand Guidelines</a></li>
|
||||
</ul>
|
||||
<li><a href="https://github.com/ripple/ripple-dev-portal" title="GitHub">Site Source</a></li>
|
||||
</ul><!-- /#dev-menu -->
|
||||
</div><!-- /.subnav .container -->
|
||||
</div><!-- /.subnav -->
|
||||
</header>
|
||||
|
||||
|
||||
<div class="wrap container" role="document">
|
||||
<aside class="sidebar" role="complementary">
|
||||
<div class="dev_nav_wrapper">
|
||||
<div id="cont">
|
||||
<ul class="dev_nav_sidebar">
|
||||
<li class="level-1"><a href="index.html">Category: Concepts</a></li>
|
||||
<li class="level-2"><a href="concept-paths.html">Paths</a></li>
|
||||
<li class="level-2"><a href="concept-fees.html">Fees (Disambiguation)</a></li>
|
||||
<li class="level-2"><a href="concept-transfer-fees.html">Transfer Fees</a></li>
|
||||
<li class="level-2"><a href="concept-transaction-cost.html">Transaction Cost</a></li>
|
||||
<li class="level-2"><a href="concept-fee-voting.html">Fee Voting</a></li>
|
||||
<li class="level-2"><a href="concept-reserves.html">Reserves</a></li>
|
||||
<li class="level-2"><a href="concept-freeze.html">Freeze</a></li>
|
||||
<li class="level-2"><a href="concept-amendments.html">Amendments</a></li>
|
||||
<li class="level-2"><a href="concept-stand-alone-mode.html">Stand-Alone Mode</a></li>
|
||||
</ul>
|
||||
<hr />
|
||||
<h5>In this page:</h5>
|
||||
</div>
|
||||
<script type="text/javascript" src="assets/js/jquery.gensidebar.js"></script>
|
||||
</div>
|
||||
</aside>
|
||||
<main class="main" role="main">
|
||||
<div class='content'>
|
||||
<h1 id="paths">Paths</h1>
|
||||
<p>In the Ripple Consensus Ledger, paths define a way for payments to flow through intermediary steps on their way from sender to receiver. Paths enable cross-currency payments by connecting sender and receiver via market makers. Paths also enable complex settlement of offsetting debts.</p>
|
||||
<p>A single Payment transaction in the Ripple Consensus Ledger can use multiple paths, combining liquidity from different sources to deliver the desired amount. Thus, a transaction includes a <em>path set</em>, which is a collection of possible paths to take. The paths in a path set must start and end with the same currency.</p>
|
||||
<p>Since XRP can be sent directly to any address, an XRP-to-XRP transaction does not use any paths.</p>
|
||||
<h2 id="path-steps">Path Steps</h2>
|
||||
<p>A path is made of steps that connect the sender to the receiver of the payment. Every step is either:</p>
|
||||
<ul>
|
||||
<li>Rippling through another account in the same currency</li>
|
||||
<li>Exchanging currency at an order book</li>
|
||||
</ul>
|
||||
<p>Rippling through another account is the process of moving debt around. In the typical case, this involves reducing a gateway's obligation to one party and increasing the gateway's obligation to another party. Rippling can occur between any accounts that are connected by trust lines. See <a href="https://ripple.com/knowledge_center/understanding-the-noripple-flag/">Understanding the NoRipple Flag</a> for more examples of rippling.</p>
|
||||
<p>In the case of a currency exchange step, the path step specifies which currency to change to, but does not record the state of the orders in the order book. Since the order of transactions is not finalized until a ledger is validated, it is impossible to determine for certain which offers a transaction will execute, until after the transaction has been validated. Consequently, you cannot know in advance which offers a transaction will take: only which order books the transaction will use. (You can make an educated guess, since each transaction takes the best available offers at the time it executes in the final ledger.)</p>
|
||||
<p>In both types of steps, each intermediate account gains and loses approximately equal value: either a balance ripples from a trust line to another trust line in the same currency, or they exchange currencies according to a previously-placed order. In some cases, the amounts gained and lost may not be exactly equivalent, due to <a href="https://ripple.com/knowledge_center/transfer-fees/">transfer fees</a>, trust line quality, or rounding.</p>
|
||||
<p><a href="img/paths-examples.png"><img alt="Diagram of three example paths" src="img/paths-examples.png"/></a></p>
|
||||
<h1 id="technical-details">Technical Details</h1>
|
||||
<h2 id="pathfinding">Pathfinding</h2>
|
||||
<p>The <code>rippled</code> API has two methods that can be used for pathfinding. The <a href="reference-rippled.html#ripple-path-find"><code>ripple_path_find</code> command</a> does a one-time lookup of possible path sets. The <a href="reference-rippled.html#path-find"><code>path_find</code> command</a> (WebSocket only) expands on the initial search with follow-up responses whenever a ledger closes or the server finds a better path.</p>
|
||||
<p>You can have <code>rippled</code> automatically fill in paths when you sign it, by including the <code>build_path</code> field in a request to the <a href="reference-rippled.html#sign"><code>sign</code> command</a> or <a href="reference-rippled.html#sign-and-submit-mode"><code>submit</code> command (sign-and-submit mode)</a>. However, we recommend pathfinding separately and confirming the results prior to signing, in order to avoid surprises. There are no guarantees on how expensive the paths the server finds will be at the time of submission. (Although <code>rippled</code> is designed to search for the cheapest paths possible, it may not always find them. Untrustworthy <code>rippled</code> instances could also be modified to change this behavior for profit.)</p>
|
||||
<p>Finding paths is a very challenging problem that changes slightly every few seconds as new ledgers are validated, so <code>rippled</code> is not designed to find the absolute best path. Still, you can find several possible paths and estimate the cost of delivering a particular amount.</p>
|
||||
<h2 id="implied-steps">Implied Steps</h2>
|
||||
<p>By convention, several steps of a path are implied by the <a href="reference-transaction-format.html#payment">fields of the Payment transaction</a>: specifically, the <code>Account</code> (sender), <code>Destination</code> (receiver), <code>Amount</code> (currency and amount to be delivered) and <code>SendMax</code> (currency and amount to be sent, if specified). The implied steps are as follows:</p>
|
||||
<ul>
|
||||
<li>The first step of a path is always implied to be the sender of the transaction, as defined by the transaction's <code>Account</code> field.</li>
|
||||
<li>If the transaction includes a <code>SendMax</code> field with an <code>issuer</code> that is not the sender of the transaction, that issuer is implied to be the second step of the path.<ul>
|
||||
<li>If <code>issuer</code> of the <code>SendMax</code> <em>is</em> the sending account, then the path starts at the sending account, and may use any of that account's trust lines in the given currency. See <a href="reference-transaction-format.html#special-issuer-values-for-sendmax-and-amount">special values for SendMax and Amount</a> for details.</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li>If the <code>Amount</code> field of the transaction includes an <code>issuer</code> that is not the same as the <code>Destination</code> of the transaction, that issuer is implied to be the second-to-last step of the path.</li>
|
||||
<li>Finally, last step of a path is always implied to be the receiver of a transaction, as defined by the transaction's <code>Destination</code> field.</li>
|
||||
</ul>
|
||||
<h2 id="default-paths">Default Paths</h2>
|
||||
<p>In addition to any paths that are specified in the transaction, a transaction can also execute along the <em>default path</em>. The default path is the simplest possible way to connect the <a href="#implied-steps">implied steps</a> of the transaction.</p>
|
||||
<p>The default path could be any of the following:</p>
|
||||
<ul>
|
||||
<li>If the transaction is uses only one currency (regardless of issuer), then the default path assumes the payment will ripple through the accounts involved. This path will only work if there are trust lines connecting those accounts.<ul>
|
||||
<li>If <code>SendMax</code> is omitted, or the <code>issuer</code> of the <code>SendMax</code> is the sender, the default path needs a trust line from the sending <code>Account</code> to the <code>issuer</code> of the destination <code>Amount</code> in order to work.</li>
|
||||
<li>If the <code>SendMax</code> and <code>Amount</code> have different <code>issuer</code> values, and neither are the sender or receiver, the default path is probably not useful because it would need to ripple across a trust line between the two issuers. Ripple, Inc. typically discourages issuers from trusting one another directly.</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li>For cross-currency transactions, the default path uses the order book between the source currency (as specified in the <code>SendMax</code> field) and the destination currency (as specified in the <code>Amount</code> field).</li>
|
||||
</ul>
|
||||
<p>The following diagram enumerates all possible default paths:
|
||||
<a href="img/paths-default_paths.png"><img alt="Diagram of default paths" src="img/paths-default_paths.png"/></a></p>
|
||||
<p>You can use the <a href="reference-transaction-format.html#payment-flags"><code>tfNoDirectRipple</code> flag</a> to disable the default path. In this case, the transaction can only execute using the paths explicitly included in the transaction. Traders can use this option to take arbitrage opportunities.</p>
|
||||
<h2 id="path-specifications">Path Specifications</h2>
|
||||
<p>A path set is an array. Each member of the path set is another array that represents an individual <em>path</em>. Each member of a path is an object that specifies the step. A step has the following fields:</p>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Field</th>
|
||||
<th>Value</th>
|
||||
<th>Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>account</td>
|
||||
<td>String - Address</td>
|
||||
<td>(Optional) If present, this path step represents rippling through the specified account.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>currency</td>
|
||||
<td>String - currency code</td>
|
||||
<td>(Optional) If present, this path step represents changing currencies through an order book. The currency specified indicates the new currency.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>issuer</td>
|
||||
<td>String - Address</td>
|
||||
<td>(Optional) If the path step represents changing currencies through an order book, this field indicates the issuer of the new currency. This field is not present when changing to XRP.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>type</td>
|
||||
<td>Integer</td>
|
||||
<td><strong>DEPRECATED</strong> (Optional) An indicator of which other fields are present.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>type_hex</td>
|
||||
<td>String</td>
|
||||
<td><strong>DEPRECATED</strong>: (Optional) A hexadecimal representation of the <code>type</code> field.</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<p>The <code>type</code> field, used for the binary serialization of a path set, is actually constructed through bitwise operations on a single integer. The bits are defined as follows:</p>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Value (Hex)</th>
|
||||
<th>Value (Decimal)</th>
|
||||
<th>Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>0x01</td>
|
||||
<td>1</td>
|
||||
<td>A change of account (rippling): the <code>account</code> field is present.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>0x10</td>
|
||||
<td>16</td>
|
||||
<td>A change of currency: the <code>currency</code> field is present.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>0x20</td>
|
||||
<td>32</td>
|
||||
<td>A change of issuer: the <code>issuer</code> field is present.</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</main>
|
||||
</div>
|
||||
|
||||
<footer class="content-info" role="contentinfo">
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
|
||||
<section class="col-sm-3 widget nav_menu-3 widget_nav_menu">
|
||||
<h4>Resources<hr></h4>
|
||||
<ul id="menu-resources" class="menu">
|
||||
<li class="menu-insights"><a href="https://ripple.com/insights/">Insights</a></li>
|
||||
<li class="menu-press-center"><a href="https://ripple.com/press-center/">Press Center</a></li>
|
||||
<li class="menu-media-resources"><a href="https://ripple.com/media-resources/">Media Resources</a></li>
|
||||
<li class="menu-videos"><a href="https://ripple.com/videos/">Videos</a></li>
|
||||
<li class="menu-whitepapers-reports"><a href="https://ripple.com/whitepapers-reports/">Whitepapers & Reports</a></li>
|
||||
<li class="menu-xrp-portal"><a href="https://ripple.com/xrp-portal/">XRP Portal</a></li>
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
<section class="col-sm-3 widget nav_menu-5 widget_nav_menu">
|
||||
<h4>Regulators<hr></h4>
|
||||
<ul id="menu-compliance-regulatory-relations" class="menu"><li class="menu-compliance"><a href="https://ripple.com/compliance/">Compliance</a></li>
|
||||
<li class="menu-policy-framework"><a href="https://ripple.com/policy-framework/">Policy Framework</a></li>
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
<section class="col-sm-3 widget nav_menu-4 widget_nav_menu">
|
||||
<h4>Support<hr></h4>
|
||||
<ul id="menu-dev-footer-menu" class="menu">
|
||||
<li class="menu-contact-us"><a href="https://ripple.com/contact/">Contact Us</a></li>
|
||||
<li class="active menu-developer-center"><a href="https://ripple.com/build/">Developer Center</a></li>
|
||||
<li class="menu-knowledge-center"><a href="https://ripple.com/learn/">Knowledge Center</a></li>
|
||||
<li class="menu-ripple-forum"><a target="_blank" href="https://forum.ripple.com/">Ripple Forum</a></li>
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
<section class="col-sm-3 widget nav_menu-2 widget_nav_menu">
|
||||
<h4>About<hr></h4>
|
||||
<ul id="menu-company-footer" class="menu">
|
||||
<li class="menu-our-company"><a href="https://ripple.com/company/">Our Company</a></li>
|
||||
<li class="menu-careers"><a href="https://ripple.com/company/careers/">Careers</a></li>
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
<div class="col-sm-12 absolute_bottom_footer">
|
||||
<div class="col-sm-8">
|
||||
<span>© 2013-2015 Ripple Labs, Inc. All Rights Reserved.</span>
|
||||
<span><a href="https://ripple.com/terms-of-use/">Terms</a></span>
|
||||
<span><a href="https://ripple.com/privacy-policy/">Privacy</a></span>
|
||||
</div>
|
||||
</div><!-- /.absolute_bottom_footer -->
|
||||
|
||||
</div><!-- /.row -->
|
||||
</div><!-- /.container -->
|
||||
</footer>
|
||||
</body>
|
||||
</html>
|
||||
232
concept-reserves.html
Normal file
@@ -0,0 +1,232 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
|
||||
<meta name="viewport" content="width=device-width">
|
||||
|
||||
<title>Reserves - Ripple Developer Portal</title>
|
||||
|
||||
<!-- favicon -->
|
||||
<link rel="icon" href="favicon.ico" type="image/x-icon">
|
||||
<link rel="shortcut icon" href="favicon.ico" type="image/x-icon">
|
||||
|
||||
<!-- jQuery -->
|
||||
<script src="assets/vendor/jquery-1.11.1.min.js"></script>
|
||||
|
||||
<!-- Custom Stylesheets. ripple.css includes bootstrap, font stuff -->
|
||||
<link href="assets/css/ripple.css" rel="stylesheet" />
|
||||
<link href="assets/css/devportal.css" rel="stylesheet" />
|
||||
|
||||
<!-- Bootstrap JS -->
|
||||
<script src="assets/vendor/bootstrap.min.js"></script>
|
||||
|
||||
|
||||
<!-- syntax highlighting -->
|
||||
<link rel="stylesheet" href="assets/vendor/docco.min.css">
|
||||
<script src="assets/vendor/highlight.min.js"></script>
|
||||
|
||||
<!-- syntax selection js -->
|
||||
<script src="assets/js/multicodetab.js"></script>
|
||||
<script>
|
||||
$(document).ready(function() {
|
||||
$().multicode_tabs();
|
||||
hljs.initHighlighting();
|
||||
make_code_expandable();
|
||||
});
|
||||
</script>
|
||||
|
||||
<script src="assets/js/expandcode.js"></script>
|
||||
<script src="assets/js/fixsidebarscroll.js"></script>
|
||||
|
||||
</head>
|
||||
|
||||
<body class="page page-template page-template-template-dev-portal page-template-template-dev-portal-php sidebar-primary wpb-js-composer js-comp-ver-3.6.2 vc_responsive">
|
||||
<header role="banner" class="banner navbar navbar-default navbar-fixed-top initial_header">
|
||||
<div class="container">
|
||||
<div class="navbar-header">
|
||||
<a href="index.html" class="navbar-brand"><img src="assets/img/ripple-logo-color.png" class="logo"></a>
|
||||
</div><!-- /.navbar-header -->
|
||||
<div class="nav">
|
||||
<div class="draft-warning">DRAFT PAGE</div>
|
||||
</div><!-- /.nav -->
|
||||
|
||||
</div><!-- /.container -->
|
||||
|
||||
<div class="subnav dev_nav">
|
||||
<div class="container">
|
||||
<ul id="menu-dev-menu" class="menu">
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">References <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="reference-rippled.html">rippled</a></li>
|
||||
<li><a href="reference-transaction-format.html">Transaction Format</a></li>
|
||||
<li><a href="reference-ledger-format.html">Ledger Format</a></li>
|
||||
<li><a href="reference-rippleapi.html">RippleAPI</a></li>
|
||||
<li><a href="reference-data-api.html">Ripple Data API v2</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Tutorials <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="tutorial-rippleapi-beginners-guide.html">RippleAPI Beginners Guide</a></li>
|
||||
<li><a href="tutorial-rippled-setup.html">rippled Setup</a></li>
|
||||
<li><a href="tutorial-reliable-transaction-submission.html">Reliable Transaction Submission</a></li>
|
||||
<li><a href="tutorial-multisign.html">How to Multi-Sign</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Concepts <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="concept-paths.html">Paths</a></li>
|
||||
<li><a href="concept-fees.html">Fees (Disambiguation)</a></li>
|
||||
<li><a href="concept-transfer-fees.html">Transfer Fees</a></li>
|
||||
<li><a href="concept-transaction-cost.html">Transaction Cost</a></li>
|
||||
<li><a href="concept-fee-voting.html">Fee Voting</a></li>
|
||||
<li><a href="concept-reserves.html">Reserves</a></li>
|
||||
<li><a href="concept-freeze.html">Freeze</a></li>
|
||||
<li><a href="concept-amendments.html">Amendments</a></li>
|
||||
<li><a href="concept-stand-alone-mode.html">Stand-Alone Mode</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Best Practices <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="concept-issuing-and-operational-addresses.html">Issuing and Operational Addresses</a></li>
|
||||
<li><a href="tutorial-gateway-guide.html">Gateway Guide</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">API Tools <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="ripple-api-tool.html">WebSocket API Tool</a></li>
|
||||
<li><a href="data-api-v2-tool.html">Data API v2 Tool</a></li>
|
||||
<li><a href="tool-jsonrpc.html">rippled JSON-RPC Tool</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Resources <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="https://forum.ripple.com/viewforum.php?f=2">Forums</a></li>
|
||||
<li><a href="https://www.bountysource.com/teams/ripple/bounties">Bounties</a></li>
|
||||
<li><a href="https://ripplelabs.atlassian.net/">Bug Tracking</a></li>
|
||||
<li><a href="https://ripple.com/category/dev-blog/">Dev Blog</a></li>
|
||||
<li><a href="https://ripple.com/press-releases/">Press Center</a></li>
|
||||
<li><a href="https://ripple.com/brand-guidelines/">Brand Guidelines</a></li>
|
||||
</ul>
|
||||
<li><a href="https://github.com/ripple/ripple-dev-portal" title="GitHub">Site Source</a></li>
|
||||
</ul><!-- /#dev-menu -->
|
||||
</div><!-- /.subnav .container -->
|
||||
</div><!-- /.subnav -->
|
||||
</header>
|
||||
|
||||
|
||||
<div class="wrap container" role="document">
|
||||
<aside class="sidebar" role="complementary">
|
||||
<div class="dev_nav_wrapper">
|
||||
<div id="cont">
|
||||
<ul class="dev_nav_sidebar">
|
||||
<li class="level-1"><a href="index.html">Category: Concepts</a></li>
|
||||
<li class="level-2"><a href="concept-paths.html">Paths</a></li>
|
||||
<li class="level-2"><a href="concept-fees.html">Fees (Disambiguation)</a></li>
|
||||
<li class="level-2"><a href="concept-transfer-fees.html">Transfer Fees</a></li>
|
||||
<li class="level-2"><a href="concept-transaction-cost.html">Transaction Cost</a></li>
|
||||
<li class="level-2"><a href="concept-fee-voting.html">Fee Voting</a></li>
|
||||
<li class="level-2"><a href="concept-reserves.html">Reserves</a></li>
|
||||
<li class="level-2"><a href="concept-freeze.html">Freeze</a></li>
|
||||
<li class="level-2"><a href="concept-amendments.html">Amendments</a></li>
|
||||
<li class="level-2"><a href="concept-stand-alone-mode.html">Stand-Alone Mode</a></li>
|
||||
</ul>
|
||||
<hr />
|
||||
<h5>In this page:</h5>
|
||||
</div>
|
||||
<script type="text/javascript" src="assets/js/jquery.gensidebar.js"></script>
|
||||
</div>
|
||||
</aside>
|
||||
<main class="main" role="main">
|
||||
<div class='content'>
|
||||
<h1 id="reserves">Reserves</h1>
|
||||
<p>The Ripple Consensus Ledger applies <em>reserve requirements</em>, in XRP, to protect the shared global ledger from growing excessively large as the result of spam or malicious usage. The goal is to constrain the growth of the ledger to match <a href="https://en.wikipedia.org/wiki/Moore's_law">Moore's Law</a> so that a current commodity-level machine can always fit the current ledger in RAM and the full ledger history on disk.</p>
|
||||
<p>Each account in the shared global ledger must hold a minimum of XRP in order to submit transactions, and it cannot send this XRP to other accounts. You cannot create a new account unless you send enough XRP to meet the minimum reserve requirement.</p>
|
||||
<p>The current minimum reserve requirement is <strong>20 XRP</strong>. (This is the cost of an account that owns no additional objects in the ledger.)</p>
|
||||
<h2 id="base-reserve-and-owner-reserve">Base Reserve and Owner Reserve</h2>
|
||||
<p>The reserve requirement is divided into two parts:</p>
|
||||
<ul>
|
||||
<li>The <strong>Base Reserve</strong> is a minimum amount of XRP that is required for every account in the ledger. Currently, this is 20 XRP (<code>20000000</code> drops).</li>
|
||||
<li>The <strong>Owner Reserve</strong> is an additional requirement that scales with the number of objects that the account owns in the ledger. Currently, this is 5 XRP (<code>5000000</code> drops) per item.</li>
|
||||
</ul>
|
||||
<h3 id="owner-reserves">Owner Reserves</h3>
|
||||
<p>Many objects in the ledger are owned by a particular account, and therefore count toward the reserve requirement of that account. When objects are removed from the ledger, they no longer count against their owner's reserve requirement.</p>
|
||||
<ul>
|
||||
<li><a href="reference-ledger-format.html#offer">Offers</a> are owned by the account that placed them. An Offer can be automatically removed from the ledger if it is fully consumed or if it is found unfunded during transaction processing. Alternatively, the owner can cancel an offer by sending an <a href="reference-transaction-format.html#offercancel">OfferCancel transaction</a>, or by sending an <a href="reference-transaction-format.html#offercreate">OfferCreate transaction</a> that contains an <code>OfferSequence</code> parameter.</li>
|
||||
<li><a href="reference-ledger-format.html#ripplestate">Trust lines</a> are shared between two accounts. The owner reserve can apply to one or both of the accounts, depending on whether the fields that account controls are in their default state. See <a href="reference-ledger-format.html#contributing-to-the-owner-reserve">Contributing to the Owner Reserve</a> for details.</li>
|
||||
<li>A single <a href="reference-ledger-format.html#signerlist">SignerList</a> counts as 3 to 10 objects for purposes of the owner reserve, depending on how many members it has. See also: <a href="reference-ledger-format.html#signerlists-and-reserves">SignerLists and Reserves</a>.</li>
|
||||
<li><a href="reference-ledger-format.html#directorynode">Owner directories</a> list all the ledger nodes that contribute to an account's owner reserve. However, the owner directory itself does not count towards the reserve.</li>
|
||||
</ul>
|
||||
<h4 id="owner-reserve-edge-cases">Owner Reserve Edge Cases</h4>
|
||||
<p>The Ripple Consensus Ledger considers an <a href="reference-transaction-format.html#offercreate">OfferCreate transaction</a> to be an explicit statement of willingness to hold an asset. Consuming the offer automatically creates a trust line (with limit 0, and a balance above that limit) for the <code>taker_pays</code> currency if such a trust line does not exist. However, if the offer's owner does not possess enough XRP to meet the additional reserve requirement of the new trust line, the offer is considered unfunded. See also: <a href="reference-transaction-format.html#lifecycle-of-an-offer">Lifecycle of an Offer</a>.</p>
|
||||
<h2 id="going-below-the-reserve-requirement">Going Below the Reserve Requirement</h2>
|
||||
<p>During transaction processing, a transaction can only be successful if the sending account possesses at least the reserve requirement in XRP. In the process, the <a href="concept-transaction-cost.html">transaction cost</a> destroys some of the sending account's XRP balance. This can cause an account to go below the reserve requirement.</p>
|
||||
<p>When an account has less XRP than its current reserve requirement, it cannot send new transactions. Even so, it continues to exist in the ledger, as all accounts do. Unless the reserve requirements decrease, the only way for the account to become able to send transactions again is for it to receive enough XRP that it meets the reserve requirement.</p>
|
||||
<p><strong>Exception:</strong> When an account is below the reserve requirement, it can send new <a href="reference-transaction-format.html#offercreate">OfferCreate transactions</a> to acquire more XRP, or other currencies on its existing trust lines. These transactions cannot create new <a href="reference-ledger-format.html#ripplestate">trust lines</a>, or <a href="reference-ledger-format.html#offer">Offer nodes in the ledger</a>, so they can only execute trades that consume Offers that are already in the order books.</p>
|
||||
<h2 id="changing-the-reserve-requirements">Changing the Reserve Requirements</h2>
|
||||
<p>The Ripple Consensus Ledger has a mechanism for changing the reserve requirements in order to account for long-term changes in the value of XRP. Any changes have to be approved by the consensus process. See <a href="concept-fee-voting.html">Fee Voting</a> for more information.</p>
|
||||
</div>
|
||||
</main>
|
||||
</div>
|
||||
|
||||
<footer class="content-info" role="contentinfo">
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
|
||||
<section class="col-sm-3 widget nav_menu-3 widget_nav_menu">
|
||||
<h4>Resources<hr></h4>
|
||||
<ul id="menu-resources" class="menu">
|
||||
<li class="menu-insights"><a href="https://ripple.com/insights/">Insights</a></li>
|
||||
<li class="menu-press-center"><a href="https://ripple.com/press-center/">Press Center</a></li>
|
||||
<li class="menu-media-resources"><a href="https://ripple.com/media-resources/">Media Resources</a></li>
|
||||
<li class="menu-videos"><a href="https://ripple.com/videos/">Videos</a></li>
|
||||
<li class="menu-whitepapers-reports"><a href="https://ripple.com/whitepapers-reports/">Whitepapers & Reports</a></li>
|
||||
<li class="menu-xrp-portal"><a href="https://ripple.com/xrp-portal/">XRP Portal</a></li>
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
<section class="col-sm-3 widget nav_menu-5 widget_nav_menu">
|
||||
<h4>Regulators<hr></h4>
|
||||
<ul id="menu-compliance-regulatory-relations" class="menu"><li class="menu-compliance"><a href="https://ripple.com/compliance/">Compliance</a></li>
|
||||
<li class="menu-policy-framework"><a href="https://ripple.com/policy-framework/">Policy Framework</a></li>
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
<section class="col-sm-3 widget nav_menu-4 widget_nav_menu">
|
||||
<h4>Support<hr></h4>
|
||||
<ul id="menu-dev-footer-menu" class="menu">
|
||||
<li class="menu-contact-us"><a href="https://ripple.com/contact/">Contact Us</a></li>
|
||||
<li class="active menu-developer-center"><a href="https://ripple.com/build/">Developer Center</a></li>
|
||||
<li class="menu-knowledge-center"><a href="https://ripple.com/learn/">Knowledge Center</a></li>
|
||||
<li class="menu-ripple-forum"><a target="_blank" href="https://forum.ripple.com/">Ripple Forum</a></li>
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
<section class="col-sm-3 widget nav_menu-2 widget_nav_menu">
|
||||
<h4>About<hr></h4>
|
||||
<ul id="menu-company-footer" class="menu">
|
||||
<li class="menu-our-company"><a href="https://ripple.com/company/">Our Company</a></li>
|
||||
<li class="menu-careers"><a href="https://ripple.com/company/careers/">Careers</a></li>
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
<div class="col-sm-12 absolute_bottom_footer">
|
||||
<div class="col-sm-8">
|
||||
<span>© 2013-2015 Ripple Labs, Inc. All Rights Reserved.</span>
|
||||
<span><a href="https://ripple.com/terms-of-use/">Terms</a></span>
|
||||
<span><a href="https://ripple.com/privacy-policy/">Privacy</a></span>
|
||||
</div>
|
||||
</div><!-- /.absolute_bottom_footer -->
|
||||
|
||||
</div><!-- /.row -->
|
||||
</div><!-- /.container -->
|
||||
</footer>
|
||||
</body>
|
||||
</html>
|
||||
263
concept-stand-alone-mode.html
Normal file
@@ -0,0 +1,263 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
|
||||
<meta name="viewport" content="width=device-width">
|
||||
|
||||
<title>Stand-Alone Mode - Ripple Developer Portal</title>
|
||||
|
||||
<!-- favicon -->
|
||||
<link rel="icon" href="favicon.ico" type="image/x-icon">
|
||||
<link rel="shortcut icon" href="favicon.ico" type="image/x-icon">
|
||||
|
||||
<!-- jQuery -->
|
||||
<script src="assets/vendor/jquery-1.11.1.min.js"></script>
|
||||
|
||||
<!-- Custom Stylesheets. ripple.css includes bootstrap, font stuff -->
|
||||
<link href="assets/css/ripple.css" rel="stylesheet" />
|
||||
<link href="assets/css/devportal.css" rel="stylesheet" />
|
||||
|
||||
<!-- Bootstrap JS -->
|
||||
<script src="assets/vendor/bootstrap.min.js"></script>
|
||||
|
||||
|
||||
<!-- syntax highlighting -->
|
||||
<link rel="stylesheet" href="assets/vendor/docco.min.css">
|
||||
<script src="assets/vendor/highlight.min.js"></script>
|
||||
|
||||
<!-- syntax selection js -->
|
||||
<script src="assets/js/multicodetab.js"></script>
|
||||
<script>
|
||||
$(document).ready(function() {
|
||||
$().multicode_tabs();
|
||||
hljs.initHighlighting();
|
||||
make_code_expandable();
|
||||
});
|
||||
</script>
|
||||
|
||||
<script src="assets/js/expandcode.js"></script>
|
||||
<script src="assets/js/fixsidebarscroll.js"></script>
|
||||
|
||||
</head>
|
||||
|
||||
<body class="page page-template page-template-template-dev-portal page-template-template-dev-portal-php sidebar-primary wpb-js-composer js-comp-ver-3.6.2 vc_responsive">
|
||||
<header role="banner" class="banner navbar navbar-default navbar-fixed-top initial_header">
|
||||
<div class="container">
|
||||
<div class="navbar-header">
|
||||
<a href="index.html" class="navbar-brand"><img src="assets/img/ripple-logo-color.png" class="logo"></a>
|
||||
</div><!-- /.navbar-header -->
|
||||
<div class="nav">
|
||||
<div class="draft-warning">DRAFT PAGE</div>
|
||||
</div><!-- /.nav -->
|
||||
|
||||
</div><!-- /.container -->
|
||||
|
||||
<div class="subnav dev_nav">
|
||||
<div class="container">
|
||||
<ul id="menu-dev-menu" class="menu">
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">References <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="reference-rippled.html">rippled</a></li>
|
||||
<li><a href="reference-transaction-format.html">Transaction Format</a></li>
|
||||
<li><a href="reference-ledger-format.html">Ledger Format</a></li>
|
||||
<li><a href="reference-rippleapi.html">RippleAPI</a></li>
|
||||
<li><a href="reference-data-api.html">Ripple Data API v2</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Tutorials <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="tutorial-rippleapi-beginners-guide.html">RippleAPI Beginners Guide</a></li>
|
||||
<li><a href="tutorial-rippled-setup.html">rippled Setup</a></li>
|
||||
<li><a href="tutorial-reliable-transaction-submission.html">Reliable Transaction Submission</a></li>
|
||||
<li><a href="tutorial-multisign.html">How to Multi-Sign</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Concepts <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="concept-paths.html">Paths</a></li>
|
||||
<li><a href="concept-fees.html">Fees (Disambiguation)</a></li>
|
||||
<li><a href="concept-transfer-fees.html">Transfer Fees</a></li>
|
||||
<li><a href="concept-transaction-cost.html">Transaction Cost</a></li>
|
||||
<li><a href="concept-fee-voting.html">Fee Voting</a></li>
|
||||
<li><a href="concept-reserves.html">Reserves</a></li>
|
||||
<li><a href="concept-freeze.html">Freeze</a></li>
|
||||
<li><a href="concept-amendments.html">Amendments</a></li>
|
||||
<li><a href="concept-stand-alone-mode.html">Stand-Alone Mode</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Best Practices <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="concept-issuing-and-operational-addresses.html">Issuing and Operational Addresses</a></li>
|
||||
<li><a href="tutorial-gateway-guide.html">Gateway Guide</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">API Tools <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="ripple-api-tool.html">WebSocket API Tool</a></li>
|
||||
<li><a href="data-api-v2-tool.html">Data API v2 Tool</a></li>
|
||||
<li><a href="tool-jsonrpc.html">rippled JSON-RPC Tool</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Resources <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="https://forum.ripple.com/viewforum.php?f=2">Forums</a></li>
|
||||
<li><a href="https://www.bountysource.com/teams/ripple/bounties">Bounties</a></li>
|
||||
<li><a href="https://ripplelabs.atlassian.net/">Bug Tracking</a></li>
|
||||
<li><a href="https://ripple.com/category/dev-blog/">Dev Blog</a></li>
|
||||
<li><a href="https://ripple.com/press-releases/">Press Center</a></li>
|
||||
<li><a href="https://ripple.com/brand-guidelines/">Brand Guidelines</a></li>
|
||||
</ul>
|
||||
<li><a href="https://github.com/ripple/ripple-dev-portal" title="GitHub">Site Source</a></li>
|
||||
</ul><!-- /#dev-menu -->
|
||||
</div><!-- /.subnav .container -->
|
||||
</div><!-- /.subnav -->
|
||||
</header>
|
||||
|
||||
|
||||
<div class="wrap container" role="document">
|
||||
<aside class="sidebar" role="complementary">
|
||||
<div class="dev_nav_wrapper">
|
||||
<div id="cont">
|
||||
<ul class="dev_nav_sidebar">
|
||||
<li class="level-1"><a href="index.html">Category: Concepts</a></li>
|
||||
<li class="level-2"><a href="concept-paths.html">Paths</a></li>
|
||||
<li class="level-2"><a href="concept-fees.html">Fees (Disambiguation)</a></li>
|
||||
<li class="level-2"><a href="concept-transfer-fees.html">Transfer Fees</a></li>
|
||||
<li class="level-2"><a href="concept-transaction-cost.html">Transaction Cost</a></li>
|
||||
<li class="level-2"><a href="concept-fee-voting.html">Fee Voting</a></li>
|
||||
<li class="level-2"><a href="concept-reserves.html">Reserves</a></li>
|
||||
<li class="level-2"><a href="concept-freeze.html">Freeze</a></li>
|
||||
<li class="level-2"><a href="concept-amendments.html">Amendments</a></li>
|
||||
<li class="level-2"><a href="concept-stand-alone-mode.html">Stand-Alone Mode</a></li>
|
||||
</ul>
|
||||
<hr />
|
||||
<h5>In this page:</h5>
|
||||
</div>
|
||||
<script type="text/javascript" src="assets/js/jquery.gensidebar.js"></script>
|
||||
</div>
|
||||
</aside>
|
||||
<main class="main" role="main">
|
||||
<div class='content'>
|
||||
<h1 id="stand-alone-mode">Stand-Alone Mode</h1>
|
||||
<p>You can run <code>rippled</code> in stand-alone mode without a consensus of trusted servers. In stand-alone mode, <code>rippled</code> does not communicate with any other servers in the Ripple peer-to-peer network, but you can do most of the same actions on your local server only. Stand-alone provides a method for testing <code>rippled</code> behavior without being tied to the live network. For example, you can <a href="concept-amendments.html#testing-amendments">test the effects of Amendments</a> before those Amendments have gone into effect across the decentralized network.</p>
|
||||
<p>When you run <code>rippled</code> in stand-alone mode, you have to tell it what ledger version to start from:</p>
|
||||
<ul>
|
||||
<li>Create a <a href="#new-genesis-ledger">new genesis ledger</a> from scratch.</li>
|
||||
<li><a href="#load-saved-ledger">Load an existing ledger version</a> from disk.</li>
|
||||
</ul>
|
||||
<p><strong>Caution:</strong> In stand-alone mode, you must <a href="#advancing-ledgers-in-stand-alone-mode">manually advance the ledger</a>.</p>
|
||||
<h2 id="new-genesis-ledger">New Genesis Ledger</h2>
|
||||
<p>In stand-alone mode, you can have <code>rippled</code> create a new genesis ledger. This provides a known state, with none of the ledger history from the production Ripple Consensus Ledger. (This is very useful for unit tests, among other things.)</p>
|
||||
<ul>
|
||||
<li>To start <code>rippled</code> in stand-alone mode with a new genesis ledger, use the <code>-a</code> and <code>--start</code> options:</li>
|
||||
</ul>
|
||||
<pre><code>rippled -a --start --conf=/path/to/rippled.cfg
|
||||
</code></pre>
|
||||
<p>In a genesis ledger, the <a href="reference-rippled.html#special-addresses">genesis address</a> holds all 100 billion XRP. The keys of the genesis address are <a href="https://github.com/ripple/rippled/blob/94ed5b3a53077d815ad0dd65d490c8d37a147361/src/ripple/app/ledger/Ledger.cpp#L184">hardcoded</a> as follows:</p>
|
||||
<p><strong>Address:</strong> <code>rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh</code></p>
|
||||
<p><strong>Secret:</strong> <code>snoPBrXtMeMyMHUVTgbuqAfg1SUTb</code> ("masterpassphrase")</p>
|
||||
<p><strong>Caution:</strong> If you create a new genesis ledger, the hard-coded default <a href="concept-reserves.html">Reserve</a> is <strong>200 XRP</strong> minimum for funding a new address, with an increment of <strong>50 XRP</strong> per object in the ledger. These values are higher than the current reserve requirements of the production network. (See also: <a href="concept-fee-voting.html">Fee Voting</a>)</p>
|
||||
<h2 id="load-saved-ledger">Load Saved Ledger</h2>
|
||||
<p>You can start with a ledger version that was saved to disk if your <code>rippled</code> server was previously synced with the Ripple peer-to-peer network (either the production network or the <a href="tutorial-rippled-setup.html#parallel-networks">Test Net</a>).</p>
|
||||
<h3 id="1-start-rippled-normally">1. Start <code>rippled</code> normally.</h3>
|
||||
<p>To load an existing ledger, you must first retrieve that ledger from the network. Start <code>rippled</code> in networked mode as normal:</p>
|
||||
<pre><code>rippled --conf=/path/to/rippled.cfg
|
||||
</code></pre>
|
||||
<h3 id="2-wait-until-rippled-is-synced">2. Wait until <code>rippled</code> is synced.</h3>
|
||||
<p>Use the <a href="reference-rippled.html#server-info"><code>server_info</code> command</a> to check the state of your server relative to the network. Your server is synced when the <code>server_state</code> value shows any of the following values:</p>
|
||||
<ul>
|
||||
<li><code>full</code></li>
|
||||
<li><code>proposing</code></li>
|
||||
<li><code>validating</code>.</li>
|
||||
</ul>
|
||||
<h3 id="3-optional-retrieve-specific-ledger-versions">3. (Optional) Retrieve specific ledger versions.</h3>
|
||||
<p>If you only want the most recent ledger, you can skip this step.</p>
|
||||
<p>If you want to load a specific historical ledger version, use the <a href="reference-rippled.html#ledger-request"><code>ledger_request</code> command</a> to make <code>rippled</code> fetch it. If <code>rippled</code> does not already have the ledger version, you may have to run the <code>ledger_request</code> command multiple times until it has finished retrieving the ledger.</p>
|
||||
<p>If you want to replay a specific historical ledger version, you must fetch both the ledger version to replay and the ledger version immediately before it.</p>
|
||||
<h3 id="4-shut-down-rippled">4. Shut down <code>rippled</code>.</h3>
|
||||
<p>Use the <a href="reference-rippled.html#stop"><code>stop</code> command</a>:</p>
|
||||
<pre><code>rippled stop --conf=/path/to/rippled.cfg
|
||||
</code></pre>
|
||||
<h3 id="5-start-rippled-in-stand-alone-mode">5. Start <code>rippled</code> in stand-alone mode.</h3>
|
||||
<p>To load the most recent ledger version, you can use the <code>-a</code> and <code>--load</code> options when starting the server:</p>
|
||||
<pre><code>rippled -a --load --conf=/path/to/rippled.cfg
|
||||
</code></pre>
|
||||
<p>To instead load a specific historical ledger, use the <code>--load</code> parameter along with the <code>--ledger</code> parameter, providing the ledger index or identifying hash of the ledger version to load:</p>
|
||||
<pre><code>rippled -a --load --ledger 19860944 --conf=/path/to/rippled.cfg
|
||||
</code></pre>
|
||||
<h3 id="6-manually-advance-the-ledger">6. Manually advance the ledger.</h3>
|
||||
<p>When you load a ledger with <code>--ledger</code> in stand-alone mode, it goes to the current open ledger, so you must <a href="#advancing-ledgers-in-stand-alone-mode">manually advance the ledger</a>:</p>
|
||||
<pre><code>rippled ledger_accept --conf=/path/to/rippled.cfg
|
||||
</code></pre>
|
||||
<h2 id="advancing-ledgers-in-stand-alone-mode">Advancing Ledgers in Stand-Alone Mode</h2>
|
||||
<p>In stand-alone mode, <code>rippled</code> does not communicate to other members of the peer-to-peer network or participate in a consensus process. Instead, you must manually advance the ledger index using the <a href="reference-rippled.html#ledger-accept"><code>ledger_accept</code> command</a>:</p>
|
||||
<pre><code>rippled ledger_accept --conf=/path/to/rippled.cfg
|
||||
</code></pre>
|
||||
<p>In stand-alone mode, <code>rippled</code> makes no distinction between a "closed" ledger version and a "validated" ledger version. (For more information about the difference, see <a href="https://ripple.com/knowledge_center/the-ripple-ledger-consensus-process/">The Ripple Ledger Consensus Process</a>.)</p>
|
||||
<p>Whenever <code>rippled</code> closes a ledger, it reorders the transactions according to a deterministic but hard-to-game algorithm. (This is an important part of consensus, since transactions may arrive at different parts of the network in different order.) When using <code>rippled</code> in stand-alone mode, you should manually advance the ledger before submitting a transaction that depends on the result of a previous transaction. Otherwise, the second transaction might be executed before the first transaction when you manually advance the ledger. <strong>Note:</strong> You can safely submit multiple transactions from a single address to a single ledger, because <code>rippled</code> sorts transactions from the same address in ascending order by <code>Sequence</code> number.</p>
|
||||
</div>
|
||||
</main>
|
||||
</div>
|
||||
|
||||
<footer class="content-info" role="contentinfo">
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
|
||||
<section class="col-sm-3 widget nav_menu-3 widget_nav_menu">
|
||||
<h4>Resources<hr></h4>
|
||||
<ul id="menu-resources" class="menu">
|
||||
<li class="menu-insights"><a href="https://ripple.com/insights/">Insights</a></li>
|
||||
<li class="menu-press-center"><a href="https://ripple.com/press-center/">Press Center</a></li>
|
||||
<li class="menu-media-resources"><a href="https://ripple.com/media-resources/">Media Resources</a></li>
|
||||
<li class="menu-videos"><a href="https://ripple.com/videos/">Videos</a></li>
|
||||
<li class="menu-whitepapers-reports"><a href="https://ripple.com/whitepapers-reports/">Whitepapers & Reports</a></li>
|
||||
<li class="menu-xrp-portal"><a href="https://ripple.com/xrp-portal/">XRP Portal</a></li>
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
<section class="col-sm-3 widget nav_menu-5 widget_nav_menu">
|
||||
<h4>Regulators<hr></h4>
|
||||
<ul id="menu-compliance-regulatory-relations" class="menu"><li class="menu-compliance"><a href="https://ripple.com/compliance/">Compliance</a></li>
|
||||
<li class="menu-policy-framework"><a href="https://ripple.com/policy-framework/">Policy Framework</a></li>
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
<section class="col-sm-3 widget nav_menu-4 widget_nav_menu">
|
||||
<h4>Support<hr></h4>
|
||||
<ul id="menu-dev-footer-menu" class="menu">
|
||||
<li class="menu-contact-us"><a href="https://ripple.com/contact/">Contact Us</a></li>
|
||||
<li class="active menu-developer-center"><a href="https://ripple.com/build/">Developer Center</a></li>
|
||||
<li class="menu-knowledge-center"><a href="https://ripple.com/learn/">Knowledge Center</a></li>
|
||||
<li class="menu-ripple-forum"><a target="_blank" href="https://forum.ripple.com/">Ripple Forum</a></li>
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
<section class="col-sm-3 widget nav_menu-2 widget_nav_menu">
|
||||
<h4>About<hr></h4>
|
||||
<ul id="menu-company-footer" class="menu">
|
||||
<li class="menu-our-company"><a href="https://ripple.com/company/">Our Company</a></li>
|
||||
<li class="menu-careers"><a href="https://ripple.com/company/careers/">Careers</a></li>
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
<div class="col-sm-12 absolute_bottom_footer">
|
||||
<div class="col-sm-8">
|
||||
<span>© 2013-2015 Ripple Labs, Inc. All Rights Reserved.</span>
|
||||
<span><a href="https://ripple.com/terms-of-use/">Terms</a></span>
|
||||
<span><a href="https://ripple.com/privacy-policy/">Privacy</a></span>
|
||||
</div>
|
||||
</div><!-- /.absolute_bottom_footer -->
|
||||
|
||||
</div><!-- /.row -->
|
||||
</div><!-- /.container -->
|
||||
</footer>
|
||||
</body>
|
||||
</html>
|
||||
305
concept-transaction-cost.html
Normal file
@@ -0,0 +1,305 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
|
||||
<meta name="viewport" content="width=device-width">
|
||||
|
||||
<title>Transaction Cost - Ripple Developer Portal</title>
|
||||
|
||||
<!-- favicon -->
|
||||
<link rel="icon" href="favicon.ico" type="image/x-icon">
|
||||
<link rel="shortcut icon" href="favicon.ico" type="image/x-icon">
|
||||
|
||||
<!-- jQuery -->
|
||||
<script src="assets/vendor/jquery-1.11.1.min.js"></script>
|
||||
|
||||
<!-- Custom Stylesheets. ripple.css includes bootstrap, font stuff -->
|
||||
<link href="assets/css/ripple.css" rel="stylesheet" />
|
||||
<link href="assets/css/devportal.css" rel="stylesheet" />
|
||||
|
||||
<!-- Bootstrap JS -->
|
||||
<script src="assets/vendor/bootstrap.min.js"></script>
|
||||
|
||||
|
||||
<!-- syntax highlighting -->
|
||||
<link rel="stylesheet" href="assets/vendor/docco.min.css">
|
||||
<script src="assets/vendor/highlight.min.js"></script>
|
||||
|
||||
<!-- syntax selection js -->
|
||||
<script src="assets/js/multicodetab.js"></script>
|
||||
<script>
|
||||
$(document).ready(function() {
|
||||
$().multicode_tabs();
|
||||
hljs.initHighlighting();
|
||||
make_code_expandable();
|
||||
});
|
||||
</script>
|
||||
|
||||
<script src="assets/js/expandcode.js"></script>
|
||||
<script src="assets/js/fixsidebarscroll.js"></script>
|
||||
|
||||
</head>
|
||||
|
||||
<body class="page page-template page-template-template-dev-portal page-template-template-dev-portal-php sidebar-primary wpb-js-composer js-comp-ver-3.6.2 vc_responsive">
|
||||
<header role="banner" class="banner navbar navbar-default navbar-fixed-top initial_header">
|
||||
<div class="container">
|
||||
<div class="navbar-header">
|
||||
<a href="index.html" class="navbar-brand"><img src="assets/img/ripple-logo-color.png" class="logo"></a>
|
||||
</div><!-- /.navbar-header -->
|
||||
<div class="nav">
|
||||
<div class="draft-warning">DRAFT PAGE</div>
|
||||
</div><!-- /.nav -->
|
||||
|
||||
</div><!-- /.container -->
|
||||
|
||||
<div class="subnav dev_nav">
|
||||
<div class="container">
|
||||
<ul id="menu-dev-menu" class="menu">
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">References <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="reference-rippled.html">rippled</a></li>
|
||||
<li><a href="reference-transaction-format.html">Transaction Format</a></li>
|
||||
<li><a href="reference-ledger-format.html">Ledger Format</a></li>
|
||||
<li><a href="reference-rippleapi.html">RippleAPI</a></li>
|
||||
<li><a href="reference-data-api.html">Ripple Data API v2</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Tutorials <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="tutorial-rippleapi-beginners-guide.html">RippleAPI Beginners Guide</a></li>
|
||||
<li><a href="tutorial-rippled-setup.html">rippled Setup</a></li>
|
||||
<li><a href="tutorial-reliable-transaction-submission.html">Reliable Transaction Submission</a></li>
|
||||
<li><a href="tutorial-multisign.html">How to Multi-Sign</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Concepts <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="concept-paths.html">Paths</a></li>
|
||||
<li><a href="concept-fees.html">Fees (Disambiguation)</a></li>
|
||||
<li><a href="concept-transfer-fees.html">Transfer Fees</a></li>
|
||||
<li><a href="concept-transaction-cost.html">Transaction Cost</a></li>
|
||||
<li><a href="concept-fee-voting.html">Fee Voting</a></li>
|
||||
<li><a href="concept-reserves.html">Reserves</a></li>
|
||||
<li><a href="concept-freeze.html">Freeze</a></li>
|
||||
<li><a href="concept-amendments.html">Amendments</a></li>
|
||||
<li><a href="concept-stand-alone-mode.html">Stand-Alone Mode</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Best Practices <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="concept-issuing-and-operational-addresses.html">Issuing and Operational Addresses</a></li>
|
||||
<li><a href="tutorial-gateway-guide.html">Gateway Guide</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">API Tools <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="ripple-api-tool.html">WebSocket API Tool</a></li>
|
||||
<li><a href="data-api-v2-tool.html">Data API v2 Tool</a></li>
|
||||
<li><a href="tool-jsonrpc.html">rippled JSON-RPC Tool</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Resources <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="https://forum.ripple.com/viewforum.php?f=2">Forums</a></li>
|
||||
<li><a href="https://www.bountysource.com/teams/ripple/bounties">Bounties</a></li>
|
||||
<li><a href="https://ripplelabs.atlassian.net/">Bug Tracking</a></li>
|
||||
<li><a href="https://ripple.com/category/dev-blog/">Dev Blog</a></li>
|
||||
<li><a href="https://ripple.com/press-releases/">Press Center</a></li>
|
||||
<li><a href="https://ripple.com/brand-guidelines/">Brand Guidelines</a></li>
|
||||
</ul>
|
||||
<li><a href="https://github.com/ripple/ripple-dev-portal" title="GitHub">Site Source</a></li>
|
||||
</ul><!-- /#dev-menu -->
|
||||
</div><!-- /.subnav .container -->
|
||||
</div><!-- /.subnav -->
|
||||
</header>
|
||||
|
||||
|
||||
<div class="wrap container" role="document">
|
||||
<aside class="sidebar" role="complementary">
|
||||
<div class="dev_nav_wrapper">
|
||||
<div id="cont">
|
||||
<ul class="dev_nav_sidebar">
|
||||
<li class="level-1"><a href="index.html">Category: Concepts</a></li>
|
||||
<li class="level-2"><a href="concept-paths.html">Paths</a></li>
|
||||
<li class="level-2"><a href="concept-fees.html">Fees (Disambiguation)</a></li>
|
||||
<li class="level-2"><a href="concept-transfer-fees.html">Transfer Fees</a></li>
|
||||
<li class="level-2"><a href="concept-transaction-cost.html">Transaction Cost</a></li>
|
||||
<li class="level-2"><a href="concept-fee-voting.html">Fee Voting</a></li>
|
||||
<li class="level-2"><a href="concept-reserves.html">Reserves</a></li>
|
||||
<li class="level-2"><a href="concept-freeze.html">Freeze</a></li>
|
||||
<li class="level-2"><a href="concept-amendments.html">Amendments</a></li>
|
||||
<li class="level-2"><a href="concept-stand-alone-mode.html">Stand-Alone Mode</a></li>
|
||||
</ul>
|
||||
<hr />
|
||||
<h5>In this page:</h5>
|
||||
</div>
|
||||
<script type="text/javascript" src="assets/js/jquery.gensidebar.js"></script>
|
||||
</div>
|
||||
</aside>
|
||||
<main class="main" role="main">
|
||||
<div class='content'>
|
||||
<h1 id="transaction-cost">Transaction Cost</h1>
|
||||
<p>In order to protect the Ripple Consensus Ledger from being disrupted by spam and denial-of-service attacks, each transaction must destroy a small amount of <a href="https://ripple.com/knowledge_center/math-based-currency-2/">XRP</a>. This <em>transaction cost</em> is designed to increase along with the load on the network, making it very expensive to deliberately or inadvertently overload the network.</p>
|
||||
<p>Every transaction must <a href="#specifying-the-transaction-cost">specify how much XRP it will destroy</a> in order to pay the transaction cost.</p>
|
||||
<h2 id="current-transaction-cost">Current Transaction Cost</h2>
|
||||
<p>The current transaction cost required by the network for a standard transaction is typically <strong>0.01 XRP</strong> (10,000 drops), although it sometimes increases due to network load.</p>
|
||||
<p>You can also <a href="#querying-the-transaction-cost">query <code>rippled</code> for the current transaction cost</a>.</p>
|
||||
<h3 id="special-transaction-costs">Special Transaction Costs</h3>
|
||||
<p>Some transactions have different transaction costs:</p>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Transaction</th>
|
||||
<th>Cost Before Load Scaling</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>Reference Transaction (Standard cost of most transactions)</td>
|
||||
<td>10 drops</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="#key-reset-transaction">Key Reset Transaction</a></td>
|
||||
<td>0</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="reference-transaction-format.html#multi-signing">Multi-signed transaction</a></td>
|
||||
<td>10 drops × (1 + Number of Signatures Provided)</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<h2 id="beneficiaries-of-the-transaction-cost">Beneficiaries of the Transaction Cost</h2>
|
||||
<p>The transaction cost is not paid to any party: the XRP is irrevocably destroyed. Since no new XRP can ever be created, this makes XRP more scarce, and consequently benefits all holders of XRP by making XRP more valuable.</p>
|
||||
<h2 id="load-cost-and-open-ledger-cost">Load Cost and Open Ledger Cost</h2>
|
||||
<p>When the <a href="concept-amendments.html#feeescalation">FeeEscalation amendment</a> is enabled, there are two thresholds for the transaction cost:</p>
|
||||
<ul>
|
||||
<li>If the transaction cost does not meet a <code>rippled</code> server's <a href="#local-load-cost">load-based transaction cost threshold</a>, the server ignores the transaction completely. (This logic is essentially unchanged with or without the amendment.)</li>
|
||||
<li>If the transaction cost does not meet a <code>rippled</code> server's <a href="#open-ledger-cost">open ledger cost threshold</a>, the server queues the transaction for a later ledger.</li>
|
||||
</ul>
|
||||
<p>This divides transactions into roughly three categories:</p>
|
||||
<ul>
|
||||
<li>Transactions that specify a transaction cost so low that they get rejected by the load-based transaction cost.</li>
|
||||
<li>Transactions that specify a transaction cost high enough to be included in the current open ledger.</li>
|
||||
<li>Transactions in between, which get <a href="#queued-transactions">queued for a later ledger version</a>.</li>
|
||||
</ul>
|
||||
<h2 id="local-load-cost">Local Load Cost</h2>
|
||||
<p>Each <code>rippled</code> server maintains a cost threshold based on its current load. If you submit a transaction with a <code>Fee</code> value that is lower than current load-based transaction cost of the <code>rippled</code> server, that server neither applies nor relays the transaction. (<strong>Note:</strong> If you submit a transaction through an <a href="reference-rippled.html#connecting-to-rippled">admin connection</a>, the server applies and relays the transaction as long as the transaction cost meets the overall minimum.) A transaction is very unlikely to survive <a href="https://ripple.com/knowledge_center/the-ripple-ledger-consensus-process/">the consensus process</a> unless its <code>Fee</code> value meets the requirements of a majority of servers.</p>
|
||||
<h2 id="open-ledger-cost">Open Ledger Cost</h2>
|
||||
<p>A <code>rippled</code> server with the <a href="concept-amendments.html#feeescalation">FeeEscalation amendment</a> enabled has a second mechanism for enforcing the transaction cost, called the <em>open ledger cost</em>. The open ledger cost starts out equal to the minimum transaction cost, but increases exponentially when an in-progress ledger has more transactions than the previous one. Only transactions which pay more than the open ledger cost can be included in the current open ledger.
|
||||
Transactions that do not meet the open ledger cost are <a href="#queued-transactions">queued for a following ledger</a> instead.</p>
|
||||
<p>The open ledger cost requirement is proportional to the normal cost of the transaction, not the absolute transaction cost. Transaction types that have a higher-than-normal requirement, such as <a href="reference-transaction-format.html#multi-signing">multi-signed transactions</a> must pay more to meet the open ledger cost than transactions which have minimum transaction cost requirements.</p>
|
||||
<p>See also: <a href="https://github.com/ripple/rippled/blob/release/src/ripple/app/misc/FeeEscalation.md">Fee Escalation explanation in <code>rippled</code> repository</a>.</p>
|
||||
<h3 id="queued-transactions">Queued Transactions</h3>
|
||||
<p>(Requires the <a href="concept-amendments.html#feeescalation">FeeEscalation amendment</a>)</p>
|
||||
<p>When <code>rippled</code> receives a transaction that meet the server's local load cost but not the open ledger cost, the server checks the transaction to see if it is "likely to be included" in a later ledger. If so, the server adds the transaction to the transaction queue and relays the transaction to other members of the network. Otherwise, the server discards the transaction. The server tries minimize the amount of network load caused by transactions that would not pay a transaction cost, since <a href="#transaction-costs-and-failed-transactions">the transaction cost only applies when a transaction is included in a validated ledger</a>.</p>
|
||||
<p>The <code>rippled</code> server uses a variety of heuristics to determine which transactions are "likely to be included in a ledger." Most importantly, those transactions must be properly-formed and <a href="reference-transaction-format.html#authorizing-transactions">authorized</a> with valid signatures.</p>
|
||||
<p>When the current open ledger closes and the server starts a new open ledger, the server starts taking transactions from the queue to include in the new open ledger. The transaction queue is sorted with the transactions that would pay the highest transaction cost first, proportional to the un-scaled cost of those transactions. Transactions that pay the same transaction cost are queued in the order the server receives them.</p>
|
||||
<p><strong>Note:</strong> As of <code>rippled</code> <strong>version 0.31.0</strong>, the transaction queue supports at most 1 transaction per sending address. This is expected to change in later versions.</p>
|
||||
<p><strong>Caution:</strong> The current implementation does not allow transactions with an <code>AccountTxnID</code> field in the transaction queue.</p>
|
||||
<h2 id="querying-the-transaction-cost">Querying the Transaction Cost</h2>
|
||||
<p>The <code>rippled</code> APIs have two ways to query the local load-based transaction cost: the <code>server_info</code> command (intended for humans) and the <code>server_state</code> command (intended for machines).</p>
|
||||
<p>If the <a href="concept-amendments.html#feeescalation">FeeEscalation amendment</a> is enabled, you can use the <a href="reference-rippled.html#fee"><code>fee</code> command</a> to check the open ledger cost.</p>
|
||||
<h3 id="server-info">server_info</h3>
|
||||
<p>The <a href="reference-rippled.html#server-info"><code>server_info</code> command</a> reports the unscaled minimum XRP cost, as of the previous ledger, as <code>validated_ledger.base_fee_xrp</code>, in the form of decimal XRP. The actual cost necessary to relay a transaction is scaled by multiplying that <code>base_fee_xrp</code> value by the <code>load_factor</code> parameter in the same response, which represents the server's current load level. In other words:</p>
|
||||
<p><strong>Current Transaction Cost in XRP = <code>base_fee_xrp</code> × <code>load_factor</code></strong></p>
|
||||
<h3 id="server-state">server_state</h3>
|
||||
<p>The <a href="reference-rippled.html#server-state"><code>server_state</code> command</a> returns a direct representation of <code>rippled</code>'s internal load calculations. In this case, the effective load rate is the ratio of the current <code>load_factor</code> to the <code>load_base</code>. The <code>validated_ledger.base_fee</code> parameter reports the minimum transaction cost in <a href="reference-rippled.html#specifying-currency-amounts">drops of XRP</a>. This design enables <code>rippled</code> to calculate the transaction cost using only integer math, while still allowing a reasonable amount of fine-tuning for server load. The actual calculation of the transaction cost is as follows:</p>
|
||||
<p><strong>Current Transaction Cost in Drops = (<code>base_fee</code> × <code>load_factor</code>) ÷ <code>load_base</code></strong></p>
|
||||
<h2 id="specifying-the-transaction-cost">Specifying the Transaction Cost</h2>
|
||||
<p>Every signed transaction must include the transaction cost in the <a href="reference-transaction-format.html#common-fields"><code>Fee</code> field</a>. Like all fields of a signed transaction, this field cannot be changed without invalidating the signature.</p>
|
||||
<p>As a rule, the Ripple Consensus Ledger executes transactions <em>exactly</em> as they are signed. (To do anything else would be difficult to coordinate across a decentralized consensus network, at the least.) As a consequence of this, every transaction destroys the exact amount of XRP specified by the <code>Fee</code> field, even if it is much more than the current minimum transaction cost for any part of the network. The transaction cost can even destroy XRP that would otherwise be set aside for an account's reserve requirement.</p>
|
||||
<p>Before signing a transaction, we recommend <a href="#querying-the-transaction-cost">looking up the current load-based transaction cost</a>. If the transaction cost is currently high due to load scaling, you may want to wait for it to decrease. If you do not plan on submitting the transaction immediately, we recommend specifying a slightly higher transaction cost to account for future load-based fluctuations in the transaction cost.</p>
|
||||
<h3 id="automatically-specifying-the-transaction-cost">Automatically Specifying the Transaction Cost</h3>
|
||||
<p>When you sign a transaction online, you can omit the <code>Fee</code> field. In this case, <code>rippled</code> or ripple-lib looks up an appropriate value based on the state of the peer-to-peer network, and includes it before signing the transaction. However, there are several drawbacks and limitations to automatically filling in the transaction cost in this manner:</p>
|
||||
<ul>
|
||||
<li>If the network's transaction cost goes up between signing and distributing the transaction, the transaction may not be confirmed.<ul>
|
||||
<li>In the worst case, the transaction may be stuck in a state of being neither definitively confirmed or rejected, unless it included a <code>LastLedgerSequence</code> parameter or until you cancel it with a new transaction that uses the same <code>Sequence</code> number. See <a href="tutorial-reliable-transaction-submission.html">reliable transaction submission</a> for best practices.</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li>You do not know in advance exactly what value you are signing for the <code>Fee</code> field.<ul>
|
||||
<li>If you are using <code>rippled</code>, you can also use the <code>fee_mult_max</code> and <code>fee_div_max</code> parameters of the <a href="reference-rippled.html#sign"><code>sign</code> command</a> to set a limit to the load scaling you are willing to sign.</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li>You cannot look up the current transaction cost from an offline machine.</li>
|
||||
<li>You cannot automatically specify the transaction cost when <a href="reference-transaction-format.html#multi-signing">multi-signing</a>.</li>
|
||||
</ul>
|
||||
<h2 id="transaction-costs-and-failed-transactions">Transaction Costs and Failed Transactions</h2>
|
||||
<p>Since the purpose of the transaction cost is to protect the peer-to-peer Ripple network from excessive load, it should apply to any transaction that gets distributed to the network, regardless of whether or not that transaction succeeds. However, in order to affect the shared global ledger, a transaction must be included in a validated ledger. Thus, <code>rippled</code> servers attempt to include failed transactions in ledgers, with <a href="reference-transaction-format.html#result-categories"><code>tec</code> status codes</a> ("tec" stands for "Transaction Engine - Claimed fee only").</p>
|
||||
<p>The transaction cost is only debited from the sender's XRP balance when the transaction actually becomes included in a validated ledger. This is true whether the transaction is considered successful or fails with a <code>tec</code> code.</p>
|
||||
<p>If a transaction's failure is <a href="reference-transaction-format.html#finality-of-results">final</a>, the <code>rippled</code> server does not relay it to the network. Consequently, that transaction does not get included in a validated ledger, and it cannot have any effect on anyone's XRP balance.</p>
|
||||
<h3 id="insufficient-xrp">Insufficient XRP</h3>
|
||||
<p>When a <code>rippled</code> server initially evaluates a transaction, it rejects the transaction with the error code <code>terINSUF_FEE_B</code> if the sending account does not have a high enough XRP balance to pay the XRP transaction cost. Since this is a <code>ter</code> (Retry) code, the <code>rippled</code> server retries the transaction without relaying it to the network, until the transaction's outcome is <a href="reference-transaction-format.html#finality-of-results">final</a>.</p>
|
||||
<p>When a transaction has already been distributed to the network, but the account does not have sufficient XRP to pay the transaction cost, the result code <code>tecINSUFF_FEE</code> occurs instead. In this case, the account pays all the XRP it can, ending with 0 XRP. This can occur because <code>rippled</code> decides whether to relay the transaction to the network based on its in-progress ledger, but transactions may be dropped or reordered when building the consensus ledger.</p>
|
||||
<h2 id="key-reset-transaction">Key Reset Transaction</h2>
|
||||
<p>As a special case, an account can send a <a href="reference-transaction-format.html#setregularkey">SetRegularKey</a> transaction with a transaction cost of <code>0</code>, as long as the account's <a href="reference-ledger-format.html#accountroot-flags">lsfPasswordSpent flag</a> is disabled. This transaction must be signed by the account's <em>master key</em>. Sending this transaction enables the lsfPasswordSpent flag.</p>
|
||||
<p>This feature is designed to allow you to recover an account if the regular key is compromised, without worrying about whether the compromised account has any XRP available. This way, you can regain control of the account before you send additional XRP to it.</p>
|
||||
<p>The <a href="reference-ledger-format.html#accountroot-flags">lsfPasswordSpent flag</a> starts out disabled. If enabled, it gets disabled again when the account receives a <a href="reference-transaction-format.html#payment">Payment</a> of XRP.</p>
|
||||
<p>When the <a href="concept-amendments.html#feeescalation">FeeEscalation amendment</a> is enabled, <code>rippled</code> prioritizes key reset transactions above other transactions even though the nominal transaction cost of a key reset transaction is zero.</p>
|
||||
<h2 id="changing-the-transaction-cost">Changing the Transaction Cost</h2>
|
||||
<p>In addition to short-term scaling to account for load, the Ripple Consensus Ledger has a mechanism for changing the minimum transaction cost in order to account for long-term changes in the value of XRP. Any changes have to be approved by the consensus process. See <a href="concept-fee-voting.html">Fee Voting</a> for more information.</p>
|
||||
</div>
|
||||
</main>
|
||||
</div>
|
||||
|
||||
<footer class="content-info" role="contentinfo">
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
|
||||
<section class="col-sm-3 widget nav_menu-3 widget_nav_menu">
|
||||
<h4>Resources<hr></h4>
|
||||
<ul id="menu-resources" class="menu">
|
||||
<li class="menu-insights"><a href="https://ripple.com/insights/">Insights</a></li>
|
||||
<li class="menu-press-center"><a href="https://ripple.com/press-center/">Press Center</a></li>
|
||||
<li class="menu-media-resources"><a href="https://ripple.com/media-resources/">Media Resources</a></li>
|
||||
<li class="menu-videos"><a href="https://ripple.com/videos/">Videos</a></li>
|
||||
<li class="menu-whitepapers-reports"><a href="https://ripple.com/whitepapers-reports/">Whitepapers & Reports</a></li>
|
||||
<li class="menu-xrp-portal"><a href="https://ripple.com/xrp-portal/">XRP Portal</a></li>
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
<section class="col-sm-3 widget nav_menu-5 widget_nav_menu">
|
||||
<h4>Regulators<hr></h4>
|
||||
<ul id="menu-compliance-regulatory-relations" class="menu"><li class="menu-compliance"><a href="https://ripple.com/compliance/">Compliance</a></li>
|
||||
<li class="menu-policy-framework"><a href="https://ripple.com/policy-framework/">Policy Framework</a></li>
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
<section class="col-sm-3 widget nav_menu-4 widget_nav_menu">
|
||||
<h4>Support<hr></h4>
|
||||
<ul id="menu-dev-footer-menu" class="menu">
|
||||
<li class="menu-contact-us"><a href="https://ripple.com/contact/">Contact Us</a></li>
|
||||
<li class="active menu-developer-center"><a href="https://ripple.com/build/">Developer Center</a></li>
|
||||
<li class="menu-knowledge-center"><a href="https://ripple.com/learn/">Knowledge Center</a></li>
|
||||
<li class="menu-ripple-forum"><a target="_blank" href="https://forum.ripple.com/">Ripple Forum</a></li>
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
<section class="col-sm-3 widget nav_menu-2 widget_nav_menu">
|
||||
<h4>About<hr></h4>
|
||||
<ul id="menu-company-footer" class="menu">
|
||||
<li class="menu-our-company"><a href="https://ripple.com/company/">Our Company</a></li>
|
||||
<li class="menu-careers"><a href="https://ripple.com/company/careers/">Careers</a></li>
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
<div class="col-sm-12 absolute_bottom_footer">
|
||||
<div class="col-sm-8">
|
||||
<span>© 2013-2015 Ripple Labs, Inc. All Rights Reserved.</span>
|
||||
<span><a href="https://ripple.com/terms-of-use/">Terms</a></span>
|
||||
<span><a href="https://ripple.com/privacy-policy/">Privacy</a></span>
|
||||
</div>
|
||||
</div><!-- /.absolute_bottom_footer -->
|
||||
|
||||
</div><!-- /.row -->
|
||||
</div><!-- /.container -->
|
||||
</footer>
|
||||
</body>
|
||||
</html>
|
||||
231
concept-transfer-fees.html
Normal file
@@ -0,0 +1,231 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
|
||||
<meta name="viewport" content="width=device-width">
|
||||
|
||||
<title>Transfer Fees - Ripple Developer Portal</title>
|
||||
|
||||
<!-- favicon -->
|
||||
<link rel="icon" href="favicon.ico" type="image/x-icon">
|
||||
<link rel="shortcut icon" href="favicon.ico" type="image/x-icon">
|
||||
|
||||
<!-- jQuery -->
|
||||
<script src="assets/vendor/jquery-1.11.1.min.js"></script>
|
||||
|
||||
<!-- Custom Stylesheets. ripple.css includes bootstrap, font stuff -->
|
||||
<link href="assets/css/ripple.css" rel="stylesheet" />
|
||||
<link href="assets/css/devportal.css" rel="stylesheet" />
|
||||
|
||||
<!-- Bootstrap JS -->
|
||||
<script src="assets/vendor/bootstrap.min.js"></script>
|
||||
|
||||
|
||||
<!-- syntax highlighting -->
|
||||
<link rel="stylesheet" href="assets/vendor/docco.min.css">
|
||||
<script src="assets/vendor/highlight.min.js"></script>
|
||||
|
||||
<!-- syntax selection js -->
|
||||
<script src="assets/js/multicodetab.js"></script>
|
||||
<script>
|
||||
$(document).ready(function() {
|
||||
$().multicode_tabs();
|
||||
hljs.initHighlighting();
|
||||
make_code_expandable();
|
||||
});
|
||||
</script>
|
||||
|
||||
<script src="assets/js/expandcode.js"></script>
|
||||
<script src="assets/js/fixsidebarscroll.js"></script>
|
||||
|
||||
</head>
|
||||
|
||||
<body class="page page-template page-template-template-dev-portal page-template-template-dev-portal-php sidebar-primary wpb-js-composer js-comp-ver-3.6.2 vc_responsive">
|
||||
<header role="banner" class="banner navbar navbar-default navbar-fixed-top initial_header">
|
||||
<div class="container">
|
||||
<div class="navbar-header">
|
||||
<a href="index.html" class="navbar-brand"><img src="assets/img/ripple-logo-color.png" class="logo"></a>
|
||||
</div><!-- /.navbar-header -->
|
||||
<div class="nav">
|
||||
<div class="draft-warning">DRAFT PAGE</div>
|
||||
</div><!-- /.nav -->
|
||||
|
||||
</div><!-- /.container -->
|
||||
|
||||
<div class="subnav dev_nav">
|
||||
<div class="container">
|
||||
<ul id="menu-dev-menu" class="menu">
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">References <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="reference-rippled.html">rippled</a></li>
|
||||
<li><a href="reference-transaction-format.html">Transaction Format</a></li>
|
||||
<li><a href="reference-ledger-format.html">Ledger Format</a></li>
|
||||
<li><a href="reference-rippleapi.html">RippleAPI</a></li>
|
||||
<li><a href="reference-data-api.html">Ripple Data API v2</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Tutorials <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="tutorial-rippleapi-beginners-guide.html">RippleAPI Beginners Guide</a></li>
|
||||
<li><a href="tutorial-rippled-setup.html">rippled Setup</a></li>
|
||||
<li><a href="tutorial-reliable-transaction-submission.html">Reliable Transaction Submission</a></li>
|
||||
<li><a href="tutorial-multisign.html">How to Multi-Sign</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Concepts <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="concept-paths.html">Paths</a></li>
|
||||
<li><a href="concept-fees.html">Fees (Disambiguation)</a></li>
|
||||
<li><a href="concept-transfer-fees.html">Transfer Fees</a></li>
|
||||
<li><a href="concept-transaction-cost.html">Transaction Cost</a></li>
|
||||
<li><a href="concept-fee-voting.html">Fee Voting</a></li>
|
||||
<li><a href="concept-reserves.html">Reserves</a></li>
|
||||
<li><a href="concept-freeze.html">Freeze</a></li>
|
||||
<li><a href="concept-amendments.html">Amendments</a></li>
|
||||
<li><a href="concept-stand-alone-mode.html">Stand-Alone Mode</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Best Practices <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="concept-issuing-and-operational-addresses.html">Issuing and Operational Addresses</a></li>
|
||||
<li><a href="tutorial-gateway-guide.html">Gateway Guide</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">API Tools <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="ripple-api-tool.html">WebSocket API Tool</a></li>
|
||||
<li><a href="data-api-v2-tool.html">Data API v2 Tool</a></li>
|
||||
<li><a href="tool-jsonrpc.html">rippled JSON-RPC Tool</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Resources <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="https://forum.ripple.com/viewforum.php?f=2">Forums</a></li>
|
||||
<li><a href="https://www.bountysource.com/teams/ripple/bounties">Bounties</a></li>
|
||||
<li><a href="https://ripplelabs.atlassian.net/">Bug Tracking</a></li>
|
||||
<li><a href="https://ripple.com/category/dev-blog/">Dev Blog</a></li>
|
||||
<li><a href="https://ripple.com/press-releases/">Press Center</a></li>
|
||||
<li><a href="https://ripple.com/brand-guidelines/">Brand Guidelines</a></li>
|
||||
</ul>
|
||||
<li><a href="https://github.com/ripple/ripple-dev-portal" title="GitHub">Site Source</a></li>
|
||||
</ul><!-- /#dev-menu -->
|
||||
</div><!-- /.subnav .container -->
|
||||
</div><!-- /.subnav -->
|
||||
</header>
|
||||
|
||||
|
||||
<div class="wrap container" role="document">
|
||||
<aside class="sidebar" role="complementary">
|
||||
<div class="dev_nav_wrapper">
|
||||
<div id="cont">
|
||||
<ul class="dev_nav_sidebar">
|
||||
<li class="level-1"><a href="index.html">Category: Concepts</a></li>
|
||||
<li class="level-2"><a href="concept-paths.html">Paths</a></li>
|
||||
<li class="level-2"><a href="concept-fees.html">Fees (Disambiguation)</a></li>
|
||||
<li class="level-2"><a href="concept-transfer-fees.html">Transfer Fees</a></li>
|
||||
<li class="level-2"><a href="concept-transaction-cost.html">Transaction Cost</a></li>
|
||||
<li class="level-2"><a href="concept-fee-voting.html">Fee Voting</a></li>
|
||||
<li class="level-2"><a href="concept-reserves.html">Reserves</a></li>
|
||||
<li class="level-2"><a href="concept-freeze.html">Freeze</a></li>
|
||||
<li class="level-2"><a href="concept-amendments.html">Amendments</a></li>
|
||||
<li class="level-2"><a href="concept-stand-alone-mode.html">Stand-Alone Mode</a></li>
|
||||
</ul>
|
||||
<hr />
|
||||
<h5>In this page:</h5>
|
||||
</div>
|
||||
<script type="text/javascript" src="assets/js/jquery.gensidebar.js"></script>
|
||||
</div>
|
||||
</aside>
|
||||
<main class="main" role="main">
|
||||
<div class='content'>
|
||||
<h1 id="transfer-fees">Transfer Fees</h1>
|
||||
<p>The <code>TransferRate</code> setting in the Ripple Consensus Ledger allows <a href="https://ripple.com/knowledge_center/gateways/">issuing gateways</a> to charge users a <em>transfer fee</em> for sending that gateway's issuances to other users. When a gateway sets a transfer fee, it costs extra to send a transfer of that gateway's issuances. The sender of the transfer is debited an extra percentage based on the transfer fee, while the recipient of the transfer is credited the intended amount. The difference is the transfer fee, which becomes the property of the issuing gateway, and is no longer tracked in the Ripple Consensus Ledger. The transfer fee does not apply when sending or receiving <em>directly</em> to and from the issuing account, but it does apply when transferring from a <a href="concept-issuing-and-operational-addresses.html">hot wallet</a> to another user.</p>
|
||||
<p>XRP never has a transfer fee, because it never has an issuer.</p>
|
||||
<p>For example, ACME Gateway might set the transfer fee to 0.5% for ACME issuances. In order for the recipient of a payment to get 2 EUR.ACME, the sender must send 2.01 EUR.ACME. After the transaction, ACME's outstanding obligations in Ripple have decreased by 0.01€, which means that it is no longer obliged to hold that amount in the account backing its Ripple issuances.</p>
|
||||
<p>The following diagram shows a Ripple payment of 2 EUR.ACME from Alice to Charlie with a transfer fee of 1%:</p>
|
||||
<p><img alt="Alice sends 2,02€, Charlie receives 2,00€, and ACME owes 0,02€ less in Ripple" src="img/e2g-with_transferrate.png"/></p>
|
||||
<h2 id="transfer-fees-in-payment-paths">Transfer Fees in Payment Paths</h2>
|
||||
<p>A transfer fee applies whenever an individual transfer would shift issuances from one party to another through the issuing account. In more complex transactions, this can occur multiple times. Transfer fees apply starting from the end and working backwards, so that ultimately the initial sender of a payment must send enough to account for all fees. For example:</p>
|
||||
<p><img alt="Diagram of cross-currency payment with transfer fees" src="img/transfer_fees_example.png"/></p>
|
||||
<p>In this scenario, Salazar (the sender) holds EUR issued by ACME, and wants to deliver 100 USD issued by WayGate to Rosa (the recipient). FXMaker is a market maker with the best offer in the order book, at a rate of 1 USD.WayGate for every 0.9 EUR.ACME. If there were no transfer fees, Salazar could deliver 100 USD to Rosa by sending 90 EUR. However, ACME has a transfer fee of 1% and WayGate has a transfer fee of 0.2%. This means:</p>
|
||||
<ul>
|
||||
<li>FXMaker must send 100.20 USD.WayGate in order for Rosa to receive 100 USD.WayGate.</li>
|
||||
<li>FXMaker's current ask is 90.18 EUR.ACME in order to send 100.20 USD.WayGate.</li>
|
||||
<li>In order for FXMaker to receive 90.18 EUR.ACME, Salazar must send 91.0818 EUR.ACME.</li>
|
||||
</ul>
|
||||
<h1 id="technical-details">Technical Details</h1>
|
||||
<p>The transfer fee is represented by a setting on the issuing (<strong>cold wallet</strong>) account. The transfer fee has a maximum precision of 9 digits, and cannot be less than 0% or greater than 100%. The TransferRate setting applies to all currencies issued by the same account. If you want to have different transfer fee percentages for different currencies, use different cold wallets to issue each currency.</p>
|
||||
<h2 id="rippleapi">RippleAPI</h2>
|
||||
<p>In RippleAPI, the transfer fee is specified in the <code>transferRate</code> field, as an integer which represents the amount you must send in order for the recipient to get 1 billion units of the same currency. A <code>transferRate</code> of <code>1005000000</code> is equivalent to a transfer fee of 0.5%. By default, the <code>transferRate</code> is set to no fee. The value of <code>transferRate</code> cannot be less than <code>1000000000</code> or more than <code>2000000000</code>. The value <code>null</code> is special: it is equivalent to <code>1000000000</code>, meaning no fee.</p>
|
||||
<p>A gateway can send a <a href="reference-rippleapi.html#settings">Settings transaction</a> with its cold wallet to change the <code>transferRate</code> for its issuances.</p>
|
||||
<p>You can check an account's <code>transferRate</code> with the <a href="reference-rippleapi.html#getsettings">getSettings method</a>.</p>
|
||||
<h2 id="rippled">rippled</h2>
|
||||
<p>In <code>rippled</code>'s JSON-RPC and WebSocket APIs, the transfer fee is specified in the <code>TransferRate</code> field, as an integer which represents the amount you must send in order for the recipient to get 1 billion units of the same currency. A <code>TransferRate</code> of <code>1005000000</code> is equivalent to a transfer fee of 0.5%. By default, the <code>TransferRate</code> is set at <code>1000000000</code>, indicating no fee. The value of <code>TransferRate</code> cannot be less than <code>1000000000</code> or more than <code>2000000000</code>. However, value <code>0</code> is special: it is equivalent to <code>1000000000</code>, meaning no fee.</p>
|
||||
<p>A gateway can submit an <a href="reference-transaction-format.html#accountset">AccountSet transaction</a> from its cold wallet to change the <code>TransferRate</code> for its issuances.</p>
|
||||
<p>You can check an account's <code>TransferRate</code> with the <a href="reference-rippled.html#account-info"><code>account_info</code> command</a>. If the <code>TransferRate</code> is omitted, then that indicates no fee.</p>
|
||||
</div>
|
||||
</main>
|
||||
</div>
|
||||
|
||||
<footer class="content-info" role="contentinfo">
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
|
||||
<section class="col-sm-3 widget nav_menu-3 widget_nav_menu">
|
||||
<h4>Resources<hr></h4>
|
||||
<ul id="menu-resources" class="menu">
|
||||
<li class="menu-insights"><a href="https://ripple.com/insights/">Insights</a></li>
|
||||
<li class="menu-press-center"><a href="https://ripple.com/press-center/">Press Center</a></li>
|
||||
<li class="menu-media-resources"><a href="https://ripple.com/media-resources/">Media Resources</a></li>
|
||||
<li class="menu-videos"><a href="https://ripple.com/videos/">Videos</a></li>
|
||||
<li class="menu-whitepapers-reports"><a href="https://ripple.com/whitepapers-reports/">Whitepapers & Reports</a></li>
|
||||
<li class="menu-xrp-portal"><a href="https://ripple.com/xrp-portal/">XRP Portal</a></li>
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
<section class="col-sm-3 widget nav_menu-5 widget_nav_menu">
|
||||
<h4>Regulators<hr></h4>
|
||||
<ul id="menu-compliance-regulatory-relations" class="menu"><li class="menu-compliance"><a href="https://ripple.com/compliance/">Compliance</a></li>
|
||||
<li class="menu-policy-framework"><a href="https://ripple.com/policy-framework/">Policy Framework</a></li>
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
<section class="col-sm-3 widget nav_menu-4 widget_nav_menu">
|
||||
<h4>Support<hr></h4>
|
||||
<ul id="menu-dev-footer-menu" class="menu">
|
||||
<li class="menu-contact-us"><a href="https://ripple.com/contact/">Contact Us</a></li>
|
||||
<li class="active menu-developer-center"><a href="https://ripple.com/build/">Developer Center</a></li>
|
||||
<li class="menu-knowledge-center"><a href="https://ripple.com/learn/">Knowledge Center</a></li>
|
||||
<li class="menu-ripple-forum"><a target="_blank" href="https://forum.ripple.com/">Ripple Forum</a></li>
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
<section class="col-sm-3 widget nav_menu-2 widget_nav_menu">
|
||||
<h4>About<hr></h4>
|
||||
<ul id="menu-company-footer" class="menu">
|
||||
<li class="menu-our-company"><a href="https://ripple.com/company/">Our Company</a></li>
|
||||
<li class="menu-careers"><a href="https://ripple.com/company/careers/">Careers</a></li>
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
<div class="col-sm-12 absolute_bottom_footer">
|
||||
<div class="col-sm-8">
|
||||
<span>© 2013-2015 Ripple Labs, Inc. All Rights Reserved.</span>
|
||||
<span><a href="https://ripple.com/terms-of-use/">Terms</a></span>
|
||||
<span><a href="https://ripple.com/privacy-policy/">Privacy</a></span>
|
||||
</div>
|
||||
</div><!-- /.absolute_bottom_footer -->
|
||||
|
||||
</div><!-- /.row -->
|
||||
</div><!-- /.container -->
|
||||
</footer>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,214 +0,0 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset='utf-8'>
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
|
||||
<meta name="viewport" content="width=device-width">
|
||||
|
||||
<title>Ripple Developer Portal: Consensus Whitepaper</title>
|
||||
|
||||
<!-- favicon -->
|
||||
<link rel="icon" href="favicon.ico" type="image/x-icon">
|
||||
<link rel="shortcut icon" href="favicon.ico" type="image/x-icon">
|
||||
|
||||
<!-- Flatdoc -->
|
||||
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
|
||||
<script src='https://dev.ripple.com/vendor/flatdoc/v/0.8.0/legacy.js'></script>
|
||||
<script src='https://dev.ripple.com/vendor/flatdoc/v/0.8.0/flatdoc.js'></script>
|
||||
|
||||
<!-- Bootstrap -->
|
||||
<link href="css/bootstrap.min.css" rel="stylesheet">
|
||||
<script src="js/bootstrap.min.js"></script>
|
||||
|
||||
<!-- Flatdoc theme -->
|
||||
<!--
|
||||
<link href='https://dev.ripple.com/vendor/flatdoc/v/0.8.0/theme-white/style.css' rel='stylesheet'>
|
||||
<script src='https://dev.ripple.com/vendor/flatdoc/v/0.8.0/theme-white/script.js'></script>
|
||||
-->
|
||||
|
||||
<!-- Font Awesome -->
|
||||
<link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.1.0/css/font-awesome.min.css" rel="stylesheet">
|
||||
|
||||
|
||||
<!-- Custom Stylesheet -->
|
||||
<link href='https://fonts.googleapis.com/css?family=Montserrat' rel='stylesheet' type='text/css'>
|
||||
<link href='https://fonts.googleapis.com/css?family=Open+Sans:600italic,400,700,300' rel='stylesheet' type='text/css'>
|
||||
<link href='https://dev.ripple.com/css/main.css' rel='stylesheet'>
|
||||
<link href='css/custom.css' rel='stylesheet'>
|
||||
|
||||
<link rel="shortcut icon" href="favicon.ico?v=2" type="image/x-icon">
|
||||
<link rel="icon" href="favicon.ico?v=2" type="image/x-icon">
|
||||
|
||||
|
||||
<!-- start Mixpanel -->
|
||||
<script type="text/javascript">(function(e,b){if(!b.__SV){var a,f,i,g;window.mixpanel=b;a=e.createElement("script");a.type="text/javascript";a.async=!0;a.src=("https:"===e.location.protocol?"https:":"http:")+'//cdn.mxpnl.com/libs/mixpanel-2.2.min.js';f=e.getElementsByTagName("script")[0];f.parentNode.insertBefore(a,f);b._i=[];b.init=function(a,e,d){function f(b,h){var a=h.split(".");2==a.length&&(b=b[a[0]],h=a[1]);b[h]=function(){b.push([h].concat(Array.prototype.slice.call(arguments,0)))}}var c=b;"undefined"!==
|
||||
typeof d?c=b[d]=[]:d="mixpanel";c.people=c.people||[];c.toString=function(b){var a="mixpanel";"mixpanel"!==d&&(a+="."+d);b||(a+=" (stub)");return a};c.people.toString=function(){return c.toString(1)+".people (stub)"};i="disable track track_pageview track_links track_forms register register_once alias unregister identify name_tag set_config people.set people.set_once people.increment people.append people.track_charge people.clear_charges people.delete_user".split(" ");for(g=0;g<i.length;g++)f(c,i[g]);
|
||||
b._i.push([a,e,d])};b.__SV=1.2}})(document,window.mixpanel||[]);
|
||||
mixpanel.init("132d42885e094171f34467fc54da6fab");
|
||||
</script>
|
||||
|
||||
<script>if (window.location.host == "dev.ripple.com") { mixpanel.track("consensus-whitepaper"); } </script>
|
||||
<!-- end Mixpanel -->
|
||||
|
||||
<!-- start google analytics -->
|
||||
<script>
|
||||
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
|
||||
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
|
||||
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
|
||||
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
|
||||
|
||||
ga('create', 'UA-49188512-1', 'ripple.com');
|
||||
ga('send', 'pageview');
|
||||
|
||||
</script>
|
||||
<!-- end google analytics -->
|
||||
|
||||
|
||||
|
||||
<!-- syntax selection js -->
|
||||
<script src='js/multicodetab.js'></script>
|
||||
<!--
|
||||
<script>
|
||||
Flatdoc.run({
|
||||
fetcher: Flatdoc.file('ripplerest_api.md')
|
||||
});
|
||||
</script>
|
||||
-->
|
||||
<script src='js/expandcode.js'></script>
|
||||
|
||||
</head>
|
||||
<body role='flatdoc' class='no-literate'>
|
||||
<!--Draft warning would go here-->
|
||||
<div class="navbar navbar-inverse navbar-fixed-top" role="navigation">
|
||||
<div class="container">
|
||||
<div class="navbar-header">
|
||||
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
|
||||
<span class="sr-only">Toggle navigation</span>
|
||||
<span class="icon-bar"></span>
|
||||
<span class="icon-bar"></span>
|
||||
<span class="icon-bar"></span>
|
||||
</button>
|
||||
<a class="navbar-brand" href="https://dev.ripple.com/"><img class="small_logo" src="assets/img/ripple_logo_small.png"></a>
|
||||
</div>
|
||||
<div class="navbar-collapse collapse">
|
||||
<ul class="nav navbar-nav">
|
||||
<li class="dropdown">
|
||||
<a href="./" class="dropdown-toggle" data-toggle="dropdown">Documentation <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="rippled-apis.html">rippled API Reference</a></li>
|
||||
<li><a href="ripple-rest.html">REST API Reference</a></li>
|
||||
<li><a href="gatewayd.html">Gatewayd API Reference</a></li>
|
||||
<li><a href="transactions.html">Transaction Format</a></li>
|
||||
<li><a href="reliable_tx.html">Submitting Transactions</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a href="https://www.bountysource.com/teams/ripple/bounties">Bounties</a></li>
|
||||
<li><a href="https://ripplelabs.atlassian.net/">Bug Tracking</a></li>
|
||||
<li><a href="https://ripple.com/dev/blog/">Dev Blog</a></li>
|
||||
<li><a href="https://ripple.com/forum/viewforum.php?f=2&sid=c016bc6b934120b7117c0e136e74de98">Forums</a></li>
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">API Tool <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="ripple-api-tool.html">WebSocket Tool</a></li>
|
||||
<li><a href="rest-api-tool.html">REST Tool</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
<div class='right'>
|
||||
<!-- GitHub buttons -->
|
||||
<iframe src="https://dev.ripple.com/vendor/ghbtn.html?user=ripple&repo=ripple-dev-portal&type=watch&count=true" allowtransparency="true" frameborder="0" scrolling="0" width="110" height="20"></iframe>
|
||||
</div>
|
||||
</div><!--/.nav-collapse -->
|
||||
</div>
|
||||
</div>
|
||||
<!--
|
||||
<div class="header-subnav-wrapper">
|
||||
<div class='header-subnav navbar-fixed-top'>
|
||||
<ul>
|
||||
<li><a href='?p=introduction' id='subnav-intro'>Introduction</a></li>
|
||||
<li><a href='?p=ripple-rest-api' id='subnav-rest'>Ripple-REST API</a></li>
|
||||
<li><a href='?p=web-sockets-api' id='subnav-websocket'>WebSocket & JSON-RPC APIs</a></li>
|
||||
</ul>
|
||||
<div class='clearer'> </div>
|
||||
</div>
|
||||
</div>
|
||||
-->
|
||||
<div class='content-root'>
|
||||
<div class='menubar'>
|
||||
<div class='menu section' role='flatdoc-menu'></div>
|
||||
</div>
|
||||
<div role='flatdoc-content' class='content'>
|
||||
|
||||
<p class="download_consensus"><a href="https://ripple.com/files/ripple_consensus_whitepaper.pdf"><i class="fa fa-download"></i> Download the Consensus Whitepaper</a></p>
|
||||
|
||||
<iframe class="visible-lg-block visible-md-block" src="https://docs.google.com/viewer?url=https%3A%2F%2Fripple.com%2Ffiles%2Fripple_consensus_whitepaper.pdf&embedded=true" width="100%" height="1100" style="border: none;"></iframe>
|
||||
</div>
|
||||
</div>
|
||||
<div class="footer">
|
||||
<div class="container">
|
||||
<p class="text-muted">
|
||||
<div class="row">
|
||||
<div class="col-md-2">
|
||||
|
||||
<ul class="footer_links applications">
|
||||
<li><a href="https://www.rippletrade.com">Ripple Trade</a>
|
||||
<li><a href="https://www.ripplecharts.com">Ripple Charts</a>
|
||||
<li><a href="https://ripple.com/graph">Ripple Graph</a>
|
||||
<li><a href="http://codius.org/">Codius</a>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="col-md-2">
|
||||
|
||||
<ul class="footer_links middleware">
|
||||
<li><a href="gatewayd.html">Gatewayd</a>
|
||||
<li><a href="ripple-rest.html">Ripple REST</a>
|
||||
<li><a href="https://github.com/ripple/ripple-lib">Ripple Lib</a>
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
<div class="col-md-2">
|
||||
|
||||
<ul class="footer_links core_network">
|
||||
<li><a href="rippled-apis.html">rippled</a>
|
||||
<li><a href="transactions.html">Transactions</a>
|
||||
<li><a href="consensus-whitepaper.html">Consensus</a>
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
<div class="col-md-2">
|
||||
<ul class="footer_links bounties">
|
||||
<li><a href="https://www.bountysource.com/teams/ripple/bounties">Bounties</a>
|
||||
<li><a href="https://ripplelabs.atlassian.net/">Bug tracking</a>
|
||||
<li><a href="guidelines.html">Brand guidelines</a>
|
||||
<li><a href="https://ripple.com/dev/blog/">Dev blog</a>
|
||||
<li><a href="https://ripple.com/forum/viewforum.php?f=2&sid=c016bc6b934120b7117c0e136e74de98">Forums</a>
|
||||
<li><a href="https://ripple.com/wiki/Main_Page">Wiki</a>
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
<div class="col-md-4 mail_chimp">
|
||||
<p>Join the mailing list!</p>
|
||||
<label for="mce-EMAIL">Email address</label>
|
||||
<!-- Begin MailChimp Signup Form -->
|
||||
<link href="//cdn-images.mailchimp.com/embedcode/slim-081711.css" rel="stylesheet" type="text/css">
|
||||
<style type="text/css">
|
||||
#mc_embed_signup{clear:left; font:14px; }
|
||||
|
||||
</style>
|
||||
<div id="mc_embed_signup">
|
||||
<form action="//ripple.us4.list-manage.com/subscribe/post?u=245dbc1c47849f034390dc5bf&id=4dfbe160d0" method="post" id="mc-embedded-subscribe-form" name="mc-embedded-subscribe-form" class="validate" target="_blank" novalidate>
|
||||
|
||||
<input type="email" value="" name="EMAIL" class="email" id="mce-EMAIL" placeholder="" required>
|
||||
<!-- real people should not fill this in and expect good things - do not remove this or risk form bot signups-->
|
||||
<div style="position: absolute; left: -5000px; top: -50px;"><input type="text" name="b_245dbc1c47849f034390dc5bf_4dfbe160d0" tabindex="-1" value=""></div>
|
||||
<input type="submit" value="Submit" name="subscribe" id="mc-embedded-subscribe" class="button btn btn-primary">
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<!--End mc_embed_signup-->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
23
content/code_samples/freeze/check-global-freeze-no-freeze.js
Normal file
@@ -0,0 +1,23 @@
|
||||
const {RippleAPI} = require('ripple-lib');
|
||||
|
||||
const api = new RippleAPI({
|
||||
server: 'wss://s1.ripple.com' // Public rippled server
|
||||
});
|
||||
api.on('error', (errorCode, errorMessage) => {
|
||||
console.log(errorCode + ': ' + errorMessage);
|
||||
});
|
||||
|
||||
const my_address = 'rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn';
|
||||
|
||||
api.connect().then(() => {
|
||||
// Look up settings object
|
||||
return api.getSettings(my_address);
|
||||
}).then(settings => {
|
||||
console.log('Got settings for address', my_address);
|
||||
console.log('Global Freeze enabled?',
|
||||
(settings.globalFreeze === true));
|
||||
console.log('No Freeze enabled?', (settings.noFreeze === true));
|
||||
|
||||
}).then(() => {
|
||||
return api.disconnect();
|
||||
}).catch(console.error);
|
||||
37
content/code_samples/freeze/check-individual-freeze.js
Normal file
@@ -0,0 +1,37 @@
|
||||
const {RippleAPI} = require('ripple-lib');
|
||||
|
||||
const api = new RippleAPI({
|
||||
server: 'wss://s1.ripple.com' // Public rippled server
|
||||
});
|
||||
api.on('error', (errorCode, errorMessage) => {
|
||||
console.log(errorCode + ': ' + errorMessage);
|
||||
});
|
||||
|
||||
const my_address = 'rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn';
|
||||
const counterparty_address = 'rUpy3eEg8rqjqfUoLeBnZkscbKbFsKXC3v';
|
||||
const frozen_currency = 'USD';
|
||||
|
||||
api.connect().then(() => {
|
||||
|
||||
// Look up current state of trust line
|
||||
const options = {counterparty: counterparty_address,
|
||||
currency: frozen_currency};
|
||||
console.log('looking up', frozen_currency, 'trust line from',
|
||||
my_address, 'to', counterparty_address);
|
||||
return api.getTrustlines(my_address, options);
|
||||
|
||||
}).then(data => {
|
||||
|
||||
if (data.length !== 1) {
|
||||
throw 'should only be 1 trust line per counterparty+currency pair';
|
||||
}
|
||||
|
||||
const trustline = data[0];
|
||||
console.log('Trust line frozen from our side?',
|
||||
trustline.specification.frozen === true);
|
||||
console.log('Trust line frozen from counterparty\'s side?',
|
||||
trustline.counterparty.frozen === true);
|
||||
|
||||
}).then(() => {
|
||||
return api.disconnect();
|
||||
}).catch(console.error);
|
||||
201
content/code_samples/freeze/eslintrc
Normal file
@@ -0,0 +1,201 @@
|
||||
# ESLint documentation can be found at http://eslint.org/docs/
|
||||
env:
|
||||
browser: true
|
||||
node: true
|
||||
amd: false
|
||||
mocha: true
|
||||
jasmine: false
|
||||
es6: true
|
||||
rules:
|
||||
no-alert: 2
|
||||
no-array-constructor: 2
|
||||
no-arrow-condition: 0
|
||||
no-bitwise: 0
|
||||
no-caller: 2
|
||||
no-case-declarations: 2
|
||||
no-catch-shadow: 2
|
||||
no-class-assign: 2
|
||||
no-cond-assign: [2, 'always']
|
||||
no-console: 0
|
||||
no-const-assign: 2
|
||||
no-constant-condition: 2
|
||||
no-continue: 0
|
||||
no-control-regex: 2
|
||||
no-debugger: 2
|
||||
no-delete-var: 2
|
||||
no-div-regex: 0
|
||||
no-dupe-class-members: 2
|
||||
no-dupe-keys: 2
|
||||
no-dupe-args: 2
|
||||
no-duplicate-case: 2
|
||||
no-else-return: 0
|
||||
no-empty: 2
|
||||
no-empty-character-class: 2
|
||||
no-empty-label: 2
|
||||
no-empty-pattern: 2
|
||||
no-eq-null: 2
|
||||
no-eval: 2
|
||||
no-ex-assign: 2
|
||||
no-extend-native: 2
|
||||
no-extra-bind: 2
|
||||
no-extra-boolean-cast: 2
|
||||
no-extra-parens: [2, 'functions']
|
||||
no-extra-semi: 2
|
||||
no-fallthrough: 2
|
||||
no-floating-decimal: 0
|
||||
no-func-assign: 2
|
||||
no-implicit-coercion: 2
|
||||
no-implied-eval: 2
|
||||
no-inline-comments: 0
|
||||
no-inner-declarations: [2, 'functions']
|
||||
no-invalid-regexp: 2
|
||||
no-invalid-this: 0 # this rule would cause problems with mocha test cases
|
||||
no-irregular-whitespace: 2
|
||||
no-iterator: 2
|
||||
no-label-var: 2
|
||||
no-labels: 2
|
||||
no-lone-blocks: 2
|
||||
no-lonely-if: 2
|
||||
no-loop-func: 2
|
||||
no-mixed-requires: [0, false]
|
||||
no-mixed-spaces-and-tabs: [2, false]
|
||||
linebreak-style: [2, 'unix']
|
||||
no-multi-spaces: 2
|
||||
no-multi-str: 2
|
||||
no-multiple-empty-lines: [2, {max: 2}]
|
||||
no-native-reassign: 2
|
||||
no-negated-condition: 0
|
||||
no-negated-in-lhs: 2
|
||||
no-nested-ternary: 0
|
||||
no-new: 2
|
||||
no-new-func: 2
|
||||
no-new-object: 2
|
||||
no-new-require: 0
|
||||
no-new-wrappers: 2
|
||||
no-obj-calls: 2
|
||||
no-octal: 2
|
||||
no-octal-escape: 2
|
||||
no-param-reassign: 2
|
||||
no-path-concat: 0
|
||||
no-plusplus: 0
|
||||
no-process-env: 0
|
||||
no-process-exit: 0
|
||||
no-proto: 2
|
||||
no-redeclare: 2
|
||||
no-regex-spaces: 2
|
||||
no-restricted-modules: 0
|
||||
no-restricted-syntax: 0
|
||||
no-return-assign: 2
|
||||
no-script-url: 2
|
||||
no-self-compare: 2
|
||||
no-sequences: 2
|
||||
no-shadow: 2
|
||||
no-shadow-restricted-names: 2
|
||||
no-spaced-func: 2
|
||||
no-sparse-arrays: 2
|
||||
no-sync: 0
|
||||
no-ternary: 0
|
||||
no-trailing-spaces: 2
|
||||
no-this-before-super: 2
|
||||
no-throw-literal: 2
|
||||
no-undef: 2
|
||||
no-undef-init: 2
|
||||
no-undefined: 0
|
||||
no-unexpected-multiline: 2
|
||||
no-underscore-dangle: 0
|
||||
no-unneeded-ternary: 0
|
||||
no-unreachable: 2
|
||||
no-unused-expressions: 2
|
||||
no-unused-vars: [2, {vars: 'all', args: 'all'}]
|
||||
no-use-before-define: 2
|
||||
no-useless-call: 2
|
||||
no-useless-concat: 0
|
||||
no-void: 2
|
||||
no-var: 2
|
||||
no-warning-comments: [0, {terms: ['todo', 'fixme', 'xxx'], location: 'start'}]
|
||||
no-with: 2
|
||||
no-magic-numbers: 0
|
||||
|
||||
array-bracket-spacing: [2, 'never']
|
||||
arrow-body-style: 0
|
||||
arrow-parens: [2, 'as-needed']
|
||||
arrow-spacing: 2
|
||||
accessor-pairs: 2
|
||||
block-scoped-var: 2
|
||||
block-spacing: 2
|
||||
brace-style: 2
|
||||
callback-return: 0
|
||||
camelcase: 0
|
||||
comma-dangle: 2
|
||||
comma-spacing: 2
|
||||
comma-style: 2
|
||||
complexity: [0, 11]
|
||||
computed-property-spacing: 2
|
||||
consistent-return: 2
|
||||
consistent-this: [2, 'self']
|
||||
constructor-super: 2
|
||||
curly: [2, 'all']
|
||||
default-case: 0
|
||||
dot-location: [2, 'property']
|
||||
dot-notation: [2, {allowKeywords: true}]
|
||||
eol-last: 2
|
||||
eqeqeq: 2
|
||||
func-names: 0
|
||||
func-style: [2, 'declaration']
|
||||
generator-star-spacing: 2
|
||||
global-require: 0
|
||||
guard-for-in: 0
|
||||
handle-callback-err: 2
|
||||
id-length: 0
|
||||
indent: [2, 2, {SwitchCase: 1}]
|
||||
init-declarations: 0
|
||||
jsx-quotes: 0
|
||||
key-spacing: [2, {beforeColon: false, afterColon: true}]
|
||||
lines-around-comment: 0
|
||||
max-depth: [0, 4]
|
||||
max-len: [2, 80]
|
||||
max-nested-callbacks: [0, 2]
|
||||
max-params: [0, 4]
|
||||
max-statements: [0, 10]
|
||||
new-cap: 2
|
||||
new-parens: 2
|
||||
newline-after-var: 0
|
||||
object-curly-spacing: [2, 'never']
|
||||
object-shorthand: 0
|
||||
one-var: [2, 'never']
|
||||
operator-assignment: [0, 'always']
|
||||
operator-linebreak: 0
|
||||
padded-blocks: 0
|
||||
prefer-arrow-callback: 0
|
||||
prefer-const: 2
|
||||
prefer-spread: 2
|
||||
prefer-reflect: 0
|
||||
prefer-template: 0
|
||||
quote-props: 0
|
||||
quotes: [2, 'single']
|
||||
radix: 2
|
||||
id-match: 0
|
||||
require-jsdoc: 0
|
||||
require-yield: 0
|
||||
semi: 2
|
||||
semi-spacing: 2
|
||||
sort-vars: 0
|
||||
space-after-keywords: 2
|
||||
space-before-keywords: 2
|
||||
space-before-blocks: 2
|
||||
space-before-function-paren: [2, 'never']
|
||||
space-in-parens: 2
|
||||
space-infix-ops: 2
|
||||
space-return-throw-case: 2
|
||||
space-unary-ops: [2, {words: true, nonwords: false}]
|
||||
spaced-comment: 2
|
||||
strict: [2, 'global']
|
||||
use-isnan: 2
|
||||
valid-jsdoc: 2
|
||||
valid-typeof: 2
|
||||
vars-on-top: 0
|
||||
wrap-iife: 0
|
||||
wrap-regex: 0
|
||||
yoda: [2, 'never']
|
||||
ecmaFeatures:
|
||||
jsx: true
|
||||
16
content/code_samples/freeze/package.json
Normal file
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"name": "freeze-examples",
|
||||
"version": "0.0.2",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"ripple-lib": "*",
|
||||
"babel-cli": "^6.0.0",
|
||||
"babel-preset-es2015": "*"
|
||||
},
|
||||
"babel": {
|
||||
"presets": ["es2015"]
|
||||
},
|
||||
"devDependencies": {
|
||||
"eslint": "*"
|
||||
}
|
||||
}
|
||||
37
content/code_samples/freeze/set-global-freeze.js
Normal file
@@ -0,0 +1,37 @@
|
||||
const {RippleAPI} = require('ripple-lib');
|
||||
|
||||
const api = new RippleAPI({
|
||||
server: 'wss://s1.ripple.com' // Public rippled server
|
||||
});
|
||||
api.on('error', (errorCode, errorMessage) => {
|
||||
console.log(errorCode + ': ' + errorMessage);
|
||||
});
|
||||
|
||||
const issuing_address = 'rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn';
|
||||
const issuing_secret = 's████████████████████████████';
|
||||
// Best practice: get your secret from an encrypted
|
||||
// config file instead
|
||||
|
||||
api.connect().then(() => {
|
||||
|
||||
// Prepare a settings transaction to enable global freeze
|
||||
const settings = {
|
||||
'globalFreeze': true
|
||||
};
|
||||
|
||||
console.log('preparing settings transaction for account:',
|
||||
issuing_address);
|
||||
return api.prepareSettings(issuing_address, settings);
|
||||
|
||||
}).then(prepared_tx => {
|
||||
|
||||
// Sign and submit the settings transaction
|
||||
console.log('signing tx:', prepared_tx.txJSON);
|
||||
const signed1 = api.sign(prepared_tx.txJSON, issuing_secret);
|
||||
console.log('submitting tx:', signed1.id);
|
||||
|
||||
return api.submit(signed1.signedTransaction);
|
||||
|
||||
}).then(() => {
|
||||
return api.disconnect();
|
||||
}).catch(console.error);
|
||||
57
content/code_samples/freeze/set-individual-freeze.js
Normal file
@@ -0,0 +1,57 @@
|
||||
const {RippleAPI} = require('ripple-lib');
|
||||
|
||||
const api = new RippleAPI({
|
||||
server: 'wss://s1.ripple.com' // Public rippled server
|
||||
});
|
||||
api.on('error', (errorCode, errorMessage) => {
|
||||
console.log(errorCode + ': ' + errorMessage);
|
||||
});
|
||||
|
||||
const issuing_address = 'rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn';
|
||||
const issuing_secret = 's████████████████████████████';
|
||||
// Best practice: get your secret from an encrypted
|
||||
// config file instead
|
||||
const address_to_freeze = 'rUpy3eEg8rqjqfUoLeBnZkscbKbFsKXC3v';
|
||||
const currency_to_freeze = 'USD';
|
||||
|
||||
api.connect().then(() => {
|
||||
|
||||
// Look up current state of trust line
|
||||
const options = {counterparty: address_to_freeze,
|
||||
currency: currency_to_freeze};
|
||||
console.log('looking up', currency_to_freeze, 'trust line from',
|
||||
issuing_address, 'to', address_to_freeze);
|
||||
return api.getTrustlines(issuing_address, options);
|
||||
|
||||
}).then(data => {
|
||||
|
||||
// Prepare a trustline transaction to enable freeze
|
||||
let trustline = {};
|
||||
if (data.length !== 1) {
|
||||
console.log('trustline not found, making a default one');
|
||||
trustline = {
|
||||
currency: currency_to_freeze,
|
||||
counterparty: address_to_freeze,
|
||||
limit: 0
|
||||
};
|
||||
} else {
|
||||
trustline = data[0].specification;
|
||||
console.log('trustline found. previous state:', trustline);
|
||||
}
|
||||
|
||||
trustline.frozen = true;
|
||||
|
||||
console.log('preparing trustline transaction for line:', trustline);
|
||||
return api.prepareTrustline(issuing_address, trustline);
|
||||
|
||||
}).then(prepared_tx => {
|
||||
|
||||
// Sign and submit the trustline transaction
|
||||
console.log('signing tx:', prepared_tx.txJSON);
|
||||
const signed1 = api.sign(prepared_tx.txJSON, issuing_secret);
|
||||
console.log('submitting tx:', signed1.id);
|
||||
|
||||
return api.submit(signed1.signedTransaction);
|
||||
}).then(() => {
|
||||
return api.disconnect();
|
||||
}).catch(console.error);
|
||||
36
content/code_samples/freeze/set-no-freeze.js
Normal file
@@ -0,0 +1,36 @@
|
||||
const {RippleAPI} = require('ripple-lib');
|
||||
|
||||
const api = new RippleAPI({
|
||||
server: 'wss://s1.ripple.com' // Public rippled server
|
||||
});
|
||||
api.on('error', (errorCode, errorMessage) => {
|
||||
console.log(errorCode + ': ' + errorMessage);
|
||||
});
|
||||
|
||||
const issuing_address = 'rUpy3eEg8rqjqfUoLeBnZkscbKbFsKXC3v';
|
||||
const issuing_secret = 'snnDVkSW3aV6jvMJTPdCiE2Qxv1RW';
|
||||
// Best practice: get your secret from an encrypted
|
||||
// config file instead
|
||||
|
||||
api.connect().then(() => {
|
||||
|
||||
// Prepare a settings transaction to enable no freeze
|
||||
const settings = {
|
||||
'noFreeze': true
|
||||
};
|
||||
|
||||
console.log('preparing settings transaction for account:',
|
||||
issuing_address);
|
||||
return api.prepareSettings(issuing_address, settings);
|
||||
|
||||
}).then(prepared_tx => {
|
||||
|
||||
// Sign and submit the settings transaction
|
||||
console.log('signing tx:', prepared_tx.txJSON);
|
||||
const signed1 = api.sign(prepared_tx.txJSON, issuing_secret);
|
||||
console.log('submitting tx:', signed1.id);
|
||||
|
||||
return api.submit(signed1.signedTransaction);
|
||||
}).then(() => {
|
||||
return api.disconnect();
|
||||
}).catch(console.error);
|
||||
34
content/code_samples/rippleapi_quickstart/browser-demo.html
Normal file
@@ -0,0 +1,34 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<script src="ripple-0.16.5.js"></script>
|
||||
<script>
|
||||
console.log(ripple);
|
||||
var api = new ripple.RippleAPI({server:'wss://s1.ripple.com/'});
|
||||
api.connect().then(function() {
|
||||
return api.getServerInfo();
|
||||
}).then(function(server_info) {
|
||||
document.body.innerHTML += "<p>Connected to rippled server!</p>" +
|
||||
" <table>" +
|
||||
" <tr><th>Version</th>" +
|
||||
" <td>" + server_info.buildVersion + "</td></tr>" +
|
||||
" <tr><th>Ledgers available</th>" +
|
||||
" <td>" + server_info.completeLedgers + "</td></tr>" +
|
||||
" <tr><th>hostID</th>" +
|
||||
" <td>" + server_info.hostID + "</td></tr>" +
|
||||
" <tr><th>Most Recent Validated Ledger Seq.</th>" +
|
||||
" <td>" + server_info.validatedLedger.ledgerVersion + "</td></tr>" +
|
||||
" <tr><th>Most Recent Validated Ledger Hash</th>" +
|
||||
" <td>" + server_info.validatedLedger.hash + "</td></tr>" +
|
||||
" <tr><th>Seconds since last ledger validated</th>" +
|
||||
" <td>" + server_info.validatedLedger.age + "</td></tr>" +
|
||||
" </table>";
|
||||
});
|
||||
</script>
|
||||
<style type="text/css">
|
||||
td, th { border: 1px solid black; padding: 5px; }
|
||||
table { border-collapse: collapse; }
|
||||
</style>
|
||||
</head>
|
||||
<body></body>
|
||||
</html>
|
||||
201
content/code_samples/rippleapi_quickstart/eslintrc
Normal file
@@ -0,0 +1,201 @@
|
||||
# ESLint documentation can be found at http://eslint.org/docs/
|
||||
env:
|
||||
browser: true
|
||||
node: true
|
||||
amd: false
|
||||
mocha: true
|
||||
jasmine: false
|
||||
es6: true
|
||||
rules:
|
||||
no-alert: 2
|
||||
no-array-constructor: 2
|
||||
no-arrow-condition: 0
|
||||
no-bitwise: 0
|
||||
no-caller: 2
|
||||
no-case-declarations: 2
|
||||
no-catch-shadow: 2
|
||||
no-class-assign: 2
|
||||
no-cond-assign: [2, 'always']
|
||||
no-console: 0
|
||||
no-const-assign: 2
|
||||
no-constant-condition: 2
|
||||
no-continue: 0
|
||||
no-control-regex: 2
|
||||
no-debugger: 2
|
||||
no-delete-var: 2
|
||||
no-div-regex: 0
|
||||
no-dupe-class-members: 2
|
||||
no-dupe-keys: 2
|
||||
no-dupe-args: 2
|
||||
no-duplicate-case: 2
|
||||
no-else-return: 0
|
||||
no-empty: 2
|
||||
no-empty-character-class: 2
|
||||
no-empty-label: 2
|
||||
no-empty-pattern: 2
|
||||
no-eq-null: 2
|
||||
no-eval: 2
|
||||
no-ex-assign: 2
|
||||
no-extend-native: 2
|
||||
no-extra-bind: 2
|
||||
no-extra-boolean-cast: 2
|
||||
no-extra-parens: [2, 'functions']
|
||||
no-extra-semi: 2
|
||||
no-fallthrough: 2
|
||||
no-floating-decimal: 0
|
||||
no-func-assign: 2
|
||||
no-implicit-coercion: 2
|
||||
no-implied-eval: 2
|
||||
no-inline-comments: 0
|
||||
no-inner-declarations: [2, 'functions']
|
||||
no-invalid-regexp: 2
|
||||
no-invalid-this: 0 # this rule would cause problems with mocha test cases
|
||||
no-irregular-whitespace: 2
|
||||
no-iterator: 2
|
||||
no-label-var: 2
|
||||
no-labels: 2
|
||||
no-lone-blocks: 2
|
||||
no-lonely-if: 2
|
||||
no-loop-func: 2
|
||||
no-mixed-requires: [0, false]
|
||||
no-mixed-spaces-and-tabs: [2, false]
|
||||
linebreak-style: [2, 'unix']
|
||||
no-multi-spaces: 2
|
||||
no-multi-str: 2
|
||||
no-multiple-empty-lines: [2, {max: 2}]
|
||||
no-native-reassign: 2
|
||||
no-negated-condition: 0
|
||||
no-negated-in-lhs: 2
|
||||
no-nested-ternary: 0
|
||||
no-new: 2
|
||||
no-new-func: 2
|
||||
no-new-object: 2
|
||||
no-new-require: 0
|
||||
no-new-wrappers: 2
|
||||
no-obj-calls: 2
|
||||
no-octal: 2
|
||||
no-octal-escape: 2
|
||||
no-param-reassign: 2
|
||||
no-path-concat: 0
|
||||
no-plusplus: 0
|
||||
no-process-env: 0
|
||||
no-process-exit: 0
|
||||
no-proto: 2
|
||||
no-redeclare: 2
|
||||
no-regex-spaces: 2
|
||||
no-restricted-modules: 0
|
||||
no-restricted-syntax: 0
|
||||
no-return-assign: 2
|
||||
no-script-url: 2
|
||||
no-self-compare: 2
|
||||
no-sequences: 2
|
||||
no-shadow: 2
|
||||
no-shadow-restricted-names: 2
|
||||
no-spaced-func: 2
|
||||
no-sparse-arrays: 2
|
||||
no-sync: 0
|
||||
no-ternary: 0
|
||||
no-trailing-spaces: 2
|
||||
no-this-before-super: 2
|
||||
no-throw-literal: 2
|
||||
no-undef: 2
|
||||
no-undef-init: 2
|
||||
no-undefined: 0
|
||||
no-unexpected-multiline: 2
|
||||
no-underscore-dangle: 0
|
||||
no-unneeded-ternary: 0
|
||||
no-unreachable: 2
|
||||
no-unused-expressions: 2
|
||||
no-unused-vars: [2, {vars: 'all', args: 'all'}]
|
||||
no-use-before-define: 2
|
||||
no-useless-call: 2
|
||||
no-useless-concat: 0
|
||||
no-void: 2
|
||||
no-var: 2
|
||||
no-warning-comments: [0, {terms: ['todo', 'fixme', 'xxx'], location: 'start'}]
|
||||
no-with: 2
|
||||
no-magic-numbers: 0
|
||||
|
||||
array-bracket-spacing: [2, 'never']
|
||||
arrow-body-style: 0
|
||||
arrow-parens: [2, 'as-needed']
|
||||
arrow-spacing: 2
|
||||
accessor-pairs: 2
|
||||
block-scoped-var: 2
|
||||
block-spacing: 2
|
||||
brace-style: 2
|
||||
callback-return: 0
|
||||
camelcase: 0
|
||||
comma-dangle: 2
|
||||
comma-spacing: 2
|
||||
comma-style: 2
|
||||
complexity: [0, 11]
|
||||
computed-property-spacing: 2
|
||||
consistent-return: 2
|
||||
consistent-this: [2, 'self']
|
||||
constructor-super: 2
|
||||
curly: [2, 'all']
|
||||
default-case: 0
|
||||
dot-location: [2, 'property']
|
||||
dot-notation: [2, {allowKeywords: true}]
|
||||
eol-last: 2
|
||||
eqeqeq: 2
|
||||
func-names: 0
|
||||
func-style: [2, 'declaration']
|
||||
generator-star-spacing: 2
|
||||
global-require: 0
|
||||
guard-for-in: 0
|
||||
handle-callback-err: 2
|
||||
id-length: 0
|
||||
indent: [2, 2, {SwitchCase: 1}]
|
||||
init-declarations: 0
|
||||
jsx-quotes: 0
|
||||
key-spacing: [2, {beforeColon: false, afterColon: true}]
|
||||
lines-around-comment: 0
|
||||
max-depth: [0, 4]
|
||||
max-len: [2, 80]
|
||||
max-nested-callbacks: [0, 2]
|
||||
max-params: [0, 4]
|
||||
max-statements: [0, 10]
|
||||
new-cap: 2
|
||||
new-parens: 2
|
||||
newline-after-var: 0
|
||||
object-curly-spacing: [2, 'never']
|
||||
object-shorthand: 0
|
||||
one-var: [2, 'never']
|
||||
operator-assignment: [0, 'always']
|
||||
operator-linebreak: 0
|
||||
padded-blocks: 0
|
||||
prefer-arrow-callback: 0
|
||||
prefer-const: 2
|
||||
prefer-spread: 2
|
||||
prefer-reflect: 0
|
||||
prefer-template: 0
|
||||
quote-props: 0
|
||||
quotes: [2, 'single']
|
||||
radix: 2
|
||||
id-match: 0
|
||||
require-jsdoc: 0
|
||||
require-yield: 0
|
||||
semi: 2
|
||||
semi-spacing: 2
|
||||
sort-vars: 0
|
||||
space-after-keywords: 2
|
||||
space-before-keywords: 2
|
||||
space-before-blocks: 2
|
||||
space-before-function-paren: [2, 'never']
|
||||
space-in-parens: 2
|
||||
space-infix-ops: 2
|
||||
space-return-throw-case: 2
|
||||
space-unary-ops: [2, {words: true, nonwords: false}]
|
||||
spaced-comment: 2
|
||||
strict: [2, 'global']
|
||||
use-isnan: 2
|
||||
valid-jsdoc: 2
|
||||
valid-typeof: 2
|
||||
vars-on-top: 0
|
||||
wrap-iife: 0
|
||||
wrap-regex: 0
|
||||
yoda: [2, 'never']
|
||||
ecmaFeatures:
|
||||
jsx: true
|
||||
@@ -0,0 +1,23 @@
|
||||
'use strict';
|
||||
const RippleAPI = require('ripple-lib').RippleAPI;
|
||||
|
||||
const api = new RippleAPI({
|
||||
server: 'wss://s1.ripple.com' // Public rippled server
|
||||
});
|
||||
api.connect().then(() => {
|
||||
/* 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 -------------------------------------- */
|
||||
}).then(() => {
|
||||
return api.disconnect();
|
||||
}).then(() => {
|
||||
console.log('done and disconnected.');
|
||||
}).catch(console.error);
|
||||
18
content/code_samples/rippleapi_quickstart/package.json
Normal file
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"name": "my_ripple_experiment",
|
||||
"version": "0.0.1",
|
||||
"license": "MIT",
|
||||
"private": true,
|
||||
"//": "Change the license to something appropriate. You may want to use 'UNLICENSED' if you are just starting out.",
|
||||
"dependencies": {
|
||||
"ripple-lib": "*",
|
||||
"babel-cli": "^6.0.0",
|
||||
"babel-preset-es2015": "*"
|
||||
},
|
||||
"babel": {
|
||||
"presets": ["es2015"]
|
||||
},
|
||||
"devDependencies": {
|
||||
"eslint": "*"
|
||||
}
|
||||
}
|
||||
69062
content/code_samples/rippleapi_quickstart/ripple-0.16.5.js
Normal file
@@ -0,0 +1,92 @@
|
||||
'use strict';
|
||||
/* import RippleAPI and support libraries */
|
||||
const RippleAPI = require('ripple-lib').RippleAPI;
|
||||
const assert = require('assert');
|
||||
|
||||
/* Credentials of the account placing the order */
|
||||
const myAddr = 'rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn';
|
||||
const mySecret = 's████████████████████████████';
|
||||
|
||||
/* Define the order to place here */
|
||||
const myOrder = {
|
||||
'direction': 'buy',
|
||||
'quantity': {
|
||||
'currency': 'FOO',
|
||||
'counterparty': 'rUpy3eEg8rqjqfUoLeBnZkscbKbFsKXC3v',
|
||||
'value': '100'
|
||||
},
|
||||
'totalPrice': {
|
||||
'currency': 'XRP',
|
||||
'value': '1000'
|
||||
}
|
||||
};
|
||||
|
||||
/* Milliseconds to wait between checks for a new ledger. */
|
||||
const INTERVAL = 1000;
|
||||
/* Instantiate RippleAPI. Uses s2 (full history server) */
|
||||
const api = new RippleAPI({server: 'wss://s2.ripple.com'});
|
||||
/* number of ledgers to check for valid transaction before fail */
|
||||
const ledgerOffset = 5;
|
||||
const myInstructions = {maxLedgerVersionOffset: ledgerOffset};
|
||||
|
||||
|
||||
/* Verify a transaction is in a validated RCL version */
|
||||
function verifyTransaction(hash, options) {
|
||||
console.log('Verifing Transaction');
|
||||
return api.getTransaction(hash, options).then(data => {
|
||||
console.log('Final Result: ', data.outcome.result);
|
||||
console.log('Validated in Ledger: ', data.outcome.ledgerVersion);
|
||||
console.log('Sequence: ', data.sequence);
|
||||
return data.outcome.result === 'tesSUCCESS';
|
||||
}).catch(error => {
|
||||
/* if transaction not in latest validated ledger,
|
||||
try again until max ledger hit */
|
||||
if (error instanceof api.errors.PendingLedgerVersionError) {
|
||||
return new Promise((resolve, reject) => {
|
||||
setTimeout(() => verifyTransaction(hash, options)
|
||||
.then(resolve, reject), INTERVAL);
|
||||
});
|
||||
}
|
||||
return error;
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
/* function to prepare, sign, and submit a transaction to the RCL
|
||||
success verifies the transaction is being considered for the next ledger.
|
||||
Still requires vlaidation */
|
||||
function submitTransaction(lastClosedLedgerVersion, prepared, secret) {
|
||||
const signedData = api.sign(prepared.txJSON, secret);
|
||||
return api.submit(signedData.signedTransaction).then(data => {
|
||||
console.log('Tentative Result: ', data.resultCode);
|
||||
console.log('Tentative Message: ', data.resultMessage);
|
||||
/* if transaction was not successfully submitted throw error */
|
||||
assert.strictEqual(data.resultCode, 'tesSUCCESS');
|
||||
/* if successfully submitted fire off validation workflow */
|
||||
const options = {
|
||||
minLedgerVersion: lastClosedLedgerVersion,
|
||||
maxLedgerVersion: prepared.instructions.maxLedgerVersion
|
||||
};
|
||||
return new Promise((resolve, reject) => {
|
||||
setTimeout(() => verifyTransaction(signedData.id, options)
|
||||
.then(resolve, reject), INTERVAL);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
api.connect().then(() => {
|
||||
console.log('Connected');
|
||||
return api.prepareOrder(myAddr, myOrder, myInstructions);
|
||||
}).then(prepared => {
|
||||
console.log('Order Prepared');
|
||||
return api.getLedger().then(ledger => {
|
||||
console.log('Current Ledger', ledger.ledgerVersion);
|
||||
return submitTransaction(ledger.ledgerVersion, prepared, mySecret);
|
||||
});
|
||||
}).then(() => {
|
||||
api.disconnect().then(() => {
|
||||
console.log('api disconnected');
|
||||
process.exit();
|
||||
});
|
||||
}).catch(console.error);
|
||||
174
content/concept-amendments.md
Normal file
@@ -0,0 +1,174 @@
|
||||
# Amendments #
|
||||
|
||||
_(New in [version 0.31.0](https://wiki.ripple.com/Rippled-0.31.0))_
|
||||
|
||||
The Amendments system provides a means of introducing new features to the decentralized Ripple consensus network without causing disruptions. The amendments system works by utilizing the core consensus process of the network to approve any changes by showing continuous support before those changes go into effect. An amendment normally requires **80% support for two weeks** before it can apply.
|
||||
|
||||
When an Amendment has been enabled, it applies permanently to all ledger versions after the one that included it. You cannot disable an Amendment, unless you introduce a new Amendment to do so.
|
||||
|
||||
|
||||
## Background ##
|
||||
|
||||
Any changes to transaction processing could cause servers to build a different ledger with the same set of transactions. If only a portion of _validators_ (`rippled` servers [participating in consensus](tutorial-rippled-setup.html#reasons-to-run-a-validator)) have upgraded to a new version of the software, this could cause anything from minor inconveniences to full outages. In the minor case, a minority of servers spend more time and bandwidth fetching the actual consensus ledger because they cannot build it using the transaction processing rules they already know. In the worst case, [the consensus process](https://ripple.com/knowledge_center/the-ripple-ledger-consensus-process/) might be unable to validate new ledger versions because servers with different rules could not reach a consensus on the exact ledger to build.
|
||||
|
||||
Amendments provide a solution to this problem, so that new features can be enabled only when enough validators support those features.
|
||||
|
||||
Users and businesses who rely on the Ripple Consensus Ledger can also use Amendments to provide advance notice of changes in transaction processing that might affect their business. However, API changes that do not impact transaction processing or [the consensus process](https://ripple.com/knowledge_center/the-ripple-ledger-consensus-process/) do not require Amendments.
|
||||
|
||||
|
||||
## About Amendments ##
|
||||
|
||||
An amendment is a fully-functional feature or change, waiting to be enabled by the peer-to-peer network as a part of the consensus process. A `rippled` server that wants to use an amendment has code for two modes: without the amendment (previous behavior) and with the amendment (new behavior).
|
||||
|
||||
Every amendment has a unique identifying hex value and a short name. The short name is for human use, and is not used in the amendment process. Two servers can support the same amendment ID while using different names to describe it. An amendment's name is not guaranteed to be unique.
|
||||
|
||||
See also: [Known Amendments](#known-amendments)
|
||||
|
||||
## Amendment Process ##
|
||||
|
||||
Every 256th ledger is called a "flag" ledger. The process of approving an amendment starts in the ledger version immediately before the flag ledger. When `rippled` validator servers send validation messages for that ledger, those servers also submit votes in favor of specific amendments. ([Fee Voting](concept-fee-voting.html) also occurs around flag ledgers.)
|
||||
|
||||
The flag ledger itself has no special contents. However, during that time, the servers look at the votes of the validators they trust, and decide whether to insert an [`EnableAmendment` pseudo-transaction](reference-transaction-format.html#enableamendment) into the following ledger. The flags of an EnableAmendment pseudo-transaction indicate what the server thinks happened:
|
||||
|
||||
* The `tfGotMajority` flag means that support for the amendment has increased to at least 80% of trusted validators.
|
||||
* The `tfLostMajority` flag means that support for the amendment has decreased to less than 80% of trusted validators.
|
||||
* An EnableAmendment pseudo-transaction with no flags means that support for the amendment has been enabled. (The change in transaction processing applies to every ledger after this one.)
|
||||
|
||||
A server only inserts the pseudo-transaction to enable an amendment if all of the following conditions are met:
|
||||
|
||||
* The amendment has not already been enabled.
|
||||
* A previous ledger includes an EnableAmendment pseudo-transaction for this amendment with the `tfGotMajority` flag enabled.
|
||||
* The previous ledger in question is an ancestor of the current ledger.
|
||||
* The previous ledger in question has a close time that is at least **two weeks** before the close time of the latest flag ledger.
|
||||
* There are no EnableAmendment pseudo-transactions for this amendment with the `tfLostMajority` flag enabled in the consensus ledgers between the `tfGotMajority` pseudo-transaction and the current ledger.
|
||||
|
||||
It is theoretically possible (but extremely unlikely) that a `tfLostMajority` EnableAmendment pseudo-transaction could be included in the same ledger as the pseudo-transaction to enable an amendment. In this case, the pseudo-transaction with the `tfLostMajority` pseudo-transaction has no effect.
|
||||
|
||||
## Amendment Voting ##
|
||||
|
||||
Operators of `rippled` validators can choose which amendments to support or reject using the [`feature` command](reference-rippled.html#feature). This decides which amendments the validator votes for in the [amendment process](#amendment-process). By default, `rippled` votes in favor of every amendment it knows about.
|
||||
|
||||
The operator of a `rippled` validator can "veto" an amendment. In this case, that validator never sends a vote in favor of the amendment. If enough servers veto an amendment, that prevents it from reaching consistent 80% support, so the amendment does not apply.
|
||||
|
||||
As with all aspects of the consensus process, amendment votes are only taken into account by servers that trust the validators sending those votes. Currently, Ripple (the company) recommends only trusting the 5 default validators that Ripple (the company) operates. For now, trusting only those validators is sufficient to coordinate with Ripple (the company) on releasing new features.
|
||||
|
||||
### Configuring Amendment Voting ###
|
||||
|
||||
You can temporarily configure an amendment using the [`feature` command](reference-rippled.html#feature). To make a persistent change to your server's support for an amendment, modify your server's `rippled.cfg` file.
|
||||
|
||||
Use the `[veto_amendments]` stanza to list amendments you do not want the server to vote for. Each line should contain one amendment's unique ID, optionally followed by the short name for the amendment. For example:
|
||||
|
||||
```
|
||||
[veto_amendments]
|
||||
C1B8D934087225F509BEB5A8EC24447854713EE447D277F69545ABFA0E0FD490 Tickets
|
||||
DA1BD556B42D85EA9C84066D028D355B52416734D3283F85E216EA5DA6DB7E13 SusPay
|
||||
```
|
||||
|
||||
Use the `[amendments]` stanza to list amendments you want to vote for. (Even if you do not list them here, by default a server votes for all the amendments it knows how to apply.) Each line should contain one amendment's unique ID, optionally followed by the short name for the amendment. For example:
|
||||
|
||||
```
|
||||
[amendments]
|
||||
4C97EBA926031A7CF7D7B36FDE3ED66DDA5421192D63DE53FFB46E43B9DC8373 MultiSign
|
||||
42426C4D4F1009EE67080A9B7965B44656D7714D104A72F9B4369F97ABF044EE FeeEscalation
|
||||
```
|
||||
|
||||
|
||||
## Testing Amendments ##
|
||||
|
||||
If you want to see how `rippled` behaves with an amendment enabled, before that amendment gets enabled on the production network, you can run use `rippled`'s configuration file to forcibly enable a feature. This is intended for development purposes only.
|
||||
|
||||
Because other members of the consensus network probably do not have the feature enabled, you should not use this feature while connecting to the production network. While testing with features forcibly enabled, you should run `rippled` in [Stand-Alone Mode](concept-stand-alone-mode.html).
|
||||
|
||||
To forcibly enable a feature, add a `[features]` stanza to your `rippled.cfg` file. In this stanza, add the short names of the features to enable, one per line. For example:
|
||||
|
||||
```
|
||||
[features]
|
||||
MultiSign
|
||||
TrustSetAuth
|
||||
```
|
||||
|
||||
|
||||
|
||||
# Known Amendments #
|
||||
|
||||
The following is a comprehensive list of all known amendments and their status on the production Ripple Consensus Ledger:
|
||||
|
||||
| Name | Introduced | Enabled |
|
||||
|---------------------------------|------------|---------|
|
||||
| [Tickets](#tickets) | v0.31.0 | TBD |
|
||||
| [SusPay](#suspay) | v0.31.0 | TBD |
|
||||
| [TrustSetAuth](#trustsetauth) | v0.30.0 | TBD |
|
||||
| [MultiSign](#multisign) | v0.31.0 | TBD |
|
||||
| [FeeEscalation](#feeescalation) | v0.31.0 | TBD |
|
||||
|
||||
**Note:** In many cases, an incomplete version of the code for an amendment is present in previous versions of the software. The "Introduced" version in the table above is the first stable version.
|
||||
|
||||
## FeeEscalation ##
|
||||
|
||||
| Amendment ID |
|
||||
|--------------|
|
||||
| 42426C4D4F1009EE67080A9B7965B44656D7714D104A72F9B4369F97ABF044EE |
|
||||
|
||||
Changes the way the [transaction cost](concept-transaction-cost.html) applies to proposed transactions. Modifies the consensus process to prioritize transactions that pay a higher transaction cost.
|
||||
|
||||
This amendment introduces a fixed-size transaction queue for transactions that were not able to be included in the previous consensus round. If the `rippled` servers in the consensus network are under heavy load, they queue the transactions with the lowest transaction cost for later ledgers. Each consensus round prioritizes transactions from the queue with the largest transaction cost (`Fee` value), and includes as many transactions as the consensus network can process. If the transaction queue is full, transactions drop from the queue entirely, starting with the ones that have the lowest transaction cost.
|
||||
|
||||
While the consensus network is under heavy load, legitimate users can pay a higher transaction cost to make sure their transactions get processed. The situation persists until the entire backlog of cheap transactions is processed or discarded.
|
||||
|
||||
A transaction remains in the queue until one of the following happens:
|
||||
|
||||
* It gets applied to a validated ledger (regardless of success or failure)
|
||||
* It becomes invalid (for example, the [`LastLedgerSequence`](reference-transaction-format.html#lastledgersequence) causes it to expire)
|
||||
* It gets dropped because there are too many transactions in the queue with a higher transaction cost.
|
||||
|
||||
## MultiSign ##
|
||||
|
||||
| Amendment ID |
|
||||
|--------------|
|
||||
| 4C97EBA926031A7CF7D7B36FDE3ED66DDA5421192D63DE53FFB46E43B9DC8373 |
|
||||
|
||||
Introduces simple [multi-signing](reference-transaction-format.html#multi-signing) as a way to authorize transactions. Creates the [`SignerList` ledger node type](reference-ledger-format.html#signerlist) and the [`SignerListSet` transaction type](reference-transaction-format.html#signerlistset). Adds the optional `Signers` field to all transaction types. Modifies some transaction result codes.
|
||||
|
||||
This amendment allows addresses to have a list of signers who can authorize transactions from that address in a multi-signature. The list has a quorum and 1 to 8 weighted signers. This allows various configurations, such as "any 3-of-5" or "signature from A plus any other two signatures."
|
||||
|
||||
Signers can be funded or unfunded addresses. Funded addresses in a signer list can sign using a regular key (if defined) or master key (unless disabled). Unfunded addresses can sign with a master key. Multi-signed transactions have the same permissions as transactions signed with a regular key.
|
||||
|
||||
An address with a SignerList can disable the master key even if a regular key is not defined. An address with a SignerList can also remove a regular key even if the master key is disabled. Therefore, the `tecMASTER_DISABLED` transaction result code is renamed `tecNO_ALTERNATIVE_KEY`. The `tecNO_REGULAR_KEY` transaction result is retired and replaced with `tecNO_ALTERNATIVE_KEY`. Additionally, this amendment adds the following new [transaction result codes](reference-transaction-format.html#result-categories):
|
||||
|
||||
* `temBAD_SIGNER`
|
||||
* `temBAD_QUORUM`
|
||||
* `temBAD_WEIGHT`
|
||||
* `tefBAD_SIGNATURE`
|
||||
* `tefBAD_QUORUM`
|
||||
* `tefNOT_MULTI_SIGNING`
|
||||
* `tefBAD_AUTH_MASTER`
|
||||
|
||||
## SusPay ##
|
||||
|
||||
| Amendment ID |
|
||||
|--------------|
|
||||
| DA1BD556B42D85EA9C84066D028D355B52416734D3283F85E216EA5DA6DB7E13 |
|
||||
|
||||
Provides "Suspended Payments" for XRP as a means of escrow within the Ripple Consensus Ledger. Creates the `SuspendedPayment` ledger node type and the new transaction types `SuspendedPaymentCreate`, `SuspendedPaymentFinish`, and `SuspendedPaymentCancel`.
|
||||
|
||||
This amendment is still in development. The current version is enabled on the [Ripple Test Net](https://ripple.com/build/ripple-test-net/).
|
||||
|
||||
## TrustSetAuth ##
|
||||
|
||||
| Amendment ID |
|
||||
|--------------|
|
||||
| 6781F8368C4771B83E8B821D88F580202BCB4228075297B19E4FDC5233F1EFDC |
|
||||
|
||||
Allows pre-authorization of accounting relationships (zero-balance trust lines) when using [Authorized Accounts](tutorial-gateway-guide.html#authorized-accounts).
|
||||
|
||||
With this amendment enabled, a `TrustSet` transaction with [`tfSetfAuth` enabled](reference-transaction-format.html#trustset-flags) can create a new [`RippleState` ledger node](reference-ledger-format.html#ripplestate) even if it keeps all the other values of the `RippleState` node in their default state. The new `RippleState` node has the [`lsfLowAuth` or `lsfHighAuth` flag](reference-ledger-format.html#ripplestate-flags) enabled accordingly. The sender of the transaction must have [`lsfRequireAuth` enabled](reference-ledger-format.html#accountroot-flags).
|
||||
|
||||
## Tickets ##
|
||||
|
||||
| Amendment ID |
|
||||
|--------------|
|
||||
| C1B8D934087225F509BEB5A8EC24447854713EE447D277F69545ABFA0E0FD490 |
|
||||
|
||||
Introduces Tickets as a way to reserve a transaction sequence number for later execution. Creates the `Ticket` ledger node type and the transaction types `TicketCreate` and `TicketCancel`.
|
||||
|
||||
This amendment is still in development.
|
||||
27
content/concept-fee-voting.md
Normal file
@@ -0,0 +1,27 @@
|
||||
# Fee Voting #
|
||||
|
||||
Validators can vote for changes to basic [transaction cost](concept-transaction-cost.html) as well as [reserve requirements](concept-reserves.html). If the preferences in a validator's configuration are different than the network's current settings, the validator expresses its preferences to the network periodically. If a quorum of validators agrees on a change, they can apply a change that takes effect thereafter. Validators may do this for various reasons, especially to reflect long-term changes in the value of XRP.
|
||||
|
||||
Operators of [`rippled` validators](tutorial-rippled-setup.html#running-a-validator) can set their preferences for the transaction cost and reserve requirements in the `[voting]` stanza of the `rippled.cfg` file. **Caution:** insufficient requirements could expose the Ripple peer-to-peer network to denial-of-service attacks. The parameters you can set are as follows:
|
||||
|
||||
| Parameter | Description | Recommended Value |
|
||||
|-----------|-------------|-------------------|
|
||||
| reference\_fee | Amount of XRP, in _drops_, that must be destroyed to send the reference transaction, the cheapest possible transaction. (1 XRP = 1 million drops.) The actual transaction cost is a multiple of this value, scaled dynamically based on the load of individual servers. | `10` (0.00001 XRP) |
|
||||
| account\_reserve | Minimum amount of XRP, in _drops_, that an account must have on reserve. This is the smallest amount that can be sent to fund a new account in the ledger. | `20000000` (20 XRP) |
|
||||
| owner\_reserve | Additional amount of XRP, in _drops_, that an account must have on reserve for _each_ object it owns in the ledger. | `5000000` (5 XRP) |
|
||||
|
||||
### Voting Process ###
|
||||
|
||||
Every 256th ledger is called a "flag" ledger. (A flag ledger is defined such that the `ledger_index` [modulo](https://en.wikipedia.org/wiki/Modulo_operation) `256` is equal to `0`.) In the ledger immediately before the flag ledger, each validator whose account reserve or transaction cost preferences are different than the current network setting distributes a "vote" message alongside its ledger validation, indicating the values that validator prefers.
|
||||
|
||||
In the flag ledger itself, nothing happens, but validators receive and take note of the votes from other validators they trust.
|
||||
|
||||
After counting the votes of other validators, each validator attempts to compromise between its own preferences and the preferences of a majority of validators it trusts. (For example, if one validator wants to raise the minimum transaction cost from 10 to 100, but most validators only want to raise it from 10 to 20, the one validator settles on the change to raise the cost to 20. However, the one validator never settles on a value lower than 10 or higher than 100.) If a compromise is possible, the validator inserts a [SetFee pseudo-transaction](reference-transaction-format.html#setfee) into its proposal for the ledger following the flag ledger. Other validators who want the same change insert an identical SetFee pseudo-transaction into their proposals for the same ledger. (Validators whose preferences match the existing network settings do nothing.) If a SetFee psuedo-transaction survives the consensus process to be included in a validated ledger, then the new transaction cost and reserve settings denoted by the SetFee pseudo-transaction take effect starting with the following ledger.
|
||||
|
||||
In short:
|
||||
|
||||
* **Flag ledger -1**: Validators submit votes.
|
||||
* **Flag ledger**: Validators tally votes and decide what SetFee to include, if any.
|
||||
* **Flag ledger +1**: Validators insert SetFee pseudo-transaction into their proposed ledgers.
|
||||
* **Flag ledger +2**: New settings take effect, if a SetFee psuedotransaction achieved consensus.
|
||||
|
||||
27
content/concept-fees.md
Normal file
@@ -0,0 +1,27 @@
|
||||
# Fees (Disambiguation) #
|
||||
|
||||
The Ripple Consensus Ledger is a decentralized ledger, secured by cryptography and operated by a distributed peer-to-peer network of servers. This means that no one party, not even Ripple, can require a fee for access to the network.
|
||||
|
||||
However, the rules of the Ripple Consensus Ledger include several types of fees, including neutral fees which protect the ledger against abuse. These neutral fees are not paid to anyone. There are also several optional ways that users can collect fees from each other, both inside and outside the Ripple Consensus Ledger.
|
||||
|
||||
|
||||
## In the Ledger ##
|
||||
|
||||
### Neutral Fees ###
|
||||
|
||||
The _**transaction cost**_ (sometimes called the transaction fee) is a miniscule amount of XRP destroyed in order to send a transaction. This cost scales with the load of the network, which protects the peer-to-peer network from spam. See [Transaction Cost](concept-transaction-cost.html) for more information.
|
||||
|
||||
The _**account reserve**_ is a minimum amount of XRP that an account must possess. It scales with the number of objects the account owns in the ledger. This disincentivizes users from increasing the size of the ledger carelessly or maliciously. See [Reserves](concept-reserves.html) for more information.
|
||||
|
||||
### Optional Fees ###
|
||||
|
||||
_**Transfer fees**_ are optional percentage fees that gateways can charge to transfer the currencies they issue to other accounts within the Ripple Consensus Ledger. See [Transfer Fees](concept-transfer-fees.html) for more information.
|
||||
|
||||
_**Trust line quality**_ is a setting that allows an account to value balances on a trust line at higher or lower than face value. This can lead to situations that are similar to charging a fee. Trust line quality does not apply to XRP, which is not tied to a trust line.
|
||||
|
||||
|
||||
## Outside the Ledger ##
|
||||
|
||||
Although the fees described above are the only fees built into the Ripple Consensus Ledger, people can still invent ways to charge fees associated with the ledger. For example, gateways commonly charge their customers to send money into and out of the Ripple Consensus Ledger.
|
||||
|
||||
Many other fees are also possible. Businesses might charge for access to a client application, maintenance of non-Ripple accounts, exchange services (especially when buying XRP on a private market instead of directly within the Ripple Consensus Ledger) and any number of other services. Always be aware of the fee schedule before doing business with any gateway or other financial institution.
|
||||
412
content/concept-freeze.md
Normal file
@@ -0,0 +1,412 @@
|
||||
Freeze Features
|
||||
===============
|
||||
|
||||
The Ripple Consensus Ledger gives accounts the ability to freeze non-XRP balances, which can be useful to comply with regulatory requirements, or while investigating suspicious activity. There are three settings related to freezes:
|
||||
|
||||
* [**Individual Freeze**](#individual-freeze) - Freeze one counterparty.
|
||||
* [**Global Freeze**](#global-freeze) - Freeze all counterparties.
|
||||
* [**No Freeze**](#no-freeze) - Permanently give up the ability to freeze individual counterparties, as well as the ability to end a global freeze.
|
||||
|
||||
Because no party has a privileged place in the Ripple Consensus Ledger, the freeze feature cannot prevent a counterparty from conducting transactions in XRP or funds issued by other counterparties. No one can freeze XRP.
|
||||
|
||||
All freeze settings can be enacted regardless of whether the balance(s) to be frozen are positive or negative. Either the currency issuer or the currency holder can freeze a trust line; however, the effect of a currency holder freezing an issuer is minimal.
|
||||
|
||||
|
||||
Individual Freeze
|
||||
-----------------
|
||||
|
||||
The **Individual Freeze** feature is a setting on a trust line. When an issuing account enables the Individual Freeze setting, the following rules apply:
|
||||
|
||||
* Payments can still occur directly between the two parties of the frozen trust line.
|
||||
* The counterparty of that trust line can no longer decrease its balance on the frozen trust line, except in direct payments to the issuer. The counterparty can only send the frozen issuances directly to the issuer.
|
||||
* The counterparty can still receive payments from others on the frozen trust line.
|
||||
* The counterparty's offers to sell the currency issued on the frozen trust line are [considered unfunded](reference-transaction-format.html#lifecycle-of-an-offer).
|
||||
|
||||
A gateway can freeze the trust line linking it to a counterparty if that counterparty shows suspicious activity or violates the gateway's terms of use. The gateway should also freeze the counterparty in any other systems the gateway operates that are connected to the Ripple Consensus Ledger. (Otherwise, an account might still be able to engage in undesired activity by sending payments through the gateway.)
|
||||
|
||||
An individual account can freeze its trust line to a gateway. This has no effect on transactions between the gateway and other users. It does, however, prevent other accounts, including [operational addresses](concept-issuing-and-operational-addresses.html), from sending that gateway's issued currency to the individual account. This type of individual freeze has no effect on offers.
|
||||
|
||||
The Individual Freeze applies to a single currency only. In order to freeze multiple currencies with a particular counterparty, the account must enable Individual Freeze on the trust lines for each currency individually.
|
||||
|
||||
An account cannot enable the Individual Freeze setting if it has previously enabled the [No Freeze](#no-freeze) setting.
|
||||
|
||||
|
||||
Global Freeze
|
||||
-------------
|
||||
|
||||
The **Global Freeze** feature is a setting on an account. When an issuing account enables the Global Freeze feature, the following rules apply:
|
||||
|
||||
* All counterparties of the frozen issuing account can no longer decrease the balances in their trust lines to the frozen account, except in direct payments to the issuer. (This also affects any [operational addresses](concept-issuing-and-operational-addresses.html).)
|
||||
* Counterparties of the frozen issuing account can still send and receive payments directly to and from the issuing account.
|
||||
* All offers to sell currencies issued by the frozen account are [considered unfunded](reference-transaction-format.html#lifecycle-of-an-offer).
|
||||
|
||||
It can be useful to enable Global Freeze on a gateway's [issuing account](concept-issuing-and-operational-addresses.html) if the secret key to an operational address is compromised, or immediately after regaining control of a such an address. This stops the flow of funds, preventing attackers from getting away with any more money or at least making it easier to track what happened. In addition to enacting a Global Freeze in the Ripple Consensus Ledger, a financial institution should also suspend activities in its connectors to outside systems.
|
||||
|
||||
It can also be useful to enable Global Freeze if a gateway intends to migrate to a new [issuing account](concept-issuing-and-operational-addresses.html), or if the gateway intends to cease doing business. This locks the funds at a specific point in time, so users cannot trade them away for other currencies.
|
||||
|
||||
Global Freeze applies to _all_ currencies issued and held by the account. You cannot enable Global Freeze for only one currency. If you want to have the ability to freeze some currencies and not others, you should use different accounts for each currency.
|
||||
|
||||
An account can always enable the Global Freeze setting. However, if the account has previously enabled the [No Freeze](#no-freeze) setting, it can never _disable_ Global Freeze.
|
||||
|
||||
|
||||
No Freeze
|
||||
---------
|
||||
|
||||
The **No Freeze** feature is a setting on an account that permanently gives up the ability to freeze counterparties. A business can use this feature to treat its issued funds as "more like physical money" in the sense that the business cannot interfere with customers trading it among themselves. The NoFreeze setting has two effects:
|
||||
|
||||
* The issuing account can no longer enable Individual Freeze on trust lines to any counterparty.
|
||||
* The issuing account can still enable Global Freeze to enact a global freeze, but the account cannot _disable_ Global Freeze.
|
||||
|
||||
The Ripple Consensus Ledger cannot force a gateway to honor the obligations that its issued funds represent, so giving up the ability to enable a Global Freeze cannot protect customers. However, giving up the ability to _disable_ a Global Freeze ensures that the Global Freeze feature is not used unfairly against some customers.
|
||||
|
||||
The No Freeze setting applies to all currencies issued to and from an account. If you want to be able to freeze some currencies but not others, you should use different accounts for each currency.
|
||||
|
||||
You can only enable the No Freeze setting with a transaction signed by your account's master key. You cannot use a [Regular Key](reference-transaction-format.html#setregularkey) or a [multi-signed transaction](reference-transaction-format.html#multi-signing) to enable No Freeze.
|
||||
|
||||
|
||||
# Technical Details #
|
||||
|
||||
## Enabling or Disabling Individual Freeze ##
|
||||
|
||||
### Using `rippled` ###
|
||||
|
||||
To enable or disable Individual Freeze on a specific trust line, send a `TrustSet` transaction. Use the [`tfSetFreeze` flag](reference-transaction-format.html#trustset-flags) to enable a freeze, and the `tfClearFreeze` flag to disable it. The fields of the transaction should be as follows:
|
||||
|
||||
| Field | Value | Description |
|
||||
|----------------------|--------|-------------|
|
||||
| Account | String | The address of your Ripple account. |
|
||||
| TransactionType | String | `TrustSet` |
|
||||
| LimitAmount | Object | Object defining the trust line to freeze. |
|
||||
| LimitAmount.currency | String | Currency of the trust line |
|
||||
| LimitAmount.issuer | String | The Ripple address of the counterparty to freeze |
|
||||
| LimitAmount.value | String | The amount of currency you trust this counterparty to issue to you, as a quoted number. From the perspective of a gateway, this is typically `"0"`. |
|
||||
| Flags | Number | To enable a freeze, use a value with the bit `0x00100000` (tfSetFreeze) enabled. To disable a freeze, use a value with the bit `0x00200000` (tfClearFreeze) enabled instead. |
|
||||
|
||||
Set the `Fee`, `Sequence`, and `LastLedgerSequence` parameters [in the typical way](reference-transaction-format.html#signing-and-submitting-transactions).
|
||||
|
||||
Example of submitting a TrustSet transaction to enable an individual freeze using the [WebSocket API](reference-rippled.html#websocket-api):
|
||||
|
||||
```
|
||||
{
|
||||
"id": 12,
|
||||
"command": "submit",
|
||||
"tx_json": {
|
||||
"TransactionType": "TrustSet",
|
||||
"Account": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn",
|
||||
"Fee": "12000",
|
||||
"Flags": 1048576,
|
||||
"LastLedgerSequence": 18103014,
|
||||
"LimitAmount": {
|
||||
"currency": "USD",
|
||||
"issuer": "rsA2LpzuawewSBQXkiju3YQTMzW13pAAdW",
|
||||
"value": "110"
|
||||
},
|
||||
"Sequence": 340
|
||||
},
|
||||
"secret": "s████████████████████████████",
|
||||
"offline": false,
|
||||
"fee_mult_max": 1000
|
||||
}
|
||||
```
|
||||
|
||||
(**Reminder**: Never transmit your account secret to an untrusted server or over an insecure channel.)
|
||||
|
||||
|
||||
### Using RippleAPI ###
|
||||
|
||||
To enable or disable Individual Freeze on a specific trust line, prepare a *Trustline* transaction using the [prepareTrustline](reference-rippleapi.html#preparetrustline) method. The fields of the `trustline` parameter should be set as follows:
|
||||
|
||||
| Field | Value | Description |
|
||||
|--------------|--------|-------------|
|
||||
| currency | String | The [currency](reference-rippleapi.html#currency) of the trust line to freeze |
|
||||
| counterparty | String | The [Ripple address](reference-rippleapi.html#ripple-address) of the counterparty |
|
||||
| limit | String | The amount of currency you trust this counterparty to issue to you, as a quoted number. From the perspective of a gateway, this is typically `"0"`. |
|
||||
| frozen | Boolean | `true` to enable Individual Freeze on this trust line. `false` to disable Individual Freeze. |
|
||||
|
||||
The rest of the [transaction flow](reference-rippleapi.html#transaction-flow) is the same as any other transaction.
|
||||
|
||||
Example JavaScript (ECMAScript 6) code to enable Individual Freeze on a trust line:
|
||||
|
||||
```js
|
||||
{% include 'code_samples/freeze/set-individual-freeze.js' %}
|
||||
```
|
||||
|
||||
|
||||
## Enabling or Disabling Global Freeze ##
|
||||
|
||||
### Using `rippled` ###
|
||||
|
||||
To enable Global Freeze on an account, send an `AccountSet` transaction with the [asfGlobalFreeze flag value](reference-transaction-format.html#accountset-flags) in the `SetFlag` field. To disable Global Freeze, put the asfGlobalFreeze flag value in the `ClearFlag` field instead.
|
||||
|
||||
Example of submitting an AccountSet transaction to enable Global Freeze using the [WebSocket API](reference-rippled.html#websocket-api):
|
||||
|
||||
```
|
||||
{
|
||||
"id": 12,
|
||||
"command": "submit",
|
||||
"tx_json": {
|
||||
"TransactionType": "AccountSet",
|
||||
"Account": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn",
|
||||
"Fee": "12000",
|
||||
"Flags": 0,
|
||||
"SetFlag": 7,
|
||||
"LastLedgerSequence": 18122753,
|
||||
"Sequence": 349
|
||||
},
|
||||
"secret": "s████████████████████████████",
|
||||
"offline": false,
|
||||
"fee_mult_max": 1000
|
||||
}
|
||||
```
|
||||
|
||||
(**Reminder**: Never transmit your account secret to an untrusted server or over an insecure channel.)
|
||||
|
||||
|
||||
### Using RippleAPI ###
|
||||
|
||||
To enable or disable Global Freeze on an account, prepare a **Settings** transaction using the [prepareSettings](reference-rippleapi.html#preparesettings) method. The `settings` parameter should be an object set as follows:
|
||||
|
||||
| Field | Value | Description |
|
||||
|--------------|--------|-------------|
|
||||
| globalFreeze | Boolean | `true` to enable a Global Freeze on this account. `false` to disable Global Freeze. |
|
||||
|
||||
The rest of the [transaction flow](reference-rippleapi.html#transaction-flow) is the same as any other transaction.
|
||||
|
||||
Example JavaScript (ECMAScript 6) code to enable Global Freeze on an account:
|
||||
|
||||
```js
|
||||
{% include 'code_samples/freeze/set-global-freeze.js' %}
|
||||
```
|
||||
|
||||
|
||||
|
||||
## Enabling No Freeze ##
|
||||
|
||||
### Using `rippled` ###
|
||||
|
||||
To enable No Freeze on an account, send an `AccountSet` transaction with the [asfNoFreeze flag value](reference-transaction-format.html#accountset-flags) in the `SetFlag` field. You must sign this transaction using the master key. Once enabled, you cannot disable No Freeze.
|
||||
|
||||
Example of submitting an AccountSet transaction to enable No Freeze using the [WebSocket API](reference-rippled.html#websocket-api):
|
||||
|
||||
WebSocket request:
|
||||
|
||||
```
|
||||
{
|
||||
"id": 12,
|
||||
"command": "submit",
|
||||
"tx_json": {
|
||||
"TransactionType": "AccountSet",
|
||||
"Account": "raKEEVSGnKSD9Zyvxu4z6Pqpm4ABH8FS6n",
|
||||
"Fee": "12000",
|
||||
"Flags": 0,
|
||||
"SetFlag": 6,
|
||||
"LastLedgerSequence": 18124917,
|
||||
"Sequence": 4
|
||||
},
|
||||
"secret": "s████████████████████████████",
|
||||
"offline": false,
|
||||
"fee_mult_max": 1000
|
||||
}
|
||||
```
|
||||
|
||||
(**Reminder**: Never transmit your account secret to an untrusted server or over an insecure channel.)
|
||||
|
||||
### Using RippleAPI ###
|
||||
|
||||
To enable No Freeze on an account, prepare a **Settings** transaction using the [prepareSettings](reference-rippleapi.html#preparesettings) method. Once enabled, you cannot disable No Freeze. The `settings` parameter should be an object set as follows:
|
||||
|
||||
| Field | Value | Description |
|
||||
|----------|---------|-------------|
|
||||
| noFreeze | Boolean | `true` |
|
||||
|
||||
You must [sign](reference-rippleapi.html#sign) this transaction using the master key. The rest of the [transaction flow](reference-rippleapi.html#transaction-flow) is the same as any other transaction.
|
||||
|
||||
Example JavaScript (ECMAScript 6) code to enable No Freeze on an account:
|
||||
|
||||
```js
|
||||
{% include 'code_samples/freeze/set-no-freeze.js' %}
|
||||
```
|
||||
|
||||
|
||||
## Checking for Individual Freeze ##
|
||||
|
||||
### Using `rippled` ###
|
||||
|
||||
To see if a trust line has an Individual Freeze enabled, use the [`account_lines` method](reference-rippled.html#account-lines) with the following parameters:
|
||||
|
||||
| Field | Value | Description |
|
||||
|----------|---------|-------------|
|
||||
| account | String | The Ripple address of the issuing account |
|
||||
| peer | String | The Ripple address of the counterparty account |
|
||||
| ledger\_index | String | Use `validated` to get the most recently validated information. |
|
||||
|
||||
The response contains an array of trust lines, for each currency in which the issuing account and the counterparty are linked. Look for the following fields in each trust line object:
|
||||
|
||||
| Field | Value | Description |
|
||||
|--------------|---------|-------------|
|
||||
| freeze | Boolean | (May be omitted) `true` if the issuing account has frozen this trust line. If omitted, that is the same as `false`. |
|
||||
| freeze\_peer | Boolean | (May be omitted) `true` if the counterparty has frozen this trust line. If omitted, that is the same as `false`. |
|
||||
|
||||
Example WebSocket request to check for individual freeze:
|
||||
|
||||
```
|
||||
{
|
||||
"id": 15,
|
||||
"command": "account_lines",
|
||||
"account": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn",
|
||||
"ledger": "validated",
|
||||
"peer": "rsA2LpzuawewSBQXkiju3YQTMzW13pAAdW"
|
||||
}
|
||||
```
|
||||
|
||||
Example WebSocket response:
|
||||
|
||||
```
|
||||
{
|
||||
"id": 15,
|
||||
"status": "success",
|
||||
"type": "response",
|
||||
"result": {
|
||||
"account": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn",
|
||||
"lines": [
|
||||
{
|
||||
"account": "rsA2LpzuawewSBQXkiju3YQTMzW13pAAdW",
|
||||
"balance": "10",
|
||||
"currency": "USD",
|
||||
"freeze": true,
|
||||
"limit": "110",
|
||||
"limit_peer": "0",
|
||||
"peer_authorized": true,
|
||||
"quality_in": 0,
|
||||
"quality_out": 0
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
The field `"freeze": true` indicates that rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn has enabled Individual Freeze on the USD trust line to rsA2LpzuawewSBQXkiju3YQTMzW13pAAdW. The lack of a field `"freeze_peer": true` indicates that the counterparty has _not_ frozen the trust line.
|
||||
|
||||
|
||||
### Using RippleAPI ###
|
||||
|
||||
To see if a trust line has an Individual Freeze enabled, use the [`getTrustlines` method](reference-rippleapi.html#gettrustlines) with the following parameters:
|
||||
|
||||
| Field | Value | Description |
|
||||
|---------------|---------|-------------|
|
||||
| address | String | The Ripple address of the issuing account |
|
||||
| options.counterparty | String | The Ripple address of the counterparty account |
|
||||
|
||||
The response contains an array of trust lines, for each currency in which the issuing account and the counterparty are linked. Look for the following fields in each trust line object:
|
||||
|
||||
| Field | Value | Description |
|
||||
|----------------------|---------|-------------|
|
||||
| specification.frozen | Boolean | (May be omitted) `true` if the issuing account has frozen the trust line. |
|
||||
| counterparty.frozen | Boolean | (May be omitted) `true` if the counterparty has frozen the trust line. |
|
||||
|
||||
Example JavaScript (ECMAScript 6) code to check whether a trust line is frozen:
|
||||
|
||||
```js
|
||||
{% include 'code_samples/freeze/check-individual-freeze.js' %}
|
||||
```
|
||||
|
||||
|
||||
## Checking for Global Freeze and No Freeze ##
|
||||
|
||||
### Using `rippled` ###
|
||||
|
||||
To see if an account has Global Freeze and/or No Freeze enabled, use the [`account_info` method](reference-rippled.html#account-lines) with the following parameters:
|
||||
|
||||
| Field | Value | Description |
|
||||
|----------|---------|-------------|
|
||||
| account | String | The Ripple address of the issuing account |
|
||||
| ledger\_index | String | Use `validated` to get the most recently validated information. |
|
||||
|
||||
Check the value of the `account_data.Flags` field of the response using the [bitwise-AND](https://en.wikipedia.org/wiki/Bitwise_operation#AND) operator:
|
||||
|
||||
* If `Flags` AND `0x00400000` ([lsfGlobalFreeze](reference-ledger-format.html#accountroot-flags)) is _nonzero_: Global Freeze is enabled.
|
||||
* If `Flags` AND `0x00200000` ([lsfNoFreeze](reference-ledger-format.html#accountroot-flags)) is _nonzero_: No Freeze is enabled.
|
||||
|
||||
Example WebSocket request:
|
||||
|
||||
```
|
||||
{
|
||||
"id": 1,
|
||||
"command": "account_info",
|
||||
"account": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn",
|
||||
"ledger_index": "validated"
|
||||
}
|
||||
```
|
||||
|
||||
WebSocket response:
|
||||
|
||||
```
|
||||
{
|
||||
"id": 4,
|
||||
"status": "success",
|
||||
"type": "response",
|
||||
"result": {
|
||||
"account_data": {
|
||||
"Account": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn",
|
||||
"AccountTxnID": "41320138CA9837B34E82B3B3D6FB1E581D5DE2F0A67B3D62B5B8A8C9C8D970D0",
|
||||
"Balance": "100258663",
|
||||
"Domain": "6D64756F31332E636F6D",
|
||||
"EmailHash": "98B4375E1D753E5B91627516F6D70977",
|
||||
"Flags": 12582912,
|
||||
"LedgerEntryType": "AccountRoot",
|
||||
"MessageKey": "0000000000000000000000070000000300",
|
||||
"OwnerCount": 4,
|
||||
"PreviousTxnID": "41320138CA9837B34E82B3B3D6FB1E581D5DE2F0A67B3D62B5B8A8C9C8D970D0",
|
||||
"PreviousTxnLgrSeq": 18123095,
|
||||
"Sequence": 352,
|
||||
"TransferRate": 1004999999,
|
||||
"index": "13F1A95D7AAB7108D5CE7EEAF504B2894B8C674E6D68499076441C4837282BF8",
|
||||
"urlgravatar": "http://www.gravatar.com/avatar/98b4375e1d753e5b91627516f6d70977"
|
||||
},
|
||||
"ledger_hash": "A777B05A293A73E511669B8A4A45A298FF89AD9C9394430023008DB4A6E7FDD5",
|
||||
"ledger_index": 18123249,
|
||||
"validated": true
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
In the above example, the `Flags` value is 12582912. This indicates that has the following flags enabled: lsfGlobalFreeze, lsfDefaultRipple, as demonstrated by the following JavaScript code:
|
||||
|
||||
```js
|
||||
var lsfGlobalFreeze = 0x00400000;
|
||||
var lsfNoFreeze = 0x00200000;
|
||||
|
||||
var currentFlags = 12582912;
|
||||
|
||||
console.log(currentFlags & lsfGlobalFreeze); //4194304
|
||||
//therefore, Global Freeze is enabled
|
||||
|
||||
console.log(currentFlags & lsfNoFreeze); //0
|
||||
//therefore, No Freeze is not enabled
|
||||
```
|
||||
|
||||
### Using RippleAPI ###
|
||||
|
||||
To see if an account has Global Freeze and/or No Freeze enabled, use the [`getSettings` method](reference-rippleapi.html#getsettings) with the following parameters:
|
||||
|
||||
| Field | Value | Description |
|
||||
|---------------|---------|-------------|
|
||||
| address | String | The Ripple address of the issuing account |
|
||||
|
||||
Look for the following values in the response object:
|
||||
|
||||
| Field | Value | Description |
|
||||
|---------------|---------|-------------|
|
||||
| noFreeze | Boolean | (May be omitted) `true` if No Freeze is enabled. |
|
||||
| globalFreeze | Boolean | (May be omitted) `true` if Global Freeze is enabled. |
|
||||
|
||||
Example JavaScript (ECMAScript 6) code to check whether an account has Global Freeze or No Freeze enabled:
|
||||
|
||||
```js
|
||||
{% include 'code_samples/freeze/check-global-freeze-no-freeze.js' %}
|
||||
```
|
||||
|
||||
# See Also #
|
||||
|
||||
* [Gateway Bulletin GB-2014-02 New Feature: Balance Freeze](https://ripple.com/files/GB-2014-02.pdf)
|
||||
* [Freeze Code Samples](https://github.com/ripple/ripple-dev-portal/tree/gh-pages/content/code_samples/freeze)
|
||||
53
content/concept-issuing-and-operational-addresses.md
Normal file
@@ -0,0 +1,53 @@
|
||||
# Issuing and Operational Addresses #
|
||||
|
||||
All non-XRP currency balances (issuances) in the Ripple Consensus Ledger (RCL) are tied to accounting relationships between two Ripple addresses. To control an address in the RCL, you only need the secret key mathematically connected to that address. Since no party can unilaterally prevent transactions or correct the ledger, financial institutions typically use multiple Ripple ledger addresses to minimize the risk associated with a compromised secret key. Ripple strongly recommends the following separation of roles:
|
||||
|
||||
* One **issuing address**, also known as a "cold wallet." This address is the hub of the financial institution's accounting relationships in the ledger, but sends as few transactions as possible.
|
||||
* One or more **operational addresses**, also known as "hot wallets." Automated, internet-connected systems use the secret keys to these addresses to conduct day-to-day business like transfers to customers and partners.
|
||||
* Optional **standby addresses**, also known as "warm wallets." Trusted human operators use these addresses to transfer money to the operational addresses.
|
||||
|
||||
## Funds Lifecycle ##
|
||||
|
||||
[](img/funds_flow_diagram.png)
|
||||
|
||||
Funds in the Ripple Consensus Ledger tend to flow in a cycle. When the issuing address sends payments, it creates balances in the accounting relationships in the Ripple Consensus Ledger. Within the RCL, users can exchange balances across different accounting relationships, so we use the term _issuances_ to describe any non-XRP balance. Issuances have positive value from the perspective of the customers, partners, operational addresses, and standby addresses. The same issuances are negative balances from the perspective of the issuing address, since they represent obligations. When the issuing address receives a payment, this reduces its obligations, effectively "destroying" the issuances that were sent.
|
||||
|
||||
The issuing address sends issuances to a standby address, or directly to an operational address. The standby addresses send those issuances to operational addresses. Operational addresses send payments to liquidity providers or other customers and partners. Because all issuances are tied to accounting relationships with the issuing address, payments and exchanges of issuances "ripple through" the issuing address. The payment debits the sender's balance in its accounting relationship with the issuing address and credits the recipient's balance in the recipient's accounting relationship with the issuing address. The Ripple Consensus Ledger also supports more complicated [paths](concept-paths.html) that connect multiple issuers through order books and [liquidity providers who allow their funds to ripple](https://ripple.com/knowledge_center/understanding-the-noripple-flag/).
|
||||
|
||||
## Issuing Address ##
|
||||
|
||||
The issuing address is like a vault. Partners, customers, and operational addresses create accounting relationships (trust lines) to the issuing address, but this address sends as few transactions as possible. Periodically, a human operator creates and signs a transaction from the issuing address in order to refill the balances of a standby or operational address. Ideally, the secret key used to sign these transactions should never be accessible from any internet-connected computer.
|
||||
|
||||
Unlike a vault, the issuing address can receive payments directly from customers and partners. Since all transactions in the Ripple Consensus Ledger are public, automated systems can monitor for payments to the issuing address without needing a secret key.
|
||||
|
||||
### Issuing Address Compromise ###
|
||||
|
||||
If a malicious actor learns the secret key behind a institution's issuing address, that actor can create new issuances without limit and trade them in the decentralized exchange. This would make it difficult for the financial institution to distinguish legitimately-obtained issuances and redeem them fairly. If a financial institution loses control of its issuing address, the institution must create a new issuing address, and all users who have accounting relationships with the old issuing address must create new accounting relationships with the new address.
|
||||
|
||||
### Multiple Issuing Addresses ###
|
||||
|
||||
A financial institution can issue more than one currency in the Ripple Consensus Ledger from a single issuing address. However, there are some settings that apply equally to all currencies issued from an address, including the percentage for [transfer fees](concept-transfer-fees.html) and the [global freeze](concept-freeze.html) status. If the financial institution wants the flexibility to manage settings differently for each currency, the institution must use a different issuing address for each currency.
|
||||
|
||||
|
||||
## Operational Addresses ##
|
||||
|
||||
An operational address is like a cash register. It makes payments on behalf of the institution by transferring issuances to customers and partners. In order to sign transactions automatically, the secret key for an operational address must be stored on a server that is connected to the internet. (The secret key can be stored encrypted, but the server must decrypt it in order to sign transactions.) Customers and partners do not, and should not, create accounting relationships with an operational address.
|
||||
|
||||
Each operational address has a limited balance of issuances. When the balance of an operational address gets low, the financial institution refills it by sending a payment from the issuing address or a standby address.
|
||||
|
||||
### Operational Address Compromise ###
|
||||
|
||||
If a malicious actor learns the secret key behind an operational address, the financial institution can only lose as much currency as that operational address holds. The institution can switch to a new operational address with no action from customers and partners.
|
||||
|
||||
|
||||
## Standby Addresses ##
|
||||
|
||||
Another optional step that an institution can take to balance risk and convenience is to use "standby addresses" as an intermediate step between the issuing address and operational addresses. The institution can fund additional Ripple addresses as standby addresses, whose keys are not stored online, but are entrusted to different trusted users.
|
||||
|
||||
When an operational address is running low on funds, a trusted user can use a standby address to refill the operational address's balance. When a standby addresses run low on funds, the institution can use the issuing address to send more currency to a standby address in a single transaction, and the standby addresses can distribute that currency among themselves if necessary. This improves security of the issuing address, allowing it to make fewer total transactions, without leaving too much money in the control of a single automated system.
|
||||
|
||||
As with operational addresses, a standby address must have an accounting relationship with the issuing address, and not with customers or partners. All precautions that apply to operational addresses also apply to standby addresses.
|
||||
|
||||
### Standby Address Compromise ###
|
||||
|
||||
If a standby address is compromised, the results are similar to an operational address being compromised. A malicious actor can steal any balances possessed by the standby address, and the financial institution can change to a new standby address with no action from customers and partners.
|
||||
88
content/concept-paths.md
Normal file
@@ -0,0 +1,88 @@
|
||||
# Paths #
|
||||
|
||||
In the Ripple Consensus Ledger, paths define a way for payments to flow through intermediary steps on their way from sender to receiver. Paths enable cross-currency payments by connecting sender and receiver via market makers. Paths also enable complex settlement of offsetting debts.
|
||||
|
||||
A single Payment transaction in the Ripple Consensus Ledger can use multiple paths, combining liquidity from different sources to deliver the desired amount. Thus, a transaction includes a _path set_, which is a collection of possible paths to take. The paths in a path set must start and end with the same currency.
|
||||
|
||||
Since XRP can be sent directly to any address, an XRP-to-XRP transaction does not use any paths.
|
||||
|
||||
## Path Steps ##
|
||||
|
||||
A path is made of steps that connect the sender to the receiver of the payment. Every step is either:
|
||||
|
||||
* Rippling through another account in the same currency
|
||||
* Exchanging currency at an order book
|
||||
|
||||
Rippling through another account is the process of moving debt around. In the typical case, this involves reducing a gateway's obligation to one party and increasing the gateway's obligation to another party. Rippling can occur between any accounts that are connected by trust lines. See [Understanding the NoRipple Flag](https://ripple.com/knowledge_center/understanding-the-noripple-flag/) for more examples of rippling.
|
||||
|
||||
In the case of a currency exchange step, the path step specifies which currency to change to, but does not record the state of the orders in the order book. Since the order of transactions is not finalized until a ledger is validated, it is impossible to determine for certain which offers a transaction will execute, until after the transaction has been validated. Consequently, you cannot know in advance which offers a transaction will take: only which order books the transaction will use. (You can make an educated guess, since each transaction takes the best available offers at the time it executes in the final ledger.)
|
||||
|
||||
In both types of steps, each intermediate account gains and loses approximately equal value: either a balance ripples from a trust line to another trust line in the same currency, or they exchange currencies according to a previously-placed order. In some cases, the amounts gained and lost may not be exactly equivalent, due to [transfer fees](https://ripple.com/knowledge_center/transfer-fees/), trust line quality, or rounding.
|
||||
|
||||
[](img/paths-examples.png)
|
||||
|
||||
|
||||
|
||||
# Technical Details #
|
||||
|
||||
## Pathfinding ##
|
||||
|
||||
The `rippled` API has two methods that can be used for pathfinding. The [`ripple_path_find` command](reference-rippled.html#ripple-path-find) does a one-time lookup of possible path sets. The [`path_find` command](reference-rippled.html#path-find) (WebSocket only) expands on the initial search with follow-up responses whenever a ledger closes or the server finds a better path.
|
||||
|
||||
You can have `rippled` automatically fill in paths when you sign it, by including the `build_path` field in a request to the [`sign` command](reference-rippled.html#sign) or [`submit` command (sign-and-submit mode)](reference-rippled.html#sign-and-submit-mode). However, we recommend pathfinding separately and confirming the results prior to signing, in order to avoid surprises. There are no guarantees on how expensive the paths the server finds will be at the time of submission. (Although `rippled` is designed to search for the cheapest paths possible, it may not always find them. Untrustworthy `rippled` instances could also be modified to change this behavior for profit.)
|
||||
|
||||
Finding paths is a very challenging problem that changes slightly every few seconds as new ledgers are validated, so `rippled` is not designed to find the absolute best path. Still, you can find several possible paths and estimate the cost of delivering a particular amount.
|
||||
|
||||
|
||||
## Implied Steps ##
|
||||
|
||||
By convention, several steps of a path are implied by the [fields of the Payment transaction](reference-transaction-format.html#payment): specifically, the `Account` (sender), `Destination` (receiver), `Amount` (currency and amount to be delivered) and `SendMax` (currency and amount to be sent, if specified). The implied steps are as follows:
|
||||
|
||||
* The first step of a path is always implied to be the sender of the transaction, as defined by the transaction's `Account` field.
|
||||
* If the transaction includes a `SendMax` field with an `issuer` that is not the sender of the transaction, that issuer is implied to be the second step of the path.
|
||||
* If `issuer` of the `SendMax` _is_ the sending account, then the path starts at the sending account, and may use any of that account's trust lines in the given currency. See [special values for SendMax and Amount](reference-transaction-format.html#special-issuer-values-for-sendmax-and-amount) for details.
|
||||
* If the `Amount` field of the transaction includes an `issuer` that is not the same as the `Destination` of the transaction, that issuer is implied to be the second-to-last step of the path.
|
||||
* Finally, last step of a path is always implied to be the receiver of a transaction, as defined by the transaction's `Destination` field.
|
||||
|
||||
|
||||
## Default Paths ##
|
||||
|
||||
In addition to any paths that are specified in the transaction, a transaction can also execute along the _default path_. The default path is the simplest possible way to connect the [implied steps](#implied-steps) of the transaction.
|
||||
|
||||
The default path could be any of the following:
|
||||
|
||||
* If the transaction is uses only one currency (regardless of issuer), then the default path assumes the payment will ripple through the accounts involved. This path will only work if there are trust lines connecting those accounts.
|
||||
* If `SendMax` is omitted, or the `issuer` of the `SendMax` is the sender, the default path needs a trust line from the sending `Account` to the `issuer` of the destination `Amount` in order to work.
|
||||
* If the `SendMax` and `Amount` have different `issuer` values, and neither are the sender or receiver, the default path is probably not useful because it would need to ripple across a trust line between the two issuers. Ripple, Inc. typically discourages issuers from trusting one another directly.
|
||||
* For cross-currency transactions, the default path uses the order book between the source currency (as specified in the `SendMax` field) and the destination currency (as specified in the `Amount` field).
|
||||
|
||||
The following diagram enumerates all possible default paths:
|
||||
[](img/paths-default_paths.png)
|
||||
|
||||
You can use the [`tfNoDirectRipple` flag](reference-transaction-format.html#payment-flags) to disable the default path. In this case, the transaction can only execute using the paths explicitly included in the transaction. Traders can use this option to take arbitrage opportunities.
|
||||
|
||||
|
||||
## Path Specifications ##
|
||||
|
||||
A path set is an array. Each member of the path set is another array that represents an individual _path_. Each member of a path is an object that specifies the step. A step has the following fields:
|
||||
|
||||
| Field | Value | Description |
|
||||
|-------|-------|-------------|
|
||||
| account | String - Address | (Optional) If present, this path step represents rippling through the specified account. |
|
||||
| currency | String - currency code | (Optional) If present, this path step represents changing currencies through an order book. The currency specified indicates the new currency. |
|
||||
| issuer | String - Address | (Optional) If the path step represents changing currencies through an order book, this field indicates the issuer of the new currency. This field is not present when changing to XRP. |
|
||||
| type | Integer | **DEPRECATED** (Optional) An indicator of which other fields are present. |
|
||||
| type_hex | String | **DEPRECATED**: (Optional) A hexadecimal representation of the `type` field. |
|
||||
|
||||
The `type` field, used for the binary serialization of a path set, is actually constructed through bitwise operations on a single integer. The bits are defined as follows:
|
||||
|
||||
| Value (Hex) | Value (Decimal) | Description |
|
||||
|-------------|-----------------|-------------|
|
||||
| 0x01 | 1 | A change of account (rippling): the `account` field is present. |
|
||||
| 0x10 | 16 | A change of currency: the `currency` field is present. |
|
||||
| 0x20 | 32 | A change of issuer: the `issuer` field is present. |
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
43
content/concept-reserves.md
Normal file
@@ -0,0 +1,43 @@
|
||||
# Reserves #
|
||||
|
||||
The Ripple Consensus Ledger applies _reserve requirements_, in XRP, to protect the shared global ledger from growing excessively large as the result of spam or malicious usage. The goal is to constrain the growth of the ledger to match [Moore's Law](https://en.wikipedia.org/wiki/Moore's_law) so that a current commodity-level machine can always fit the current ledger in RAM and the full ledger history on disk.
|
||||
|
||||
Each account in the shared global ledger must hold a minimum of XRP in order to submit transactions, and it cannot send this XRP to other accounts. You cannot create a new account unless you send enough XRP to meet the minimum reserve requirement.
|
||||
|
||||
The current minimum reserve requirement is **20 XRP**. (This is the cost of an account that owns no additional objects in the ledger.)
|
||||
|
||||
|
||||
## Base Reserve and Owner Reserve ##
|
||||
|
||||
The reserve requirement is divided into two parts:
|
||||
|
||||
* The **Base Reserve** is a minimum amount of XRP that is required for every account in the ledger. Currently, this is 20 XRP (`20000000` drops).
|
||||
* The **Owner Reserve** is an additional requirement that scales with the number of objects that the account owns in the ledger. Currently, this is 5 XRP (`5000000` drops) per item.
|
||||
|
||||
|
||||
### Owner Reserves ###
|
||||
|
||||
Many objects in the ledger are owned by a particular account, and therefore count toward the reserve requirement of that account. When objects are removed from the ledger, they no longer count against their owner's reserve requirement.
|
||||
|
||||
* [Offers](reference-ledger-format.html#offer) are owned by the account that placed them. An Offer can be automatically removed from the ledger if it is fully consumed or if it is found unfunded during transaction processing. Alternatively, the owner can cancel an offer by sending an [OfferCancel transaction](reference-transaction-format.html#offercancel), or by sending an [OfferCreate transaction](reference-transaction-format.html#offercreate) that contains an `OfferSequence` parameter.
|
||||
* [Trust lines](reference-ledger-format.html#ripplestate) are shared between two accounts. The owner reserve can apply to one or both of the accounts, depending on whether the fields that account controls are in their default state. See [Contributing to the Owner Reserve](reference-ledger-format.html#contributing-to-the-owner-reserve) for details.
|
||||
* A single [SignerList](reference-ledger-format.html#signerlist) counts as 3 to 10 objects for purposes of the owner reserve, depending on how many members it has. See also: [SignerLists and Reserves](reference-ledger-format.html#signerlists-and-reserves).
|
||||
* [Owner directories](reference-ledger-format.html#directorynode) list all the ledger nodes that contribute to an account's owner reserve. However, the owner directory itself does not count towards the reserve.
|
||||
|
||||
#### Owner Reserve Edge Cases ####
|
||||
|
||||
The Ripple Consensus Ledger considers an [OfferCreate transaction](reference-transaction-format.html#offercreate) to be an explicit statement of willingness to hold an asset. Consuming the offer automatically creates a trust line (with limit 0, and a balance above that limit) for the `taker_pays` currency if such a trust line does not exist. However, if the offer's owner does not possess enough XRP to meet the additional reserve requirement of the new trust line, the offer is considered unfunded. See also: [Lifecycle of an Offer](reference-transaction-format.html#lifecycle-of-an-offer).
|
||||
|
||||
|
||||
|
||||
## Going Below the Reserve Requirement ##
|
||||
|
||||
During transaction processing, a transaction can only be successful if the sending account possesses at least the reserve requirement in XRP. In the process, the [transaction cost](concept-transaction-cost.html) destroys some of the sending account's XRP balance. This can cause an account to go below the reserve requirement.
|
||||
|
||||
When an account has less XRP than its current reserve requirement, it cannot send new transactions. Even so, it continues to exist in the ledger, as all accounts do. Unless the reserve requirements decrease, the only way for the account to become able to send transactions again is for it to receive enough XRP that it meets the reserve requirement.
|
||||
|
||||
**Exception:** When an account is below the reserve requirement, it can send new [OfferCreate transactions](reference-transaction-format.html#offercreate) to acquire more XRP, or other currencies on its existing trust lines. These transactions cannot create new [trust lines](reference-ledger-format.html#ripplestate), or [Offer nodes in the ledger](reference-ledger-format.html#offer), so they can only execute trades that consume Offers that are already in the order books.
|
||||
|
||||
## Changing the Reserve Requirements ##
|
||||
|
||||
The Ripple Consensus Ledger has a mechanism for changing the reserve requirements in order to account for long-term changes in the value of XRP. Any changes have to be approved by the consensus process. See [Fee Voting](concept-fee-voting.html) for more information.
|
||||
103
content/concept-stand-alone-mode.md
Normal file
@@ -0,0 +1,103 @@
|
||||
Stand-Alone Mode
|
||||
===============================================================================
|
||||
|
||||
You can run `rippled` in stand-alone mode without a consensus of trusted servers. In stand-alone mode, `rippled` does not communicate with any other servers in the Ripple peer-to-peer network, but you can do most of the same actions on your local server only. Stand-alone provides a method for testing `rippled` behavior without being tied to the live network. For example, you can [test the effects of Amendments](concept-amendments.html#testing-amendments) before those Amendments have gone into effect across the decentralized network.
|
||||
|
||||
When you run `rippled` in stand-alone mode, you have to tell it what ledger version to start from:
|
||||
|
||||
* Create a [new genesis ledger](#new-genesis-ledger) from scratch.
|
||||
* [Load an existing ledger version](#load-saved-ledger) from disk.
|
||||
|
||||
**Caution:** In stand-alone mode, you must [manually advance the ledger](#advancing-ledgers-in-stand-alone-mode).
|
||||
|
||||
New Genesis Ledger
|
||||
-------------------------------------------------------------------------------
|
||||
In stand-alone mode, you can have `rippled` create a new genesis ledger. This provides a known state, with none of the ledger history from the production Ripple Consensus Ledger. (This is very useful for unit tests, among other things.)
|
||||
|
||||
* To start `rippled` in stand-alone mode with a new genesis ledger, use the `-a` and `--start` options:
|
||||
|
||||
```
|
||||
rippled -a --start --conf=/path/to/rippled.cfg
|
||||
```
|
||||
|
||||
In a genesis ledger, the [genesis address](reference-rippled.html#special-addresses) holds all 100 billion XRP. The keys of the genesis address are [hardcoded](https://github.com/ripple/rippled/blob/94ed5b3a53077d815ad0dd65d490c8d37a147361/src/ripple/app/ledger/Ledger.cpp#L184) as follows:
|
||||
|
||||
**Address:** `rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh`
|
||||
|
||||
**Secret:** `snoPBrXtMeMyMHUVTgbuqAfg1SUTb` ("masterpassphrase")
|
||||
|
||||
**Caution:** If you create a new genesis ledger, the hard-coded default [Reserve](concept-reserves.html) is **200 XRP** minimum for funding a new address, with an increment of **50 XRP** per object in the ledger. These values are higher than the current reserve requirements of the production network. (See also: [Fee Voting](concept-fee-voting.html))
|
||||
|
||||
|
||||
|
||||
Load Saved Ledger
|
||||
-------------------------------------------------------------------------------
|
||||
You can start with a ledger version that was saved to disk if your `rippled` server was previously synced with the Ripple peer-to-peer network (either the production network or the [Test Net](tutorial-rippled-setup.html#parallel-networks)).
|
||||
|
||||
### 1. Start `rippled` normally. ###
|
||||
|
||||
To load an existing ledger, you must first retrieve that ledger from the network. Start `rippled` in networked mode as normal:
|
||||
|
||||
```
|
||||
rippled --conf=/path/to/rippled.cfg
|
||||
```
|
||||
|
||||
### 2. Wait until `rippled` is synced. ###
|
||||
|
||||
Use the [`server_info` command](reference-rippled.html#server-info) to check the state of your server relative to the network. Your server is synced when the `server_state` value shows any of the following values:
|
||||
|
||||
* `full`
|
||||
* `proposing`
|
||||
* `validating`.
|
||||
|
||||
### 3. (Optional) Retrieve specific ledger versions. ###
|
||||
|
||||
If you only want the most recent ledger, you can skip this step.
|
||||
|
||||
If you want to load a specific historical ledger version, use the [`ledger_request` command](reference-rippled.html#ledger-request) to make `rippled` fetch it. If `rippled` does not already have the ledger version, you may have to run the `ledger_request` command multiple times until it has finished retrieving the ledger.
|
||||
|
||||
If you want to replay a specific historical ledger version, you must fetch both the ledger version to replay and the ledger version immediately before it.
|
||||
|
||||
### 4. Shut down `rippled`. ###
|
||||
|
||||
Use the [`stop` command](reference-rippled.html#stop):
|
||||
|
||||
```
|
||||
rippled stop --conf=/path/to/rippled.cfg
|
||||
```
|
||||
|
||||
### 5. Start `rippled` in stand-alone mode. ###
|
||||
|
||||
To load the most recent ledger version, you can use the `-a` and `--load` options when starting the server:
|
||||
|
||||
```
|
||||
rippled -a --load --conf=/path/to/rippled.cfg
|
||||
```
|
||||
|
||||
To instead load a specific historical ledger, use the `--load` parameter along with the `--ledger` parameter, providing the ledger index or identifying hash of the ledger version to load:
|
||||
|
||||
```
|
||||
rippled -a --load --ledger 19860944 --conf=/path/to/rippled.cfg
|
||||
```
|
||||
|
||||
### 6. Manually advance the ledger. ###
|
||||
|
||||
When you load a ledger with `--ledger` in stand-alone mode, it goes to the current open ledger, so you must [manually advance the ledger](#advancing-ledgers-in-stand-alone-mode):
|
||||
|
||||
```
|
||||
rippled ledger_accept --conf=/path/to/rippled.cfg
|
||||
```
|
||||
|
||||
|
||||
Advancing Ledgers in Stand-Alone Mode
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
In stand-alone mode, `rippled` does not communicate to other members of the peer-to-peer network or participate in a consensus process. Instead, you must manually advance the ledger index using the [`ledger_accept` command](reference-rippled.html#ledger-accept):
|
||||
|
||||
```
|
||||
rippled ledger_accept --conf=/path/to/rippled.cfg
|
||||
```
|
||||
|
||||
In stand-alone mode, `rippled` makes no distinction between a "closed" ledger version and a "validated" ledger version. (For more information about the difference, see [The Ripple Ledger Consensus Process](https://ripple.com/knowledge_center/the-ripple-ledger-consensus-process/).)
|
||||
|
||||
Whenever `rippled` closes a ledger, it reorders the transactions according to a deterministic but hard-to-game algorithm. (This is an important part of consensus, since transactions may arrive at different parts of the network in different order.) When using `rippled` in stand-alone mode, you should manually advance the ledger before submitting a transaction that depends on the result of a previous transaction. Otherwise, the second transaction might be executed before the first transaction when you manually advance the ledger. **Note:** You can safely submit multiple transactions from a single address to a single ledger, because `rippled` sorts transactions from the same address in ascending order by `Sequence` number.
|
||||
144
content/concept-transaction-cost.md
Normal file
@@ -0,0 +1,144 @@
|
||||
# Transaction Cost #
|
||||
|
||||
In order to protect the Ripple Consensus Ledger from being disrupted by spam and denial-of-service attacks, each transaction must destroy a small amount of [XRP](https://ripple.com/knowledge_center/math-based-currency-2/). This _transaction cost_ is designed to increase along with the load on the network, making it very expensive to deliberately or inadvertently overload the network.
|
||||
|
||||
Every transaction must [specify how much XRP it will destroy](#specifying-the-transaction-cost) in order to pay the transaction cost.
|
||||
|
||||
|
||||
## Current Transaction Cost ##
|
||||
|
||||
The current transaction cost required by the network for a standard transaction is typically **0.01 XRP** (10,000 drops), although it sometimes increases due to network load.
|
||||
|
||||
You can also [query `rippled` for the current transaction cost](#querying-the-transaction-cost).
|
||||
|
||||
### Special Transaction Costs ###
|
||||
|
||||
Some transactions have different transaction costs:
|
||||
|
||||
| Transaction | Cost Before Load Scaling |
|
||||
|-----------------------|--------------------------|
|
||||
| Reference Transaction (Standard cost of most transactions) | 10 drops |
|
||||
| [Key Reset Transaction](#key-reset-transaction) | 0 |
|
||||
| [Multi-signed transaction](reference-transaction-format.html#multi-signing) | 10 drops × (1 + Number of Signatures Provided) |
|
||||
|
||||
|
||||
## Beneficiaries of the Transaction Cost ##
|
||||
|
||||
The transaction cost is not paid to any party: the XRP is irrevocably destroyed. Since no new XRP can ever be created, this makes XRP more scarce, and consequently benefits all holders of XRP by making XRP more valuable.
|
||||
|
||||
|
||||
## Load Cost and Open Ledger Cost ##
|
||||
|
||||
When the [FeeEscalation amendment](concept-amendments.html#feeescalation) is enabled, there are two thresholds for the transaction cost:
|
||||
|
||||
* If the transaction cost does not meet a `rippled` server's [load-based transaction cost threshold](#local-load-cost), the server ignores the transaction completely. (This logic is essentially unchanged with or without the amendment.)
|
||||
* If the transaction cost does not meet a `rippled` server's [open ledger cost threshold](#open-ledger-cost), the server queues the transaction for a later ledger.
|
||||
|
||||
This divides transactions into roughly three categories:
|
||||
|
||||
* Transactions that specify a transaction cost so low that they get rejected by the load-based transaction cost.
|
||||
* Transactions that specify a transaction cost high enough to be included in the current open ledger.
|
||||
* Transactions in between, which get [queued for a later ledger version](#queued-transactions).
|
||||
|
||||
|
||||
## Local Load Cost ##
|
||||
|
||||
Each `rippled` server maintains a cost threshold based on its current load. If you submit a transaction with a `Fee` value that is lower than current load-based transaction cost of the `rippled` server, that server neither applies nor relays the transaction. (**Note:** If you submit a transaction through an [admin connection](reference-rippled.html#connecting-to-rippled), the server applies and relays the transaction as long as the transaction cost meets the overall minimum.) A transaction is very unlikely to survive [the consensus process](https://ripple.com/knowledge_center/the-ripple-ledger-consensus-process/) unless its `Fee` value meets the requirements of a majority of servers.
|
||||
|
||||
## Open Ledger Cost ##
|
||||
|
||||
A `rippled` server with the [FeeEscalation amendment](concept-amendments.html#feeescalation) enabled has a second mechanism for enforcing the transaction cost, called the _open ledger cost_. The open ledger cost starts out equal to the minimum transaction cost, but increases exponentially when an in-progress ledger has more transactions than the previous one. Only transactions which pay more than the open ledger cost can be included in the current open ledger.
|
||||
Transactions that do not meet the open ledger cost are [queued for a following ledger](#queued-transactions) instead.
|
||||
|
||||
The open ledger cost requirement is proportional to the normal cost of the transaction, not the absolute transaction cost. Transaction types that have a higher-than-normal requirement, such as [multi-signed transactions](reference-transaction-format.html#multi-signing) must pay more to meet the open ledger cost than transactions which have minimum transaction cost requirements.
|
||||
|
||||
See also: [Fee Escalation explanation in `rippled` repository](https://github.com/ripple/rippled/blob/release/src/ripple/app/misc/FeeEscalation.md).
|
||||
|
||||
### Queued Transactions ###
|
||||
|
||||
(Requires the [FeeEscalation amendment](concept-amendments.html#feeescalation))
|
||||
|
||||
When `rippled` receives a transaction that meet the server's local load cost but not the open ledger cost, the server checks the transaction to see if it is "likely to be included" in a later ledger. If so, the server adds the transaction to the transaction queue and relays the transaction to other members of the network. Otherwise, the server discards the transaction. The server tries minimize the amount of network load caused by transactions that would not pay a transaction cost, since [the transaction cost only applies when a transaction is included in a validated ledger](#transaction-costs-and-failed-transactions).
|
||||
|
||||
The `rippled` server uses a variety of heuristics to determine which transactions are "likely to be included in a ledger." Most importantly, those transactions must be properly-formed and [authorized](reference-transaction-format.html#authorizing-transactions) with valid signatures.
|
||||
|
||||
When the current open ledger closes and the server starts a new open ledger, the server starts taking transactions from the queue to include in the new open ledger. The transaction queue is sorted with the transactions that would pay the highest transaction cost first, proportional to the un-scaled cost of those transactions. Transactions that pay the same transaction cost are queued in the order the server receives them.
|
||||
|
||||
**Note:** As of `rippled` **version 0.31.0**, the transaction queue supports at most 1 transaction per sending address. This is expected to change in later versions.
|
||||
|
||||
**Caution:** The current implementation does not allow transactions with an `AccountTxnID` field in the transaction queue.
|
||||
|
||||
|
||||
|
||||
## Querying the Transaction Cost ##
|
||||
|
||||
The `rippled` APIs have two ways to query the local load-based transaction cost: the `server_info` command (intended for humans) and the `server_state` command (intended for machines).
|
||||
|
||||
If the [FeeEscalation amendment](concept-amendments.html#feeescalation) is enabled, you can use the [`fee` command](reference-rippled.html#fee) to check the open ledger cost.
|
||||
|
||||
### server_info ###
|
||||
|
||||
The [`server_info` command](reference-rippled.html#server-info) reports the unscaled minimum XRP cost, as of the previous ledger, as `validated_ledger.base_fee_xrp`, in the form of decimal XRP. The actual cost necessary to relay a transaction is scaled by multiplying that `base_fee_xrp` value by the `load_factor` parameter in the same response, which represents the server's current load level. In other words:
|
||||
|
||||
**Current Transaction Cost in XRP = `base_fee_xrp` × `load_factor`**
|
||||
|
||||
|
||||
### server_state ###
|
||||
|
||||
The [`server_state` command](reference-rippled.html#server-state) returns a direct representation of `rippled`'s internal load calculations. In this case, the effective load rate is the ratio of the current `load_factor` to the `load_base`. The `validated_ledger.base_fee` parameter reports the minimum transaction cost in [drops of XRP](reference-rippled.html#specifying-currency-amounts). This design enables `rippled` to calculate the transaction cost using only integer math, while still allowing a reasonable amount of fine-tuning for server load. The actual calculation of the transaction cost is as follows:
|
||||
|
||||
**Current Transaction Cost in Drops = (`base_fee` × `load_factor`) ÷ `load_base`**
|
||||
|
||||
|
||||
|
||||
## Specifying the Transaction Cost ##
|
||||
|
||||
Every signed transaction must include the transaction cost in the [`Fee` field](reference-transaction-format.html#common-fields). Like all fields of a signed transaction, this field cannot be changed without invalidating the signature.
|
||||
|
||||
As a rule, the Ripple Consensus Ledger executes transactions _exactly_ as they are signed. (To do anything else would be difficult to coordinate across a decentralized consensus network, at the least.) As a consequence of this, every transaction destroys the exact amount of XRP specified by the `Fee` field, even if it is much more than the current minimum transaction cost for any part of the network. The transaction cost can even destroy XRP that would otherwise be set aside for an account's reserve requirement.
|
||||
|
||||
Before signing a transaction, we recommend [looking up the current load-based transaction cost](#querying-the-transaction-cost). If the transaction cost is currently high due to load scaling, you may want to wait for it to decrease. If you do not plan on submitting the transaction immediately, we recommend specifying a slightly higher transaction cost to account for future load-based fluctuations in the transaction cost.
|
||||
|
||||
|
||||
### Automatically Specifying the Transaction Cost ###
|
||||
|
||||
When you sign a transaction online, you can omit the `Fee` field. In this case, `rippled` or ripple-lib looks up an appropriate value based on the state of the peer-to-peer network, and includes it before signing the transaction. However, there are several drawbacks and limitations to automatically filling in the transaction cost in this manner:
|
||||
|
||||
* If the network's transaction cost goes up between signing and distributing the transaction, the transaction may not be confirmed.
|
||||
* In the worst case, the transaction may be stuck in a state of being neither definitively confirmed or rejected, unless it included a `LastLedgerSequence` parameter or until you cancel it with a new transaction that uses the same `Sequence` number. See [reliable transaction submission](tutorial-reliable-transaction-submission.html) for best practices.
|
||||
* You do not know in advance exactly what value you are signing for the `Fee` field.
|
||||
* If you are using `rippled`, you can also use the `fee_mult_max` and `fee_div_max` parameters of the [`sign` command](reference-rippled.html#sign) to set a limit to the load scaling you are willing to sign.
|
||||
* You cannot look up the current transaction cost from an offline machine.
|
||||
* You cannot automatically specify the transaction cost when [multi-signing](reference-transaction-format.html#multi-signing).
|
||||
|
||||
|
||||
|
||||
## Transaction Costs and Failed Transactions ##
|
||||
|
||||
Since the purpose of the transaction cost is to protect the peer-to-peer Ripple network from excessive load, it should apply to any transaction that gets distributed to the network, regardless of whether or not that transaction succeeds. However, in order to affect the shared global ledger, a transaction must be included in a validated ledger. Thus, `rippled` servers attempt to include failed transactions in ledgers, with [`tec` status codes](reference-transaction-format.html#result-categories) ("tec" stands for "Transaction Engine - Claimed fee only").
|
||||
|
||||
The transaction cost is only debited from the sender's XRP balance when the transaction actually becomes included in a validated ledger. This is true whether the transaction is considered successful or fails with a `tec` code.
|
||||
|
||||
If a transaction's failure is [final](reference-transaction-format.html#finality-of-results), the `rippled` server does not relay it to the network. Consequently, that transaction does not get included in a validated ledger, and it cannot have any effect on anyone's XRP balance.
|
||||
|
||||
### Insufficient XRP ###
|
||||
|
||||
When a `rippled` server initially evaluates a transaction, it rejects the transaction with the error code `terINSUF_FEE_B` if the sending account does not have a high enough XRP balance to pay the XRP transaction cost. Since this is a `ter` (Retry) code, the `rippled` server retries the transaction without relaying it to the network, until the transaction's outcome is [final](reference-transaction-format.html#finality-of-results).
|
||||
|
||||
When a transaction has already been distributed to the network, but the account does not have sufficient XRP to pay the transaction cost, the result code `tecINSUFF_FEE` occurs instead. In this case, the account pays all the XRP it can, ending with 0 XRP. This can occur because `rippled` decides whether to relay the transaction to the network based on its in-progress ledger, but transactions may be dropped or reordered when building the consensus ledger.
|
||||
|
||||
|
||||
## Key Reset Transaction ##
|
||||
|
||||
As a special case, an account can send a [SetRegularKey](reference-transaction-format.html#setregularkey) transaction with a transaction cost of `0`, as long as the account's [lsfPasswordSpent flag](reference-ledger-format.html#accountroot-flags) is disabled. This transaction must be signed by the account's _master key_. Sending this transaction enables the lsfPasswordSpent flag.
|
||||
|
||||
This feature is designed to allow you to recover an account if the regular key is compromised, without worrying about whether the compromised account has any XRP available. This way, you can regain control of the account before you send additional XRP to it.
|
||||
|
||||
The [lsfPasswordSpent flag](reference-ledger-format.html#accountroot-flags) starts out disabled. If enabled, it gets disabled again when the account receives a [Payment](reference-transaction-format.html#payment) of XRP.
|
||||
|
||||
When the [FeeEscalation amendment](concept-amendments.html#feeescalation) is enabled, `rippled` prioritizes key reset transactions above other transactions even though the nominal transaction cost of a key reset transaction is zero.
|
||||
|
||||
|
||||
## Changing the Transaction Cost ##
|
||||
|
||||
In addition to short-term scaling to account for load, the Ripple Consensus Ledger has a mechanism for changing the minimum transaction cost in order to account for long-term changes in the value of XRP. Any changes have to be approved by the consensus process. See [Fee Voting](concept-fee-voting.html) for more information.
|
||||
43
content/concept-transfer-fees.md
Normal file
@@ -0,0 +1,43 @@
|
||||
# Transfer Fees #
|
||||
|
||||
The `TransferRate` setting in the Ripple Consensus Ledger allows [issuing gateways](https://ripple.com/knowledge_center/gateways/) to charge users a _transfer fee_ for sending that gateway's issuances to other users. When a gateway sets a transfer fee, it costs extra to send a transfer of that gateway's issuances. The sender of the transfer is debited an extra percentage based on the transfer fee, while the recipient of the transfer is credited the intended amount. The difference is the transfer fee, which becomes the property of the issuing gateway, and is no longer tracked in the Ripple Consensus Ledger. The transfer fee does not apply when sending or receiving _directly_ to and from the issuing account, but it does apply when transferring from a [hot wallet](concept-issuing-and-operational-addresses.html) to another user.
|
||||
|
||||
XRP never has a transfer fee, because it never has an issuer.
|
||||
|
||||
For example, ACME Gateway might set the transfer fee to 0.5% for ACME issuances. In order for the recipient of a payment to get 2 EUR.ACME, the sender must send 2.01 EUR.ACME. After the transaction, ACME's outstanding obligations in Ripple have decreased by 0.01€, which means that it is no longer obliged to hold that amount in the account backing its Ripple issuances.
|
||||
|
||||
The following diagram shows a Ripple payment of 2 EUR.ACME from Alice to Charlie with a transfer fee of 1%:
|
||||
|
||||

|
||||
|
||||
## Transfer Fees in Payment Paths ##
|
||||
|
||||
A transfer fee applies whenever an individual transfer would shift issuances from one party to another through the issuing account. In more complex transactions, this can occur multiple times. Transfer fees apply starting from the end and working backwards, so that ultimately the initial sender of a payment must send enough to account for all fees. For example:
|
||||
|
||||

|
||||
|
||||
In this scenario, Salazar (the sender) holds EUR issued by ACME, and wants to deliver 100 USD issued by WayGate to Rosa (the recipient). FXMaker is a market maker with the best offer in the order book, at a rate of 1 USD.WayGate for every 0.9 EUR.ACME. If there were no transfer fees, Salazar could deliver 100 USD to Rosa by sending 90 EUR. However, ACME has a transfer fee of 1% and WayGate has a transfer fee of 0.2%. This means:
|
||||
|
||||
* FXMaker must send 100.20 USD.WayGate in order for Rosa to receive 100 USD.WayGate.
|
||||
* FXMaker's current ask is 90.18 EUR.ACME in order to send 100.20 USD.WayGate.
|
||||
* In order for FXMaker to receive 90.18 EUR.ACME, Salazar must send 91.0818 EUR.ACME.
|
||||
|
||||
# Technical Details #
|
||||
|
||||
The transfer fee is represented by a setting on the issuing (**cold wallet**) account. The transfer fee has a maximum precision of 9 digits, and cannot be less than 0% or greater than 100%. The TransferRate setting applies to all currencies issued by the same account. If you want to have different transfer fee percentages for different currencies, use different cold wallets to issue each currency.
|
||||
|
||||
## RippleAPI ##
|
||||
|
||||
In RippleAPI, the transfer fee is specified in the `transferRate` field, as an integer which represents the amount you must send in order for the recipient to get 1 billion units of the same currency. A `transferRate` of `1005000000` is equivalent to a transfer fee of 0.5%. By default, the `transferRate` is set to no fee. The value of `transferRate` cannot be less than `1000000000` or more than `2000000000`. The value `null` is special: it is equivalent to `1000000000`, meaning no fee.
|
||||
|
||||
A gateway can send a [Settings transaction](reference-rippleapi.html#settings) with its cold wallet to change the `transferRate` for its issuances.
|
||||
|
||||
You can check an account's `transferRate` with the [getSettings method](reference-rippleapi.html#getsettings).
|
||||
|
||||
## rippled ##
|
||||
|
||||
In `rippled`'s JSON-RPC and WebSocket APIs, the transfer fee is specified in the `TransferRate` field, as an integer which represents the amount you must send in order for the recipient to get 1 billion units of the same currency. A `TransferRate` of `1005000000` is equivalent to a transfer fee of 0.5%. By default, the `TransferRate` is set at `1000000000`, indicating no fee. The value of `TransferRate` cannot be less than `1000000000` or more than `2000000000`. However, value `0` is special: it is equivalent to `1000000000`, meaning no fee.
|
||||
|
||||
A gateway can submit an [AccountSet transaction](reference-transaction-format.html#accountset) from its cold wallet to change the `TransferRate` for its issuances.
|
||||
|
||||
You can check an account's `TransferRate` with the [`account_info` command](reference-rippled.html#account-info). If the `TransferRate` is omitted, then that indicates no fee.
|
||||
5
content/data_types/account_sequence.md
Normal file
@@ -0,0 +1,5 @@
|
||||
A Sequence number is a 32-bit unsigned integer used to identify a transaction or Offer relative to a specific account.
|
||||
|
||||
Every [account object in the Ripple Consensus Ledger](reference-ledger-format.html#accountroot) has a Sequence number, which starts at 1. For a transaction to be relayed to the network and possibly included in a validated ledger, it must have a `Sequence` field that matches the sending account's current `Sequence` number. An account's Sequence field is incremented whenever a transaction from that account is included in a validated ledger (regardless of whether the transaction succeeded or failed). This preserves the order of transactions submitted by an account, and differentiates transactions that would otherwise be identical.
|
||||
|
||||
Every [Offer node in the Ripple Consensus Ledger](reference-ledger-format.html#offer) is marked with the sending `Account` [Address][] and the `Sequence` value of the [OfferCreate transaction](reference-transaction-format.html#offercreate) that created it. These two fields, together, uniquely identify the Offer.
|
||||
22
content/data_types/address.md
Normal file
@@ -0,0 +1,22 @@
|
||||
Ripple Accounts are identified by a base-58 Ripple Address, which is derived from the account's master public key. An address is represented as a String in JSON, with the following characteristics:
|
||||
|
||||
* Between 25 and 35 characters in length
|
||||
* Starts with the character `r`
|
||||
* Case-sensitive
|
||||
* [Base-58](https://wiki.ripple.com/Encodings) encoded using only the following characters: `rpshnaf39wBUDNEGHJKLM4PQRST7VWXYZ2bcdeCg65jkm8oFqi1tuvAxyz` That's alphanumeric characters, excluding zero (`0`), capital O (`O`), capital I (`I`), and lowercase L (`l`).
|
||||
* Contains error-checking that makes it unlikely that a randomly-generated string is a valid address.
|
||||
|
||||
#### Special Addresses ####
|
||||
[ACCOUNT_ONE]: #special-addresses
|
||||
[ACCOUNT_ZERO]: #special-addresses
|
||||
|
||||
Some addresses have special meaning, or historical uses, in the Ripple Consensus Ledger. In many cases, these are "black hole" addresses, meaning the address is not derived from a known secret key. Since it is almost impossible to guess a secret key from just an address, any XRP possessed by those addresses is lost forever.
|
||||
|
||||
| Address | Name | Meaning | Black Hole? |
|
||||
|-----------------------------|------|---------|-------------|
|
||||
| rrrrrrrrrrrrrrrrrrrrrhoLvTp | ACCOUNT\_ZERO | An address that is the base-58 encoding of the value `0`. In peer-to-peer communications, `rippled` uses this address as the issuer for XRP. | Yes |
|
||||
| rrrrrrrrrrrrrrrrrrrrBZbvji | ACCOUNT\_ONE | An address that is the base-58 encoding of the value `1`. In the ledger, [RippleState entries](reference-ledger-format.html#ripplestate) use this address as a placeholder for the issuer of a trust line balance. | Yes |
|
||||
| rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh | The genesis account | When `rippled` starts a new genesis ledger from scratch (for example, in stand-alone mode), this account holds all the XRP. This address is generated from the seed value "masterpassphrase" which is [hard-coded](https://github.com/ripple/rippled/blob/94ed5b3a53077d815ad0dd65d490c8d37a147361/src/ripple/app/ledger/Ledger.cpp#L184). | No |
|
||||
| rrrrrrrrrrrrrrrrrNAMEtxvNvQ | Ripple Name reservation black-hole | In the past, Ripple asked users to send XRP to this account to reserve Ripple Names.| Yes |
|
||||
| rrrrrrrrrrrrrrrrrrrn5RM1rHd | NaN Address | Previous versions of [ripple-lib](https://github.com/ripple/ripple-lib) generated this address when base-58 encoding the value [NaN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/NaN). | Yes |
|
||||
|
||||
5
content/data_types/currency_code.md
Normal file
@@ -0,0 +1,5 @@
|
||||
There are two kinds of currency code in the Ripple Consensus Ledger:
|
||||
|
||||
* Three-character currency code. We recommend using all-uppercase [ISO 4217 Currency Codes](http://www.xe.com/iso4217.php). However, any combination of the following characters is permitted: all uppercase and lowercase letters, digits, as well as the symbols `?`, `!`, `@`, `#`, `$`, `%`, `^`, `&`, `*`, `<`, `>`, `(`, `)`, `{`, `}`, `[`, `]`, and <code>|</code>. The currency code `XRP` (all-uppercase) is reserved for XRP and cannot be used by issued currencies.
|
||||
* 160-bit hexadecimal values, such as `0158415500000000C1F76FF6ECB0BAC600000000`, according to Ripple's internal [Currency Format](https://wiki.ripple.com/Currency_format). This representation is uncommon.
|
||||
|
||||
10
content/data_types/hash.md
Normal file
@@ -0,0 +1,10 @@
|
||||
Many objects in Ripple, particularly transactions and ledgers, are uniquely identified by a 256-bit hash value. This value is typically calculated as a "SHA-512Half", which calculates a [SHA-512](http://dx.doi.org/10.6028/NIST.FIPS.180-4) hash from some contents, then takes the first 64 characters of the hexadecimal representation. Since the hash of an object is derived from the contents in a way that is extremely unlikely to produce collisions, two objects with the same hash can be considered identical.
|
||||
|
||||
A Ripple hash value has the following characteristics:
|
||||
|
||||
* Exactly 64 characters in length
|
||||
* [Hexadecimal](https://en.wikipedia.org/wiki/Hexadecimal) character set: 0-9 and A-F.
|
||||
* Typically written in upper case.
|
||||
|
||||
**Note:** SHA-512Half has similar security to the officially-defined _SHA-512/256_ hash function. However, Ripple's usage predates SHA-512/256 and is also easier to implement on top of an existing SHA-512 function. (As of this writing, SHA-512 support in cryptographic libraries is much more common than for SHA-512/256.)
|
||||
|
||||
7
content/data_types/ledger_index.md
Normal file
@@ -0,0 +1,7 @@
|
||||
A ledger index is a 32-bit unsigned integer used to identify a ledger. The ledger index is also known as the ledger's sequence number. The very first ledger was ledger index 1, and each subsequent ledger has a ledger index 1 higher than that of the ledger immediately before it.
|
||||
|
||||
The ledger index indicates the order of the ledgers; the [Hash][] value identifies the exact contents of the ledger. Two ledgers with the same hash are always identical. For validated ledgers, hash values and sequence numbers are equally valid and correlate 1:1. However, this is not true for in-progress ledgers:
|
||||
|
||||
* Two different `rippled` servers may have different contents for a current ledger with the same ledger index, due to latency in propagating transactions throughout the network.
|
||||
* There may be multiple closed ledger versions competing to be validated by consensus. These ledger versions have the same sequence number but different contents (and different hashes). Only one of these closed ledgers can become validated.
|
||||
* A current ledger's contents change over time, which would cause its hash to change, even though its ledger index number stays the same. Therefore, the hash of a ledger is not calculated until the ledger is closed.
|
||||
@@ -1,976 +0,0 @@
|
||||
# Introduction #
|
||||
|
||||
The Gateway Services initiative aims to make gateways interoperable, extending the connectivity of the Ripple Network beyond the bounds of the Ripple ledger. The goal is to allow anyone who's connected to Ripple (not just Ripple account holders) to look up another Ripple-connected entity, find a path between them, quote the cost of a payment, and then make that payment, in a way that is consistent, regulation-compliant, and standards-compliant. It defines a series of REST API calls that make it possible for other gateways and Ripple client applications to perform all of these actions.
|
||||
|
||||
Gateways that implement these services can easily link with one another, allowing users who have a business relationship with one of them to send and receive money to parties that are connected to other gateways in an automated fashion, while remaining regulation-compliant. Our Gatewayd framework will implement all these services, so gateway operators using Gatewayd don't need to do anything beyond standard configuration, and those with custom gateway software can use Gatewayd as a reference implementation.
|
||||
|
||||
<div class='alert-danger alert'>
|
||||
This document, and the APIs it defines, are a work in progress. Do not go implementing them already! We are exposing these explanations as guidance to where we are heading, with the intent of getting feedback to refine them as necessary.<br><br>
|
||||
All names, URLs, and addresses in this document are used for example purposes only, and do not reflect actual services or a commitment to provide actual services.
|
||||
</div>
|
||||
|
||||
## Components ##
|
||||
|
||||
| Service | Description | Based On | Replaces |
|
||||
| ------- | ----------- | -------- | -------- |
|
||||
| [host-meta](#host-meta) | Provides useful metadata about a gateway or service provider, and lists all service endpoints provided by the domain | [RFC6415](http://tools.ietf.org/html/rfc6415) | [ripple.txt](https://ripple.com/wiki/Ripple.txt) |
|
||||
| [webfinger](#webfinger) | Performs reverse lookup of Ripple addresses, and lists service endpoints for interacting with a specified account holder | [RFC7033](http://tools.ietf.org/html/rfc7033) | [Federation Name Lookup](https://ripple.com/wiki/Federation_protocol) |
|
||||
| [bridge-payments](#bridge-payments) | Plans payments from any Ripple-connected wallet to any other, connecting through gateways as necessary. | [Ripple-REST payments](ripple-rest.html#payments) | [Bridge protocol](https://ripple.com/wiki/Services_API) |
|
||||
| user-account | Provides standard method for registering an account with a Gateway, and provides signed claims about a user's identity similar to bridge-payment's required claims | [OpenID Connect Claims](http://openid.net/specs/openid-connect-core-1_0.html#Claims), [JWT](http://tools.ietf.org/html/draft-ietf-oauth-json-web-token-25) | -- |
|
||||
| wallet-payment | Makes outgoing payments and monitors for incoming payments, and works with hosted wallets. | [Ripple-REST payments](ripple-rest.html#payments) | -- |
|
||||
| wallet-info | Shows information about a wallet, and works with hosted wallets | [Ripple-REST accounts](ripple-rest.html#accounts) | -- |
|
||||
| wallet-balances | Shows information about balances in multiple currencies, and works with hosted wallets. | [Ripple-REST accounts](ripple-rest.html#accounts) | -- |
|
||||
| wallet-history | Shows history of payments sent and received, and works with hosted wallets. | [Ripple-REST payment history](ripple-rest.html#payment-history) | -- |
|
||||
|
||||
## Event Sequence ##
|
||||
|
||||
The Gateway Services APIs are built to support many different process flows, but most of them can be simplified down to a simple payment flow through one or more gateways, such as the following:
|
||||
|
||||
[](img/gateway_services_sequence.png)
|
||||
|
||||
In this sequence, the client application starts with three pieces of information that define the payment that the user would like to make:
|
||||
|
||||
* A unique identifier for the originator of the payment
|
||||
* A unique identifier for the beneficiary of the payment
|
||||
* An amount, including a currency, that the beneficiary should receive
|
||||
|
||||
Initially, the client application uses the identifiers to determine which domains it should query. In the example image, federation addresses (_user@service.tld_) are used, so the domain can be determined directly from the URI. See [Gateway Services Identifiers](#gateway-services-identifiers) for more information. The client queries each domain's host-meta to confirm that it has the necessary Gateway Services available, and where those services are provided.
|
||||
|
||||
If they provide a WebFinger service, the client application looks up the originator and beneficiary of the payment using WebFinger. A successful response with a bridge-payments link indicates that the accounts are valid and connected to Ripple through the gateways.
|
||||
|
||||
Now the client gets quotes for ways to make the payment. It asks the sending gateway for quotes. In this example, the sending gateway determines that it cannot make a payment to the receiving account directly. It requests host-meta and WebFinger from the receiving gateway just like the client did (not pictured), then gets quotes for the desired payment from the receiving Gateway. Each quote contains a wallet-payment object that the gateway wants to receive in exchange for making the desired outgoing payment.
|
||||
|
||||
*Note:* The client could skip this recursive process by calling the destination gateway directly, but in our example the sending user does not have a way to pay the receiving gateway directly. (He neither holds euros nor has a Ripple account.) Gateway Services makes it possible to connect the two because both gateways have Ripple accounts.
|
||||
|
||||
The inbound gateway takes the quotes it received from the outbound gateway, chooses one or more that it likes, and pads them to account for its own costs and risks before presenting them back to the client as quotes for the whole payment.
|
||||
|
||||
The client chooses a quote and accepts it, which causes the inbound gateway to accept the corresponding quote from the outbound gateway. It sends back a message to the client indicating success. At this point, all parties are ready for the chain of payments to be made.
|
||||
|
||||
Finally, the client performs a wallet-payment call, which either pulls the money directly out of the appropriate account (if possible), or redirects the client to a place where the user can push the money back. An invoice ID on the payment lets the inbound gateway know which Gateway Transaction the incoming payment is meant to pay for.
|
||||
|
||||
After receiving money from the sender, the inbound performs the same call on the outbound gateway, and sends the payment (in this example, a Ripple payment) with the invoice ID that the outbound gateway is looking for. When the outbound gateway receives the payment, it recognizes the amount and invoice ID, which prompts it to send the final outgoing payment to the destination.
|
||||
|
||||
|
||||
# Gateway Services Identifiers #
|
||||
|
||||
Several APIs require you to identify the sender or recipient of a payment. Since several different types of identifiers can be used this way, Gateway Services defines a standard way to create a Universal Resource Identifier (URI) for each type of resource. Any party of a payment should have a URI associated with it that can be WebFingered. This may include:
|
||||
|
||||
* The originator (sender) of a payment
|
||||
* The beneficiary (receiver) of the payment
|
||||
* Up to two gateways operating as inbound bridge (onto Ripple) and/or outbound bridges (off of Ripple)
|
||||
* Up to two "Participating parties" (one on each end of the transaction), for example the clerk at a store receiving or handing out cash. This may be important for compliance purposes, especially for remittance.
|
||||
|
||||
As a general rule on the web at large, any URI starts with a "scheme" portion, followed by a colon, for example `http:`. Gateway service supports using URIs with several different schemes as identifiers to represent the parties to a payment. Depending on the scheme, a particular URI may map to something different:
|
||||
|
||||
* `acct:` identifiers refer to a user account at a particular service, such as an account at a bank or financial service.
|
||||
* `ripple:` identifiers refer to a specific Ripple account in the shared global ledger
|
||||
* `http:` and `https:` identifiers, always followed by *a domain only*, refer to a specific business entity that is connected to Ripple
|
||||
* Other identifiers can be used, depending on the configuration of the gateway being used.
|
||||
|
||||
An identifier can only be used if a JRD with the necessary information can be found by WebFingering that identifier. Part of the challenge is knowing which WebFinger service to use to look up the desired URI. This is a matter of finding out the right domain to use from the URI.
|
||||
|
||||
## Native Identifiers ##
|
||||
|
||||
Some kinds of URIs provide a single clear domain that can be used to perform the WebFinger request. A client application must use the following rules for where to WebFinger identifiers in the following formats:
|
||||
|
||||
| Type of Identifier | Example | Where to WebFinger |
|
||||
|--------------------|---------|--------------------|
|
||||
| Email address | acct:bob@ripple.com | Domain from the email |
|
||||
| Email-style Federation address | acct:bob@fidor.de | Domain from the address
|
||||
| Ripple Address | ripple:rBWay8KRdmroZra4DTXi6h5cLtPhs5mH7v | Domain from the Ripple AccountRoot object |
|
||||
| Ripple Address with Destination Tag | ripple:rBWay8KRdmroZra4DTXi6h5cLtPhs5mH7v?dt=103047 | Domain from the Ripple AccountRoot object |
|
||||
| Ripple Name | ripple:bob | Domain from the Ripple AccountRoot object |
|
||||
| Domain | http://snapswap.us | Use [host-meta](#host-meta) instead. |
|
||||
|
||||
In the case where a particular email does not provide sufficient information to send a payment, client applications may optionally use a [WebFist](http://www.onebigfluke.com/2013/06/bootstrapping-webfinger-with-webfist.html) service to check for alternate places to WebFinger the provided address.
|
||||
|
||||
## Additional Identifiers ##
|
||||
|
||||
Additional identifiers may be supported, in order to provide compatibility with other payment systems. Decide where to WebFinger additional URI formats according to the following rules:
|
||||
|
||||
Client Applications should either:
|
||||
|
||||
* Be explicitly linked to a particular gateway (e.g. a Fidor app that uses only Fidor-hosted Gateway Services), _or_
|
||||
* Only WebFinger gateways explicitly chosen by the user.
|
||||
* Client apps can make this easier by using a central "Registry" of gateways and presenting choices to the user. <span class='draft-comment'>No spec for such a registry exists at this time.</span>
|
||||
|
||||
Gateway Services providers can recursively WebFinger the **reciever** of a payment based on the **outbound bridges** it trusts that are capable of handing the **destination currency**. Gateways should take responsibility for the outbound bridges that they trust to make the last mile of a payment. This might mean only using outbound bridges that are operated by the same business entity or its partners.
|
||||
|
||||
As long as the identifier is reasonably likely to *uniquely* refer to a particular account or person, arbitrary identifiers may be used. We recommend specific formats for the following types of identifiers: <span class='draft-comment'>Format and examples are non-final mockups.</span>
|
||||
|
||||
| Type of Identifier | Format | Example |
|
||||
|--------------------|---------|---------|
|
||||
| US Bank number | usbn:{routing}+{bank acct num} | usbn:2209348904802+23401011034 |
|
||||
| IBAN | iban:{some iban format??} | iban:9293722341 |
|
||||
| Credit/Debit card | card:{15-16 digit card number} | card:4811738483484923 |
|
||||
| Coin address | bitcoin:{bitcoin address} | bitcoin:b238974jsv9sd8sdf923as33f |
|
||||
| Paypal address | paypal:{email address used as PayPal login}<br>paypal:{phone number?} | acct:rome@ripple.com@paypal.com acct:paypal:rome@ripple.com |
|
||||
| Google wallet | google:{email address} | google:mduo13@gmail.com |
|
||||
| Square cash | square:{email address} | square:rome@ripple.com |
|
||||
|
||||
## Currency Codes ##
|
||||
|
||||
Currency codes in Gateway Services are specified as they are in Ripple. In most common cases, this means that currencies are provided as three-letter [ISO4217](http://www.xe.com/iso4217.php/) identifiers such as `"USD"`. Three-letter identifiers should be **case-insensitive**.
|
||||
|
||||
A currency can also be provided as a 160-bit hexadecimal string, in case it has unusual properties such as built-in demurrage. For example, gold with 0.5% annual demurrage from [Gold Bullion International](http://www.bullioninternational.com/digital-physical-gold/) is represented as the string `"0158415500000000C1F76FF6ECB0BAC600000000"`.
|
||||
|
||||
It is RECOMMENDED that Gateway Services providers and clients should be able to recognize hex values that refer to common 3-letter currencies. This can be achieved by the following method:
|
||||
|
||||
* Convert three-letter codes to uppercase. (This is important! Even though "btc" is considered the same as "BTC", both should map to the same hex)
|
||||
* Determine the hex ASCII codes for those letters. For example, "JPY" is "4A5059".
|
||||
* Render the hex code as "000000000000000000000000" + the hex of the 3-letter currency code + "0000000000"
|
||||
* If this code matches a hex code that is provided directly, then they are the same currency.
|
||||
|
||||
See [Currency Format](https://wiki.ripple.com/Currency_format) for more detailed information on the hex representation..
|
||||
|
||||
|
||||
|
||||
|
||||
# Host-Meta #
|
||||
|
||||
Host-Meta tells you about things operated by a domain.
|
||||
|
||||
[RFC6415](http://tools.ietf.org/html/rfc6415) defines a standardized way to publish metadata, including information about resources controlled by the host, for any domain. In contrast to the original spec, **Ripple uses the JSON version of host-meta exclusively**, and never queries for the XML version. This spec defines several Ripple-centric resources which a host can advertise in a host-meta file, so that other applications can automatically **find** the host's other Gateway services, and **verify** the domain's various Ripple assets. This extends and replaces the functionality of the [ripple.txt](https://wiki.ripple.com/Ripple.txt) spec.
|
||||
|
||||
The response to a host-meta request is a document called a JRD (JSON resource descriptor; there is also an XML version called an XRD).
|
||||
|
||||
#### Request Format ####
|
||||
|
||||
```
|
||||
GET /.well-known/host-meta.json
|
||||
```
|
||||
|
||||
Alternate request format:
|
||||
|
||||
```
|
||||
GET /.well-known/host-meta
|
||||
Accept: application/json
|
||||
```
|
||||
|
||||
__*Note:*__ Some domains that do not use Gateway Services may implement host-meta without providing a JRD. In this case, the alternate request format may return an XRD document instead of a Not Found error.
|
||||
|
||||
|
||||
Here is an example of an entire host-meta JRD:
|
||||
|
||||
__`GET https://latambridgepay.com/.well-known/host-meta.json`__
|
||||
|
||||
```
|
||||
{
|
||||
"subject": "https://latambridgepay.com",
|
||||
"expires": "2014-01-30T09:30:00Z",
|
||||
"properties": {
|
||||
"name": "Latam Bridge Pay",
|
||||
"description": "Ripple Gateway to and from Latin American banks.",
|
||||
"rl:type": "gateway",
|
||||
"rl:domain": "latambridgepay.com",
|
||||
"rl:accounts": [
|
||||
{
|
||||
"address": "r4tFZoa7Dk5nbEEaCeKQcY3rS5jGzkbn8a",
|
||||
"rl:currencies": [
|
||||
"USD",
|
||||
"BRL",
|
||||
"PEN",
|
||||
"MXN"
|
||||
]
|
||||
}
|
||||
],
|
||||
"rl:hotwallets": [
|
||||
"rEKuBLEX2nHUiGB9dCGPnFkA7xMyafHTjP"
|
||||
]
|
||||
},
|
||||
"links": [
|
||||
{
|
||||
"rel": "lrdd",
|
||||
"template": "https://latambridgepay.com/.well-known/webfinger.json?q={uri}",
|
||||
"properties": {
|
||||
"rl:uri_schemes": ["paypal","bitcoin","acct","ripple"]
|
||||
}
|
||||
},
|
||||
{
|
||||
"rel": "https://gatewayd.org/gateway-services/bridge_payments",
|
||||
"href": "https://latambridgepay.com/v1/bridge_payments",
|
||||
"properties": {
|
||||
"version": "1",
|
||||
"additional_info_definitions":{
|
||||
"bank": {
|
||||
"type": "AstropayBankCode",
|
||||
"label": {
|
||||
"en": "Astropay Bank Code"
|
||||
},
|
||||
"description": {
|
||||
"en": "Bank code from Astropay's documentation"
|
||||
}
|
||||
},
|
||||
"country": {
|
||||
"type": "AstropayCountryCode",
|
||||
"label": {
|
||||
"en": "Astropay Country Code",
|
||||
},
|
||||
"description": {
|
||||
"en": "Country code from Astropay's documentation"
|
||||
}
|
||||
},
|
||||
"cpf": {
|
||||
"type": "PersonalIDNumber",
|
||||
"label": {
|
||||
"en": "Personal Government ID Number"
|
||||
},
|
||||
"description": {
|
||||
"en": "Personal ID number from the Astropay documentation"
|
||||
},
|
||||
}
|
||||
"name": {
|
||||
"type": "FullName",
|
||||
"label": {
|
||||
"en": "Sender's Full Name"
|
||||
},
|
||||
"description": {
|
||||
"en": "First and last name of sender"
|
||||
}
|
||||
},
|
||||
"email": {
|
||||
"type": "EmailAddress",
|
||||
"label": {
|
||||
"en": "Sender's Email Address"
|
||||
},
|
||||
"description": {
|
||||
"en": "Sender's Email Address"
|
||||
}
|
||||
},
|
||||
"bdate": {
|
||||
"type": "Date",
|
||||
"label": {
|
||||
"en": "YYYYMMDD"
|
||||
},
|
||||
"description": {
|
||||
"en": "Sender's date of birth"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
This file is divided up into the following elements:
|
||||
|
||||
## Host-Meta Aliases ##
|
||||
|
||||
[Aliases are NOT RECOMMENDED](http://tools.ietf.org/html/rfc6415#section-3.1) in host-meta, according to the spec. Consumers of Gateway Services should not rely on any content there.
|
||||
|
||||
## Host-Meta Properties ##
|
||||
|
||||
```js
|
||||
...
|
||||
"properties": {
|
||||
"name": "Latam Bridge Pay",
|
||||
"description": "Ripple Gateway to and from Latin American banks.",
|
||||
"rl:type": "gateway",
|
||||
"rl:domain": "latambridgepay.com",
|
||||
"rl:accounts": [
|
||||
{
|
||||
"address": "r4tFZoa7Dk5nbEEaCeKQcY3rS5jGzkbn8a",
|
||||
"rl:currencies": [
|
||||
"USD",
|
||||
"BRL",
|
||||
"PEN",
|
||||
"MXN"
|
||||
]
|
||||
}
|
||||
],
|
||||
"rl:hotwallets": [
|
||||
"rEKuBLEX2nHUiGB9dCGPnFkA7xMyafHTjP"
|
||||
]
|
||||
}
|
||||
...
|
||||
```
|
||||
|
||||
The host-meta JRD may contain any of the following Ripple-defined properties:
|
||||
|
||||
| Property | Value | Description |
|
||||
|----------|-------|-------------|
|
||||
| rl:type | String | What type of Ripple entity this domain is. Valid types are `"gateway"`, `"merchant"`, `"bridge"`, `"wallet-service"`, `"end-user"`. Other custom types are allowed. |
|
||||
| rl:domain | String | The domain this host-meta document applies to, which should match the one it is being served from. For example, `"coin-gate.com"` |
|
||||
| rl:accounts | Array of objects | Each member of this array should be an [account definition object](#acct_def_obj) for an issuing account (cold wallet) operated by this host |
|
||||
| rl:hotwallets | Array of strings | Each member of this array should be either a base-58-encoded Ripple Address or a Ripple Name for a hot wallet operated by the host |
|
||||
|
||||
Gateway Services clients may also use the standard "name" and "description" properties.
|
||||
|
||||
<span class='draft-comment'>TBD: format for providing a JWT-signing PubKey in the properties. (Possibly use OpenID format?)</span>
|
||||
|
||||
#### Account Definition Object <a name="acct_def_obj"></a> ####
|
||||
|
||||
An account definition object is a JSON object with the following properties:
|
||||
|
||||
| Property | Value | Description |
|
||||
|----------|-------|-------------|
|
||||
| address | String | Base-58-encoded Ripple address |
|
||||
| rl:name | String | (Optional) The [Ripple Name](https://ripple.com/dev-blog/introducing-ripple-names/) of this account, omitting the leading tilde (~) |
|
||||
| rl:currencies | Object | Map of currencies issued from this address, where field names are the currency codes and values are the maximum amount issued, as a string containing a decimal number. |
|
||||
|
||||
Example account definition object:
|
||||
|
||||
```js
|
||||
{
|
||||
"address": "rLtys1YJHGj8oTpECWSzDv77YRGDWGduUX",
|
||||
"rl:currencies": {
|
||||
"BTC": "1000000"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Host-Meta Links ##
|
||||
|
||||
The `links` field contains links to almost anything. The meaning of the link is identified by a relation type, typically a URI, in the `rel` field of the link object. Gateways should use links to advertise the other Gateway Services APIs that they offer.
|
||||
|
||||
Gateway Services requires the following links in host-meta:
|
||||
|
||||
* [Webfinger Link](#webfinger_link)
|
||||
* [Bridge Payments Link](#bridge_payments_link)
|
||||
* <span class='draft-comment'>(As additional services are defined, they should have links added to host-meta.)</span>
|
||||
|
||||
|
||||
### WebFinger Link <a name="webfinger_link"></a> ###
|
||||
|
||||
This link indicates where the [WebFinger (lrdd) service](#webfinger) is provided.
|
||||
|
||||
```js
|
||||
...
|
||||
"links": [
|
||||
{
|
||||
"rel": "lrdd",
|
||||
"template": "https://latambridgepay.com/.well-known/webfinger.json?q={uri}",
|
||||
"properties": {
|
||||
"rl:uri_schemes": ["paypal","bitcoin","acct","ripple"]
|
||||
}
|
||||
},
|
||||
...
|
||||
```
|
||||
|
||||
Gateway Services requires the use of the [Webfinger protocol](https://code.google.com/p/webfinger/wiki/WebFingerProtocol). The fields of the link are defined as follows:
|
||||
|
||||
| Field | Value |
|
||||
|----------|--------|
|
||||
| rel | `lrdd` |
|
||||
| template | The URL of your webfinger service, with `{uri}` in place of the resource to look up. |
|
||||
| properties | Object with properties of this link |
|
||||
|
||||
The `properties` field should contain the following field:
|
||||
|
||||
| Field | Value | Description |
|
||||
|----------------|-------|-------------|
|
||||
| rl:uri_schemes | Array | Each member of this array refers to the scheme section (the part before the first colon) of [Gateway Services Identifiers](#gateway-services-identifiers) that can be WebFingered at this location. By default, Gateway Services providers should support `acct` and `ripple`; other schemes indicate that the gateway operates a bridge that can send to and/or receive from identifiers for those schemes. |
|
||||
|
||||
|
||||
### Bridge Payments Link <a name="bridge_payments_link"></a> ###
|
||||
|
||||
This link indicates where the [Bridge-Payments Service](#bridge-payments) is provided, and information about it.
|
||||
|
||||
```js
|
||||
...
|
||||
"links": [
|
||||
...
|
||||
{
|
||||
"rel": "https://gatewayd.org/gateway-services/bridge_payments",
|
||||
"href": "https://latambridgepay.com/v1/bridge_payments",
|
||||
"properties": {
|
||||
"version": "1",
|
||||
"bridges": [
|
||||
{
|
||||
"currency": "USD",
|
||||
"scheme": "astropay",
|
||||
"direction": "both"
|
||||
},
|
||||
{
|
||||
"currency": "BTC",
|
||||
"scheme": "bitcoin",
|
||||
"direction": "in"
|
||||
}
|
||||
],
|
||||
"additional_info_definitions":{
|
||||
"bank": {
|
||||
"type": "AstropayBankCode",
|
||||
"label": {
|
||||
"en": "Astropay Bank Code"
|
||||
},
|
||||
"description": {
|
||||
"en": "Bank code from Astropay's documentation"
|
||||
}
|
||||
},
|
||||
"country": {
|
||||
"type": "AstropayCountryCode",
|
||||
"label": {
|
||||
"en": "Astropay Country Code",
|
||||
},
|
||||
"description": {
|
||||
"en": "Country code from Astropay's documentation"
|
||||
}
|
||||
},
|
||||
"cpf": {
|
||||
"type": "PersonalIDNumber",
|
||||
"label": {
|
||||
"en": "Personal Government ID Number"
|
||||
},
|
||||
"description": {
|
||||
"en": "Personal ID number from the Astropay documentation"
|
||||
},
|
||||
}
|
||||
"name": {
|
||||
"type": "FullName",
|
||||
"label": {
|
||||
"en": "Sender's Full Name"
|
||||
},
|
||||
"description": {
|
||||
"en": "First and last name of sender"
|
||||
}
|
||||
},
|
||||
"email": {
|
||||
"type": "EmailAddress",
|
||||
"label": {
|
||||
"en": "Sender's Email Address"
|
||||
},
|
||||
"description": {
|
||||
"en": "Sender's Email Address"
|
||||
}
|
||||
},
|
||||
"bdate": {
|
||||
"type": "Date",
|
||||
"label": {
|
||||
"en": "YYYYMMDD"
|
||||
},
|
||||
"description": {
|
||||
"en": "Sender's date of birth"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
...
|
||||
```
|
||||
|
||||
|
||||
The fields of the link are defined as follows:
|
||||
|
||||
| Field | Value |
|
||||
|----------|--------|
|
||||
| rel | `https://gatewayd.org/gateway-services/bridge_payments` |
|
||||
| href | The base URL of the gateway's bridge-payments service. |
|
||||
| properties | Object with key-value map of properties for this link. |
|
||||
|
||||
#### Properties ####
|
||||
|
||||
The following properties should be provided:
|
||||
|
||||
| Field | Value |
|
||||
|----------|--------|
|
||||
| version | `"1"` for this version of the spec. |
|
||||
| bridges | Array of objects describing any Ripple bridges operated by this gateway. |
|
||||
| additional\_info\_definitions | Definitions of all additional fields that may be requested to make payments through this API. |
|
||||
|
||||
Each member of the `bridges` array should be an object with the following fields:
|
||||
|
||||
| Field | Value | Description |
|
||||
|-----------|--------|-------------|
|
||||
| currency | String | Currency code for the currency supported by this bridge. |
|
||||
| scheme | String | A valid URI scheme that matches identifiers used to make non-Ripple payments to or from this bridge. See [Gateway Services Identifiers](#gateway-services-identifiers) for a list of schemes. The scheme `ripple` is not valid here. |
|
||||
| direction | String | Whether this bridge supports payments into the Ripple network (`in`), payments out from the Ripple network (`out`) or payments in both directions (`both`). Any other values of this field are invalid. |
|
||||
|
||||
Each field name in the `additional_info` object should match a field that may be requested by the [Get Quotes method](#get-quotes). The contents of that field in the host-meta should be a definition of the field, so that client applications can create a user interface to request the user to fill in those fields.
|
||||
|
||||
| Field | Value | Description |
|
||||
|----------|--------|-------------|
|
||||
| type | String ([Additional Info Types](#additional-info-type-reference)) | What sort of validation should be performed on this field. |
|
||||
| label | Object | Map of brief labels for this field. Keys should be [two-character ISO-639.1 codes](http://www.loc.gov/standards/iso639-2/php/code_list.php), and values should be human-readable Unicode strings (in the corresponding language) suitable for display in a UI. |
|
||||
| description | Object | Map of longer descriptions for this field. Keys should be [two-character ISO-639.1 codes](http://www.loc.gov/standards/iso639-2/php/code_list.php), and values should be human-readable Unicode strings (in the corresponding language) suitable for display in a UI. |
|
||||
|
||||
For the label and description fields, client applications can choose which language to display, and which languages to fall back on in cases where the preferred language is not provided.
|
||||
|
||||
### Additional Info Type Reference ###
|
||||
|
||||
<span class='draft-comment'>TBD</span>
|
||||
|
||||
|
||||
|
||||
|
||||
# WebFinger #
|
||||
|
||||
WebFinger tells you about a person, hopefully including how to send money to that person.
|
||||
|
||||
[RFC7033](http://tools.ietf.org/html/rfc7033) defines the WebFinger protocol as a way to discover information about people or other entities on the internet, from a URI that might not be usable as a locator otherwise, such as an account or email address. The response to a WebFinger request is like the response to a Host-Meta request, but relates to a specific user (or resource) instead of to the domain. The response to a WebFinger request is also called a JRD (JSON Resource Descriptor)
|
||||
|
||||
Gateway Services uses WebFinger to identify the possible beneficiaries of a payment. The *aliases* and *links* in the WebFinger response provide information about a user with regards to Ripple, including what accounts represent that user, and what services can be used to send money to the user.
|
||||
|
||||
#### Request format: ####
|
||||
|
||||
```
|
||||
GET /.well-known/webfinger.json?resource={uri}
|
||||
```
|
||||
|
||||
Alternate request format:
|
||||
|
||||
```
|
||||
GET /.well-known/webfinger?resource={uri}
|
||||
Accept: application/json
|
||||
```
|
||||
|
||||
The following parameters must be provided in the URL:
|
||||
|
||||
| Field | Value | Description |
|
||||
|-------|-------|-------------|
|
||||
| uri | A valid, URL-encoded [Gateway Services URI](gateway-services-identifiers) | The resource to look up. For Gateway Services, should be an account that might send or receive money, or be otherwise involved in a payment. |
|
||||
|
||||
#### Response Format ####
|
||||
|
||||
The response is a JRD, in a similar format to the response to [host-meta](#host-meta). Gateway Services uses specific [Aliases](#webfinger_aliases) and [Links](#webfinger_links) as described.
|
||||
|
||||
#### Example request: ####
|
||||
|
||||
__`GET https://latambridgepay.com/.well-known/webfinger?resource=ripple:bob`__
|
||||
|
||||
|
||||
#### Example response: ####
|
||||
|
||||
```js
|
||||
{
|
||||
"subject": "ripple:bob",
|
||||
"expires": "2014-10-07T22:46:35.097Z",
|
||||
"aliases": [
|
||||
"ripple:bob",
|
||||
"ripple:rBWay8KRdmroZra4DTXi6h5cLtPhs5mH7v",
|
||||
"paypal:bob@bob-way.com"
|
||||
],
|
||||
"links": [
|
||||
{
|
||||
"rel": "https://gatewayd.org/gateway-services/bridge_payments",
|
||||
"href": "https://latambridgepay.com/v1/bridge_payments",
|
||||
"properties": {
|
||||
"version": "1",
|
||||
"send_to":
|
||||
[
|
||||
{
|
||||
"uri": "acct:bob@bob-way.com",
|
||||
"currencies": ["USD", "XAU"]
|
||||
},
|
||||
{
|
||||
"uri": "paypal:bob@bob-way.com",
|
||||
"currencies": ["USD"]
|
||||
},
|
||||
{
|
||||
"uri": "bitcoin:1Y23423jf9234...",
|
||||
"currencies": ["BTC"]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
## Webfinger Aliases <a id="webfinger_aliases"></a> ##
|
||||
|
||||
```js
|
||||
...
|
||||
"aliases": [
|
||||
"ripple:bob",
|
||||
"ripple:rBWay8KRdmroZra4DTXi6h5cLtPhs5mH7v",
|
||||
"paypal:bob@bob-way.com"
|
||||
],
|
||||
...
|
||||
```
|
||||
|
||||
The `aliases` field of a WebFinger document can contain various values, including ones that are not related to Ripple. Aliases that match supported [Gateway Services URIs](#gateway-services-identifiers) can be used to identify this account as a party to a payment.
|
||||
|
||||
If you WebFinger any of the aliases at the same domain, the resulting document should be the same. Optionally, the `subject` field may change to reflect the resource requested in the URL. Alternatively, the `subject` field can remain the same, to indicate the preferred URI for a particular resource.
|
||||
|
||||
<span class='draft-comment'>(TODO: Discuss weird edge cases here where an alias does not necessarily mean that the user can be paid according to that scheme by this gateway.)</span>
|
||||
|
||||
|
||||
## Webfinger Links <a id="webfinger_links"></a> ##
|
||||
|
||||
The `links` field of a WebFinger document should contain link elements describing where to find the following APIs:
|
||||
|
||||
* Bridge Payments
|
||||
* <span class='draft-comment'>As we add other APIs that are relevant for a particular user, links to those APIs should be added to the WebFinger response.</span>
|
||||
* Optionally, additional links with information relevant to this party can be added. <span class='draft-comment'>The Gateway Services spec may grow to include some uses of additional links, for example location data that can be used by client applications to select from agents in different regions.</span>
|
||||
|
||||
### Bridge Payments Link <a id='webfinger_bridgepayments_link'></a> ###
|
||||
|
||||
```js
|
||||
...
|
||||
{
|
||||
"rel": "https://gatewayd.org/gateway-services/bridge_payments",
|
||||
"href": "https://latambridgepay.com/v1/bridge_payments",
|
||||
"properties": {
|
||||
"version": "1",
|
||||
"send_to":
|
||||
[
|
||||
{
|
||||
"uri": "acct:bob@bob-way.com",
|
||||
"currencies": ["USD", "XAU"]
|
||||
},
|
||||
{
|
||||
"uri": "paypal:bob@bob-way.com",
|
||||
"currencies": ["USD"]
|
||||
},
|
||||
{
|
||||
"uri": "bitcoin:1Y23423jf9234...",
|
||||
"currencies": ["BTC"]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
...
|
||||
```
|
||||
|
||||
The Bridge-Payments link indicates where to find the [Bridge-Payments](#bridge-payments) service for the user in the URL; the URL provided is used as the base for Bridge-Payments methods. Unlike the version of this link in host-meta, the version in the WebFinger JRD does not have a definition of all the fields that might be requested in the `additional_info` paramter. (That information is omitted because it is not related to the resource being WebFingered.)
|
||||
|
||||
Instead, the Bridge-Payments link the WebFinger JRD has a `send_to` property, which indicates which identifiers should be used to send different currencies to the resource being queried. Each element in the `send_to` array should be an object with the following fields:
|
||||
|
||||
| Field | Value | Description |
|
||||
|-------|-------|-------------|
|
||||
| uri | A valid [Gateway Services URI](#gateway-services-identifiers) | This identifies a particular identifier that should be used at this gateway-services link when the resource in the URL is receiving a payment. It may or may not be the same as the URI from the request. Any given URI should only appear once in the `send_to` array. |
|
||||
| currencies | Array | The [currency codes](#currency-codes) for one or more currencies that should be sent to the associated identifier using this bridge-payments service. |
|
||||
|
||||
It is possible that a provider of Gateway Services may only provide WebFinger on a particular domain, so that the `href` for Bridge-Payments may be different for different resources. For example, an individual can set up her personal domain to run WebFinger, so that querying the person's personal email address returns a link to a bridge-payments service operated by a chosen gateway. It is even possible that there may be multiple instances of the Bridge-Payments link (with the same `rel`) but different destinations and properties, indicating that the resource has multiple Gateway Services providers it trusts.
|
||||
|
||||
|
||||
|
||||
# Bridge Payments #
|
||||
|
||||
The Bridge Payments service consists of the following three API calls.
|
||||
|
||||
The URL for all the Bridge Payments calls is relative to the base URL defined in the [Host-Meta Bridge Payments Link](#bridge-payments-link). This should always include at least: `/v1/bridge_payments` (The v1 may change in future versions.)
|
||||
|
||||
* [Get Quotes - `GET /quotes/{sender}/{receiver}/{amount}`](#get-quotes)
|
||||
* [Accept Quote - `POST /`](#accept-quote)
|
||||
* [Check Status - `GET /{id}`](#check-status)
|
||||
|
||||
All three of these operate on a single type: the Gateway Transaction object.
|
||||
|
||||
|
||||
## Gateway Transaction Objects ##
|
||||
|
||||
A Gateway Transaction defines is a type of object that represents a payment through a gateway. This is like a contract, representing a chain of steps that complete the intended payment from a sender to a receiver.
|
||||
|
||||
It looks like this:
|
||||
|
||||
```js
|
||||
{
|
||||
"id": "9876A034899023AEDFE",
|
||||
"state": "quote",
|
||||
"created": "2014-09-23T19:20:20.000Z",
|
||||
|
||||
"source": {
|
||||
"uri": "bobway@snapswap.us",
|
||||
"claims_required": ["dob","us_ssn","zip"],
|
||||
"claims_jwts": ["eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJmYW1pbHlfbmFtZSI6IlJlZ2luZWxsaSIsImdpdmVuX25hbWUiOiJSb21lIn0.o0l4dfizDHOlbqJonkwyqBhufIwfXX9Ltjv56Fcn9SQ", "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJtZXNzYWdlIjoiQ29uZ3JhdHVsYXRpb25zLCB5b3UgZGVjb2RlZCBhIEpXVCJ9.msBhzh2yzZabnMei9b1mchspWXWS0xOxCf4Vlhd6mAg"],
|
||||
"additional_info": {
|
||||
"bank_account": "073240754",
|
||||
"routing_number": "23790832978",
|
||||
"country": "USA",
|
||||
"bank_name": "Example Bank USA"
|
||||
}
|
||||
},
|
||||
|
||||
"wallet_payment": {
|
||||
"destination": "ripple:snapswap"
|
||||
"primary_amount": {
|
||||
"amount": "5.125",
|
||||
"currency": "USD",
|
||||
"issuer": ""
|
||||
},
|
||||
"invoice_id": "87246",
|
||||
"expiration": "2014-09-23T20:20:20.000Z",
|
||||
},
|
||||
|
||||
"destination": {
|
||||
"uri": "acct:stefan@fidor.de",
|
||||
"claims_required": [],
|
||||
"claims_jwts": [],
|
||||
"additional_info": {
|
||||
"zip": "83902-1135"
|
||||
}
|
||||
},
|
||||
"destination_amount": {
|
||||
"amount": "5",
|
||||
"currency": "USD",
|
||||
"issuer": "r4tFZoa7Dk5nbEEaCeKQcY3rS5jGzkbn8a"
|
||||
},
|
||||
|
||||
"parties": {
|
||||
"inbound_bridge": "https://snapswap.us",
|
||||
"outbound_bridge": "http://ripple.fidor.de",
|
||||
"sending_agent": "handler33@brickandmort.ar",
|
||||
"receiving_agent": ""
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
The fields are defined as follows:
|
||||
|
||||
| Field | Value | Description |
|
||||
|--------------------|--------|-------------|
|
||||
| id | String | An identifying hash value that uniquely describes this gateway payment. This is a 256-bit hash of the Gateway Transaction object, omitting the `wallet_payment`, the `state`, and the `id` itself. If any Ripple transactions are made as part of this gateway transaction, they should use this value as the `InvoiceID` field of the Ripple payment. Not included until the response to Accept Quote. |
|
||||
| created | String | The time that this resource was initially created as part of a Get-Quotes request, as an ISO8601 extended format string. This time never changes throughout the lifetime of the object. This is included so that the hashed ID is different if the same parties make a payment for the same amount on different dates. |
|
||||
| state | String | What state the payment is in. Valid states are: `"quote"`, `"invoice"`, `"in_progress"`, `"complete"`, and `"canceled"`. |
|
||||
| source | Object | Information about the originator of the payment. |
|
||||
| wallet\_payment | Object | An object that defines the payment which will initiate the entire chain of necessary transactions. After you accept the quote, you post the **wallet\_payment** object to the appropriate API to make the payment that starts the chain. <span class='draft-comment'>(This object is not yet fully defined.)</span> |
|
||||
| wallet\_payment.expiration | String | Expiration time in ISO8601 extended format. The initial wallet payment will not be accepted if it arrives after this time. When the quote is accepted, the gateway may optionally extend the expiration to a later time. |
|
||||
| destination | Object | Info about the ultimate beneficiary of the payment, in the same format as `source`. |
|
||||
| destination\_amount | Object | The amount of money that is received at the destination. The `issuer` field may be an empty string for non-Ripple addresses or cases where any trusted issuer is accepted. |
|
||||
| parties | Object | Info about intermediary parties in the transaction. A value of `""` indicates that the party is not involved or the field is not applicable this this transaction. |
|
||||
| parties.inbound\_bridge | String (URI) | The gateway provider responsible for receiving a non-Ripple payment and making a Ripple payment. Should be identified by `http://` or `https://` and a domain that has a [host-meta](#host-meta) |
|
||||
| parties.outbound\_bridge | String (URI) | The gateway provider responsible for paying the destination amount, if not the same as `inbound_bridge`. Should be identified by `http://` or `https://` and a domain that has a [host-meta](#host-meta) |
|
||||
| parties.sending\_agent | String (URI) | Another involved party responsible for handling money on behalf of the `source` party. |
|
||||
| parties.receiving\_agent | String (URI) | Another involved party responsible for handling money on behalf of the `destination` party. |
|
||||
|
||||
<span class='draft-comment'>(Possible additional parties: the sender and receiver, again, but as URIs that can definitely be WebFingered at a single definitive domain.)</span>
|
||||
|
||||
The `source` and `destination` objects are defined in the same way, as follows:
|
||||
|
||||
| Field | Value | Description |
|
||||
|--------------------|--------|-------------|
|
||||
| uri | String | A WebFinger-able unique identifier for this account or person. |
|
||||
| claims\_required | Array | A list of pieces of information that are necessary to make this payment. |
|
||||
| claims_jwts | Array | Array of [JWTs](https://tools.ietf.org/html/draft-ietf-oauth-json-web-token-28). Each JWT contains one or more claims about this account or person, and is signed by some authority who vouches for those claims.
|
||||
| additional_info | Object | If additional addressing information is necessary to make the payment, this field contains key-value pairs. The Get Quotes method returns `""` to indicate fields where information is needed. The definitions of these fields is provided in the host-meta. |
|
||||
|
||||
<span class='draft-comment'>Potential future feature - document / estimate all fees including ones on the initiating payment.</span>
|
||||
|
||||
### Calculating the Gateway Transaction ID ###
|
||||
|
||||
The `id` field of the Gateway Transaction should be a hash that uniquely identifies the overarching payment goal, not just one step along the chain. To do this, there are specific rules for calculating the ID.
|
||||
|
||||
<span class='draft-comment'>(Rough draft of this section, subject to change)</span>
|
||||
|
||||
1. Create a JSON object with all the fields of the Gateway Transaction Object __except__: `id`, `state`, and `wallet_payment`.
|
||||
2. Serialize the object as a UTF-8 string, with all the fields in alphabetical order, and no whitespace between elements.
|
||||
3. Take the SHA-256 hash of the serialized string, and use this as the `id` value.
|
||||
|
||||
|
||||
## Get Quotes ##
|
||||
|
||||
Get Quotes tells you what your options are for making a payment.
|
||||
|
||||
__`GET /v1/bridge_payments/quotes/{sender}/{receiver}/{amount}`__
|
||||
|
||||
This API should accept parameters that are formatted as follows:
|
||||
|
||||
| Parameter | Format | Example(s) |
|
||||
|-----------|--------|------------|
|
||||
| sender | A URL-encoded (%-escaped) [Gateway Services Identifier](#gateway-services-identifiers) | acct%3Abob%40ripple.com |
|
||||
| receiver | A URL-encoded (%-escaped) [Gateway Services Identifier](#gateway-services-identifiers) | ripple%3AraLiCEoiYDN3aTw2ZnGmEVXWwYXWiAxR7n |
|
||||
| amount | Decimal value, and [code for the currency to be received](#currency-codes), concatenated with a `+` | 10.99+USD |
|
||||
|
||||
The response to Get Quotes is a JSON object with two top-level fields:
|
||||
|
||||
| Field | Value | Description |
|
||||
|-----------------|---------|-------------|
|
||||
| success | Boolean | `true` if this method succeeded |
|
||||
| bridge_payments | Array | Array of [Payment Objects](#gateway-transaction-objects) in the `quote` state that represent possible payments, which could result in the destination amount being paid to the ultimate beneficiary. |
|
||||
|
||||
The Gateway Services implementation can use custom business logic to determines which bridge_payments to include in the response, if any. This can depend on the sender, the receiver, the currency and amount, or other factors.
|
||||
|
||||
Get Quotes is intended to be a recursive process: if the Gateway Services provider does not know how to make an outgoing payment to the receiver in the specified currency, it can perform a Get Quotes call using another gateway that it trusts, then return quotes accordingly (possibly marked up from the quotes of the other gateway). In this case, most portions of the payment object remain the same throughout, but the `wallet_payment` object at each stage reflects the payment that must be made to continue the chain.
|
||||
|
||||
Some fields of each gateway transaction object may be omitted or not in their final state:
|
||||
|
||||
* The `id` field is omitted until the quote is accepted by both parties (see [Accept Quote](#accept-quote)) because it is a hash of the immutable portions of the gateway transaction object.
|
||||
* The `state` field has the value `"quote"` to indicate that this is just a potential gateway transaction, and is not yet valid.
|
||||
* The `source.claims_jwts` field may be empty, even though `source.claims_required` is not empty. This indicates that this transaction requires signed claims from an authority the gateway trusts before it can be made.
|
||||
* The `source.additional_info` field may contain several fields whose value is the empty string `""`. This indicates that the client must provide values for those fields in order to accept the payment.
|
||||
* The `destination.claims_jwts` and `destination.additional_info` fields may require population in the same manner as the corresponding `source` fields.
|
||||
|
||||
|
||||
### Get Quotes Example ###
|
||||
|
||||
Request:
|
||||
|
||||
```
|
||||
GET https://latambridgepay.com/v1/bridge_payments/acct%3Abobway%40snapswap.us/acct%3Astefan%40fidor.de/5+USD
|
||||
```
|
||||
|
||||
Response:
|
||||
|
||||
```js
|
||||
{
|
||||
"success": true,
|
||||
"bridge_payments": [
|
||||
{
|
||||
"state": "quote",
|
||||
"created": "2014-09-23T19:20:20.000Z",
|
||||
"source": {
|
||||
"uri": "acct:bobway@snapswap.us",
|
||||
"claims_required": [],
|
||||
"claims_jwts": [],
|
||||
"additional_info": {}
|
||||
},
|
||||
"wallet_payment": {
|
||||
"destination": "ripple:snapswap",
|
||||
"primary_amount": {
|
||||
"amount": "5.125",
|
||||
"currency": "USD",
|
||||
"issuer": ""
|
||||
},
|
||||
"invoice_id": "78934",
|
||||
"expiration": "2014-09-23T20:20:20.000Z"
|
||||
},
|
||||
"destination": {
|
||||
"uri": "acct:stefan@fidor.de",
|
||||
"claims_required": [],
|
||||
"claims_jwts": [],
|
||||
"additional_info": {}
|
||||
},
|
||||
"destination_amount": {
|
||||
"amount": "5",
|
||||
"currency": "USD",
|
||||
"issuer": "r4tFZoa7Dk5nbEEaCeKQcY3rS5jGzkbn8a"
|
||||
},
|
||||
"parties": {
|
||||
"inbound_bridge": "https://snapswap.us",
|
||||
"outbound_bridge": "http://ripple.fidor.de",
|
||||
"sending_agent": "",
|
||||
"receiving_agent": ""
|
||||
}
|
||||
},
|
||||
{
|
||||
"state": "quote",
|
||||
"created": "2014-09-23T19:20:20.000Z",
|
||||
"source": {
|
||||
"uri": "acct:bobway@snapswap.us",
|
||||
"claims_required": [],
|
||||
"claims_jwts": [],
|
||||
"additional_info": {}
|
||||
},
|
||||
"wallet_payment": {
|
||||
"destination": "bitcoin:1AAHyhHQzRyKkUaCmAi8dPanXoxqHuGdEJ",
|
||||
"primary_amount": {
|
||||
"amount": "0.0140",
|
||||
"currency": "BTC",
|
||||
"issuer": ""
|
||||
},
|
||||
"invoice_id": "",
|
||||
"expiration": "2014-09-23T20:20:20.000Z"
|
||||
},
|
||||
"destination": {
|
||||
"uri": "acct:stefan@fidor.de",
|
||||
"claims_required": [],
|
||||
"claims_jwts": [],
|
||||
"additional_info": {}
|
||||
},
|
||||
"destination_amount": {
|
||||
"amount": "5",
|
||||
"currency": "USD",
|
||||
"issuer": "r4tFZoa7Dk5nbEEaCeKQcY3rS5jGzkbn8a"
|
||||
},
|
||||
"parties": {
|
||||
"inbound_bridge": "https://snapswap.us",
|
||||
"outbound_bridge": "http://ripple.fidor.de",
|
||||
"sending_agent": "",
|
||||
"receiving_agent": ""
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
## Accept Quote ##
|
||||
|
||||
Bridge Payments lets you tell the gateway which payment you are making, so it can be ready.
|
||||
|
||||
|
||||
Request:
|
||||
|
||||
```
|
||||
POST /v1/bridge_payments/
|
||||
{ .. gateway transaction object ... }
|
||||
```
|
||||
|
||||
No URL parameters. The request body is a single [Gateway Transaction Object](#gateway-transaction-objects) in the `quote` state, as provided by the [Get Quotes method](#get-quotes). Before submitting the request, the client may modify the following fields:
|
||||
|
||||
* `source.claims_jwts`, `source.additional_info`, `destination.claims_jwts`, and `destination.additional_info`: Provide any necessary information, along with claims signed by appropriate authorities, that the gateway requests in order to make this payment.
|
||||
* `sending_agent`, if the client wishes to name an applicable participating party
|
||||
* All other fields should be left exactly as provided by the Get Quotes method. <span class='draft-comment'>We should discuss validation of the quote. Should the server check that the sender did not change any fields to unacceptable values (basically rewriting the contract)? How does it enforce expiration dates?</span>
|
||||
|
||||
Response:
|
||||
|
||||
If the quote is valid and all necessary information is provided, the server returns `200 OK` with the request body containing two top-level fields:
|
||||
|
||||
| Field | Value | Description |
|
||||
|-----------------|---------|-------------|
|
||||
| success | Boolean | `true` if this method succeeded |
|
||||
| bridge_payment | [Gateway Transaction object](#gateway-transaction-objects) | The accepted gateway transaction object, as saved. |
|
||||
|
||||
The Gateway Transaction object should reflect the object provided in the request, with the following exceptions:
|
||||
|
||||
* The `id` field should be provided as an identifying hash for the transaction, not including the `state` field nor the `id` itself. <span class='draft-comment'>(Slightly more detail necessary here.)</span>
|
||||
* The `state` field should be updated to `invoice` status to indicate that the quote has been accepted by both the client and the Gateway Services provider.
|
||||
* Optionally, the Gateway Services provider may extend the `expiration` field to a later time than originally provided. The expiration CANNOT change to earlier than was quoted.
|
||||
|
||||
### Error: Sender Claims Required ###
|
||||
|
||||
```
|
||||
400 Bad Request
|
||||
{
|
||||
success: false,
|
||||
"sender_claims_required": [
|
||||
"bank_account",
|
||||
"routing_number",
|
||||
"country",
|
||||
"bank_name",
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
## Check Status ##
|
||||
|
||||
Bridge payment status checks tells you whether a payment has happened yet.
|
||||
|
||||
__`GET https://latambridgepay.com/v1/bridge_payments/9876`__
|
||||
|
||||
|
||||
Response:
|
||||
|
||||
```js
|
||||
{
|
||||
"id": "9876A034899023AEDFE",
|
||||
"state": "invoice",
|
||||
"created": "2014-09-23T19:20:20.000Z",
|
||||
"source": {
|
||||
"uri": "acct:bobway@snapswap.us",
|
||||
"claims_required": [],
|
||||
"claims_jwts": [],
|
||||
"additional_info": {}
|
||||
},
|
||||
"wallet_payment": {
|
||||
"destination": "ripple:snapswap",
|
||||
"primary_amount": {
|
||||
"amount": "5.125",
|
||||
"currency": "USD",
|
||||
"issuer": ""
|
||||
},
|
||||
"invoice_id": "78934",
|
||||
"expiration": "2014-09-23T20:20:20.000Z"
|
||||
},
|
||||
"destination": {
|
||||
"uri": "acct:stefan@fidor.de",
|
||||
"claims_required": [],
|
||||
"claims_jwts": [],
|
||||
"additional_info": {}
|
||||
},
|
||||
"destination_amount": {
|
||||
"amount": "5",
|
||||
"currency": "USD",
|
||||
"issuer": "r4tFZoa7Dk5nbEEaCeKQcY3rS5jGzkbn8a"
|
||||
},
|
||||
"parties": {
|
||||
"inbound_bridge": "https://snapswap.us",
|
||||
"outbound_bridge": "http://ripple.fidor.de",
|
||||
"sending_agent": "",
|
||||
"receiving_agent": ""
|
||||
}
|
||||
}
|
||||
```
|
||||
2871
content/gatewayd.md
6908
content/img-sources/Gateway Guide Graphics v5.ai
Normal file
10165
content/img-sources/Gateway Guide Graphics v6.svg
Normal file
|
After Width: | Height: | Size: 1.4 MiB |
678
content/img-sources/default-paths.uxf
Normal file
@@ -0,0 +1,678 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<diagram program="umlet" version="13.3">
|
||||
<zoom_level>10</zoom_level>
|
||||
<element>
|
||||
<id>UMLUseCase</id>
|
||||
<coordinates>
|
||||
<x>50</x>
|
||||
<y>560</y>
|
||||
<w>100</w>
|
||||
<h>100</h>
|
||||
</coordinates>
|
||||
<panel_attributes>Account
|
||||
(Sender)
|
||||
lt=.</panel_attributes>
|
||||
<additional_attributes/>
|
||||
</element>
|
||||
<element>
|
||||
<id>UMLUseCase</id>
|
||||
<coordinates>
|
||||
<x>240</x>
|
||||
<y>560</y>
|
||||
<w>100</w>
|
||||
<h>100</h>
|
||||
</coordinates>
|
||||
<panel_attributes>SendMax.
|
||||
issuer
|
||||
lt=.</panel_attributes>
|
||||
<additional_attributes/>
|
||||
</element>
|
||||
<element>
|
||||
<id>Relation</id>
|
||||
<coordinates>
|
||||
<x>140</x>
|
||||
<y>600</y>
|
||||
<w>120</w>
|
||||
<h>30</h>
|
||||
</coordinates>
|
||||
<panel_attributes>lt=.</panel_attributes>
|
||||
<additional_attributes>100.0;10.0;10.0;10.0</additional_attributes>
|
||||
</element>
|
||||
<element>
|
||||
<id>UMLUseCase</id>
|
||||
<coordinates>
|
||||
<x>470</x>
|
||||
<y>560</y>
|
||||
<w>100</w>
|
||||
<h>100</h>
|
||||
</coordinates>
|
||||
<panel_attributes>Amount.
|
||||
issuer
|
||||
lt=.</panel_attributes>
|
||||
<additional_attributes/>
|
||||
</element>
|
||||
<element>
|
||||
<id>UMLUseCase</id>
|
||||
<coordinates>
|
||||
<x>640</x>
|
||||
<y>560</y>
|
||||
<w>100</w>
|
||||
<h>100</h>
|
||||
</coordinates>
|
||||
<panel_attributes>Destination
|
||||
(Receiver)
|
||||
lt=.</panel_attributes>
|
||||
<additional_attributes/>
|
||||
</element>
|
||||
<element>
|
||||
<id>Relation</id>
|
||||
<coordinates>
|
||||
<x>560</x>
|
||||
<y>600</y>
|
||||
<w>100</w>
|
||||
<h>30</h>
|
||||
</coordinates>
|
||||
<panel_attributes>lt=.</panel_attributes>
|
||||
<additional_attributes>10.0;10.0;80.0;10.0</additional_attributes>
|
||||
</element>
|
||||
<element>
|
||||
<id>UMLSpecialState</id>
|
||||
<coordinates>
|
||||
<x>400</x>
|
||||
<y>600</y>
|
||||
<w>20</w>
|
||||
<h>20</h>
|
||||
</coordinates>
|
||||
<panel_attributes>type=termination</panel_attributes>
|
||||
<additional_attributes/>
|
||||
</element>
|
||||
<element>
|
||||
<id>UMLUseCase</id>
|
||||
<coordinates>
|
||||
<x>50</x>
|
||||
<y>170</y>
|
||||
<w>100</w>
|
||||
<h>100</h>
|
||||
</coordinates>
|
||||
<panel_attributes>Account
|
||||
(Sender)
|
||||
lt=.</panel_attributes>
|
||||
<additional_attributes/>
|
||||
</element>
|
||||
<element>
|
||||
<id>UMLUseCase</id>
|
||||
<coordinates>
|
||||
<x>410</x>
|
||||
<y>170</y>
|
||||
<w>100</w>
|
||||
<h>100</h>
|
||||
</coordinates>
|
||||
<panel_attributes>Destination
|
||||
(Receiver)
|
||||
lt=.</panel_attributes>
|
||||
<additional_attributes/>
|
||||
</element>
|
||||
<element>
|
||||
<id>UMLUseCase</id>
|
||||
<coordinates>
|
||||
<x>290</x>
|
||||
<y>170</y>
|
||||
<w>100</w>
|
||||
<h>100</h>
|
||||
</coordinates>
|
||||
<panel_attributes>Amount.
|
||||
issuer
|
||||
lt=.</panel_attributes>
|
||||
<additional_attributes/>
|
||||
</element>
|
||||
<element>
|
||||
<id>Text</id>
|
||||
<coordinates>
|
||||
<x>390</x>
|
||||
<y>210</y>
|
||||
<w>30</w>
|
||||
<h>40</h>
|
||||
</coordinates>
|
||||
<panel_attributes>=</panel_attributes>
|
||||
<additional_attributes/>
|
||||
</element>
|
||||
<element>
|
||||
<id>Relation</id>
|
||||
<coordinates>
|
||||
<x>140</x>
|
||||
<y>210</y>
|
||||
<w>170</w>
|
||||
<h>30</h>
|
||||
</coordinates>
|
||||
<panel_attributes>lw=2.5</panel_attributes>
|
||||
<additional_attributes>150.0;10.0;10.0;10.0</additional_attributes>
|
||||
</element>
|
||||
<element>
|
||||
<id>UMLUseCase</id>
|
||||
<coordinates>
|
||||
<x>50</x>
|
||||
<y>300</y>
|
||||
<w>100</w>
|
||||
<h>100</h>
|
||||
</coordinates>
|
||||
<panel_attributes>Account
|
||||
(Sender)
|
||||
lt=.</panel_attributes>
|
||||
<additional_attributes/>
|
||||
</element>
|
||||
<element>
|
||||
<id>Relation</id>
|
||||
<coordinates>
|
||||
<x>140</x>
|
||||
<y>340</y>
|
||||
<w>190</w>
|
||||
<h>30</h>
|
||||
</coordinates>
|
||||
<panel_attributes>lw=2.5</panel_attributes>
|
||||
<additional_attributes>170.0;10.0;10.0;10.0</additional_attributes>
|
||||
</element>
|
||||
<element>
|
||||
<id>UMLUseCase</id>
|
||||
<coordinates>
|
||||
<x>570</x>
|
||||
<y>300</y>
|
||||
<w>100</w>
|
||||
<h>100</h>
|
||||
</coordinates>
|
||||
<panel_attributes>Destination
|
||||
(Receiver)
|
||||
lt=.</panel_attributes>
|
||||
<additional_attributes/>
|
||||
</element>
|
||||
<element>
|
||||
<id>UMLUseCase</id>
|
||||
<coordinates>
|
||||
<x>310</x>
|
||||
<y>300</y>
|
||||
<w>100</w>
|
||||
<h>100</h>
|
||||
</coordinates>
|
||||
<panel_attributes>Amount.
|
||||
issuer
|
||||
lt=.</panel_attributes>
|
||||
<additional_attributes/>
|
||||
</element>
|
||||
<element>
|
||||
<id>UMLUseCase</id>
|
||||
<coordinates>
|
||||
<x>40</x>
|
||||
<y>40</y>
|
||||
<w>100</w>
|
||||
<h>100</h>
|
||||
</coordinates>
|
||||
<panel_attributes>Account
|
||||
(Sender)
|
||||
lt=.</panel_attributes>
|
||||
<additional_attributes/>
|
||||
</element>
|
||||
<element>
|
||||
<id>Relation</id>
|
||||
<coordinates>
|
||||
<x>250</x>
|
||||
<y>80</y>
|
||||
<w>180</w>
|
||||
<h>30</h>
|
||||
</coordinates>
|
||||
<panel_attributes>lw=2.5</panel_attributes>
|
||||
<additional_attributes>160.0;10.0;10.0;10.0</additional_attributes>
|
||||
</element>
|
||||
<element>
|
||||
<id>UMLUseCase</id>
|
||||
<coordinates>
|
||||
<x>410</x>
|
||||
<y>40</y>
|
||||
<w>100</w>
|
||||
<h>100</h>
|
||||
</coordinates>
|
||||
<panel_attributes>Destination
|
||||
(Receiver)
|
||||
lt=.</panel_attributes>
|
||||
<additional_attributes/>
|
||||
</element>
|
||||
<element>
|
||||
<id>Text</id>
|
||||
<coordinates>
|
||||
<x>140</x>
|
||||
<y>80</y>
|
||||
<w>30</w>
|
||||
<h>40</h>
|
||||
</coordinates>
|
||||
<panel_attributes>=</panel_attributes>
|
||||
<additional_attributes/>
|
||||
</element>
|
||||
<element>
|
||||
<id>UMLUseCase</id>
|
||||
<coordinates>
|
||||
<x>160</x>
|
||||
<y>40</y>
|
||||
<w>100</w>
|
||||
<h>100</h>
|
||||
</coordinates>
|
||||
<panel_attributes>Amount.
|
||||
issuer
|
||||
lt=.</panel_attributes>
|
||||
<additional_attributes/>
|
||||
</element>
|
||||
<element>
|
||||
<id>Relation</id>
|
||||
<coordinates>
|
||||
<x>400</x>
|
||||
<y>340</y>
|
||||
<w>190</w>
|
||||
<h>30</h>
|
||||
</coordinates>
|
||||
<panel_attributes>lt=.</panel_attributes>
|
||||
<additional_attributes>170.0;10.0;10.0;10.0</additional_attributes>
|
||||
</element>
|
||||
<element>
|
||||
<id>UMLUseCase</id>
|
||||
<coordinates>
|
||||
<x>50</x>
|
||||
<y>430</y>
|
||||
<w>100</w>
|
||||
<h>100</h>
|
||||
</coordinates>
|
||||
<panel_attributes>Account
|
||||
(Sender)
|
||||
lt=.</panel_attributes>
|
||||
<additional_attributes/>
|
||||
</element>
|
||||
<element>
|
||||
<id>Relation</id>
|
||||
<coordinates>
|
||||
<x>140</x>
|
||||
<y>470</y>
|
||||
<w>120</w>
|
||||
<h>30</h>
|
||||
</coordinates>
|
||||
<panel_attributes>lt=.</panel_attributes>
|
||||
<additional_attributes>100.0;10.0;10.0;10.0</additional_attributes>
|
||||
</element>
|
||||
<element>
|
||||
<id>UMLUseCase</id>
|
||||
<coordinates>
|
||||
<x>240</x>
|
||||
<y>430</y>
|
||||
<w>100</w>
|
||||
<h>100</h>
|
||||
</coordinates>
|
||||
<panel_attributes>SendMax.
|
||||
issuer
|
||||
currency
|
||||
lt=.</panel_attributes>
|
||||
<additional_attributes/>
|
||||
</element>
|
||||
<element>
|
||||
<id>Text</id>
|
||||
<coordinates>
|
||||
<x>340</x>
|
||||
<y>470</y>
|
||||
<w>30</w>
|
||||
<h>40</h>
|
||||
</coordinates>
|
||||
<panel_attributes>*=*</panel_attributes>
|
||||
<additional_attributes/>
|
||||
</element>
|
||||
<element>
|
||||
<id>UMLUseCase</id>
|
||||
<coordinates>
|
||||
<x>360</x>
|
||||
<y>430</y>
|
||||
<w>100</w>
|
||||
<h>100</h>
|
||||
</coordinates>
|
||||
<panel_attributes>Amount.
|
||||
issuer
|
||||
currency
|
||||
lt=.</panel_attributes>
|
||||
<additional_attributes/>
|
||||
</element>
|
||||
<element>
|
||||
<id>UMLUseCase</id>
|
||||
<coordinates>
|
||||
<x>570</x>
|
||||
<y>430</y>
|
||||
<w>100</w>
|
||||
<h>100</h>
|
||||
</coordinates>
|
||||
<panel_attributes>Destination
|
||||
(Receiver)
|
||||
lt=.</panel_attributes>
|
||||
<additional_attributes/>
|
||||
</element>
|
||||
<element>
|
||||
<id>Relation</id>
|
||||
<coordinates>
|
||||
<x>450</x>
|
||||
<y>470</y>
|
||||
<w>140</w>
|
||||
<h>30</h>
|
||||
</coordinates>
|
||||
<panel_attributes>lt=.</panel_attributes>
|
||||
<additional_attributes>120.0;10.0;10.0;10.0</additional_attributes>
|
||||
</element>
|
||||
<element>
|
||||
<id>Relation</id>
|
||||
<coordinates>
|
||||
<x>330</x>
|
||||
<y>600</y>
|
||||
<w>160</w>
|
||||
<h>30</h>
|
||||
</coordinates>
|
||||
<panel_attributes>lw=2.5</panel_attributes>
|
||||
<additional_attributes>140.0;10.0;10.0;10.0</additional_attributes>
|
||||
</element>
|
||||
<element>
|
||||
<id>UMLNote</id>
|
||||
<coordinates>
|
||||
<x>620</x>
|
||||
<y>130</y>
|
||||
<w>130</w>
|
||||
<h>70</h>
|
||||
</coordinates>
|
||||
<panel_attributes>Same currency:
|
||||
Direct trust line from sender to receiver</panel_attributes>
|
||||
<additional_attributes/>
|
||||
</element>
|
||||
<element>
|
||||
<id>Relation</id>
|
||||
<coordinates>
|
||||
<x>530</x>
|
||||
<y>40</y>
|
||||
<w>50</w>
|
||||
<h>240</h>
|
||||
</coordinates>
|
||||
<panel_attributes>lt=-</panel_attributes>
|
||||
<additional_attributes>10.0;220.0;30.0;220.0;30.0;10.0;10.0;10.0</additional_attributes>
|
||||
</element>
|
||||
<element>
|
||||
<id>Relation</id>
|
||||
<coordinates>
|
||||
<x>690</x>
|
||||
<y>300</y>
|
||||
<w>50</w>
|
||||
<h>240</h>
|
||||
</coordinates>
|
||||
<panel_attributes>lt=-</panel_attributes>
|
||||
<additional_attributes>10.0;220.0;30.0;220.0;30.0;10.0;10.0;10.0</additional_attributes>
|
||||
</element>
|
||||
<element>
|
||||
<id>UMLNote</id>
|
||||
<coordinates>
|
||||
<x>790</x>
|
||||
<y>560</y>
|
||||
<w>130</w>
|
||||
<h>90</h>
|
||||
</coordinates>
|
||||
<panel_attributes>Same currency:
|
||||
Rippling through two issuers - unlikely to work
|
||||
bg=yellow</panel_attributes>
|
||||
<additional_attributes/>
|
||||
</element>
|
||||
<element>
|
||||
<id>Relation</id>
|
||||
<coordinates>
|
||||
<x>730</x>
|
||||
<y>530</y>
|
||||
<w>50</w>
|
||||
<h>160</h>
|
||||
</coordinates>
|
||||
<panel_attributes>lt=-</panel_attributes>
|
||||
<additional_attributes>10.0;140.0;30.0;140.0;30.0;10.0;10.0;10.0</additional_attributes>
|
||||
</element>
|
||||
<element>
|
||||
<id>UMLNote</id>
|
||||
<coordinates>
|
||||
<x>760</x>
|
||||
<y>370</y>
|
||||
<w>130</w>
|
||||
<h>70</h>
|
||||
</coordinates>
|
||||
<panel_attributes>Same currency:
|
||||
Rippling through one issuer</panel_attributes>
|
||||
<additional_attributes/>
|
||||
</element>
|
||||
<element>
|
||||
<id>UMLUseCase</id>
|
||||
<coordinates>
|
||||
<x>660</x>
|
||||
<y>700</y>
|
||||
<w>100</w>
|
||||
<h>100</h>
|
||||
</coordinates>
|
||||
<panel_attributes>Destination
|
||||
(Receiver)
|
||||
lt=.</panel_attributes>
|
||||
<additional_attributes/>
|
||||
</element>
|
||||
<element>
|
||||
<id>Relation</id>
|
||||
<coordinates>
|
||||
<x>600</x>
|
||||
<y>740</y>
|
||||
<w>80</w>
|
||||
<h>30</h>
|
||||
</coordinates>
|
||||
<panel_attributes>lt=.</panel_attributes>
|
||||
<additional_attributes>10.0;10.0;60.0;10.0</additional_attributes>
|
||||
</element>
|
||||
<element>
|
||||
<id>UMLUseCase</id>
|
||||
<coordinates>
|
||||
<x>510</x>
|
||||
<y>700</y>
|
||||
<w>100</w>
|
||||
<h>100</h>
|
||||
</coordinates>
|
||||
<panel_attributes>Amount.
|
||||
issuer
|
||||
lt=.</panel_attributes>
|
||||
<additional_attributes/>
|
||||
</element>
|
||||
<element>
|
||||
<id>Relation</id>
|
||||
<coordinates>
|
||||
<x>290</x>
|
||||
<y>740</y>
|
||||
<w>80</w>
|
||||
<h>30</h>
|
||||
</coordinates>
|
||||
<panel_attributes>lw=2.5</panel_attributes>
|
||||
<additional_attributes>60.0;10.0;10.0;10.0</additional_attributes>
|
||||
</element>
|
||||
<element>
|
||||
<id>UMLUseCase</id>
|
||||
<coordinates>
|
||||
<x>200</x>
|
||||
<y>700</y>
|
||||
<w>100</w>
|
||||
<h>100</h>
|
||||
</coordinates>
|
||||
<panel_attributes>SendMax.
|
||||
issuer
|
||||
lt=.</panel_attributes>
|
||||
<additional_attributes/>
|
||||
</element>
|
||||
<element>
|
||||
<id>Relation</id>
|
||||
<coordinates>
|
||||
<x>140</x>
|
||||
<y>740</y>
|
||||
<w>80</w>
|
||||
<h>30</h>
|
||||
</coordinates>
|
||||
<panel_attributes>lt=.</panel_attributes>
|
||||
<additional_attributes>60.0;10.0;10.0;10.0</additional_attributes>
|
||||
</element>
|
||||
<element>
|
||||
<id>UMLUseCase</id>
|
||||
<coordinates>
|
||||
<x>50</x>
|
||||
<y>700</y>
|
||||
<w>100</w>
|
||||
<h>100</h>
|
||||
</coordinates>
|
||||
<panel_attributes>Account
|
||||
(Sender)
|
||||
lt=.</panel_attributes>
|
||||
<additional_attributes/>
|
||||
</element>
|
||||
<element>
|
||||
<id>UMLClass</id>
|
||||
<coordinates>
|
||||
<x>350</x>
|
||||
<y>700</y>
|
||||
<w>100</w>
|
||||
<h>100</h>
|
||||
</coordinates>
|
||||
<panel_attributes>Order Book
|
||||
--
|
||||
FOO
|
||||
(issuer)
|
||||
--
|
||||
BAR
|
||||
(issuer)
|
||||
lw=2.5</panel_attributes>
|
||||
<additional_attributes/>
|
||||
</element>
|
||||
<element>
|
||||
<id>Relation</id>
|
||||
<coordinates>
|
||||
<x>440</x>
|
||||
<y>740</y>
|
||||
<w>90</w>
|
||||
<h>30</h>
|
||||
</coordinates>
|
||||
<panel_attributes>lw=2.5</panel_attributes>
|
||||
<additional_attributes>70.0;10.0;10.0;10.0</additional_attributes>
|
||||
</element>
|
||||
<element>
|
||||
<id>UMLClass</id>
|
||||
<coordinates>
|
||||
<x>900</x>
|
||||
<y>50</y>
|
||||
<w>210</w>
|
||||
<h>210</h>
|
||||
</coordinates>
|
||||
<panel_attributes>Legend
|
||||
--
|
||||
</panel_attributes>
|
||||
<additional_attributes/>
|
||||
</element>
|
||||
<element>
|
||||
<id>Relation</id>
|
||||
<coordinates>
|
||||
<x>900</x>
|
||||
<y>90</y>
|
||||
<w>60</w>
|
||||
<h>30</h>
|
||||
</coordinates>
|
||||
<panel_attributes>lw=2.5</panel_attributes>
|
||||
<additional_attributes>40.0;10.0;10.0;10.0</additional_attributes>
|
||||
</element>
|
||||
<element>
|
||||
<id>Text</id>
|
||||
<coordinates>
|
||||
<x>950</x>
|
||||
<y>120</y>
|
||||
<w>140</w>
|
||||
<h>40</h>
|
||||
</coordinates>
|
||||
<panel_attributes>implied by transaction fields</panel_attributes>
|
||||
<additional_attributes/>
|
||||
</element>
|
||||
<element>
|
||||
<id>Relation</id>
|
||||
<coordinates>
|
||||
<x>900</x>
|
||||
<y>130</y>
|
||||
<w>60</w>
|
||||
<h>30</h>
|
||||
</coordinates>
|
||||
<panel_attributes>lt=.</panel_attributes>
|
||||
<additional_attributes>40.0;10.0;10.0;10.0</additional_attributes>
|
||||
</element>
|
||||
<element>
|
||||
<id>Text</id>
|
||||
<coordinates>
|
||||
<x>950</x>
|
||||
<y>80</y>
|
||||
<w>150</w>
|
||||
<h>40</h>
|
||||
</coordinates>
|
||||
<panel_attributes>completes the default path</panel_attributes>
|
||||
<additional_attributes/>
|
||||
</element>
|
||||
<element>
|
||||
<id>UMLUseCase</id>
|
||||
<coordinates>
|
||||
<x>910</x>
|
||||
<y>160</y>
|
||||
<w>30</w>
|
||||
<h>30</h>
|
||||
</coordinates>
|
||||
<panel_attributes/>
|
||||
<additional_attributes/>
|
||||
</element>
|
||||
<element>
|
||||
<id>UMLClass</id>
|
||||
<coordinates>
|
||||
<x>910</x>
|
||||
<y>210</y>
|
||||
<w>30</w>
|
||||
<h>30</h>
|
||||
</coordinates>
|
||||
<panel_attributes/>
|
||||
<additional_attributes/>
|
||||
</element>
|
||||
<element>
|
||||
<id>Text</id>
|
||||
<coordinates>
|
||||
<x>950</x>
|
||||
<y>160</y>
|
||||
<w>120</w>
|
||||
<h>40</h>
|
||||
</coordinates>
|
||||
<panel_attributes>path step - account</panel_attributes>
|
||||
<additional_attributes/>
|
||||
</element>
|
||||
<element>
|
||||
<id>Text</id>
|
||||
<coordinates>
|
||||
<x>950</x>
|
||||
<y>200</y>
|
||||
<w>130</w>
|
||||
<h>40</h>
|
||||
</coordinates>
|
||||
<panel_attributes>path step - order book</panel_attributes>
|
||||
<additional_attributes/>
|
||||
</element>
|
||||
<element>
|
||||
<id>Relation</id>
|
||||
<coordinates>
|
||||
<x>760</x>
|
||||
<y>680</y>
|
||||
<w>50</w>
|
||||
<h>160</h>
|
||||
</coordinates>
|
||||
<panel_attributes>lt=-</panel_attributes>
|
||||
<additional_attributes>10.0;140.0;30.0;140.0;30.0;10.0;10.0;10.0</additional_attributes>
|
||||
</element>
|
||||
<element>
|
||||
<id>UMLNote</id>
|
||||
<coordinates>
|
||||
<x>820</x>
|
||||
<y>720</y>
|
||||
<w>130</w>
|
||||
<h>90</h>
|
||||
</coordinates>
|
||||
<panel_attributes>Cross-currency:
|
||||
Default path automatically uses an order book</panel_attributes>
|
||||
<additional_attributes/>
|
||||
</element>
|
||||
</diagram>
|
||||
BIN
content/img-sources/funds_flow_diagram.odp
Normal file
61
content/img-sources/noripple-01.uxf
Normal file
@@ -0,0 +1,61 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<diagram program="umlet" version="13.2">
|
||||
<zoom_level>10</zoom_level>
|
||||
<element>
|
||||
<id>UMLUseCase</id>
|
||||
<coordinates>
|
||||
<x>420</x>
|
||||
<y>80</y>
|
||||
<w>60</w>
|
||||
<h>60</h>
|
||||
</coordinates>
|
||||
<panel_attributes>Bob</panel_attributes>
|
||||
<additional_attributes/>
|
||||
</element>
|
||||
<element>
|
||||
<id>UMLUseCase</id>
|
||||
<coordinates>
|
||||
<x>70</x>
|
||||
<y>80</y>
|
||||
<w>60</w>
|
||||
<h>60</h>
|
||||
</coordinates>
|
||||
<panel_attributes>Charlie</panel_attributes>
|
||||
<additional_attributes/>
|
||||
</element>
|
||||
<element>
|
||||
<id>UMLUseCase</id>
|
||||
<coordinates>
|
||||
<x>240</x>
|
||||
<y>80</y>
|
||||
<w>60</w>
|
||||
<h>60</h>
|
||||
</coordinates>
|
||||
<panel_attributes>Alice</panel_attributes>
|
||||
<additional_attributes/>
|
||||
</element>
|
||||
<element>
|
||||
<id>Relation</id>
|
||||
<coordinates>
|
||||
<x>290</x>
|
||||
<y>90</y>
|
||||
<w>150</w>
|
||||
<h>40</h>
|
||||
</coordinates>
|
||||
<panel_attributes>lt=<-
|
||||
$20</panel_attributes>
|
||||
<additional_attributes>10.0;20.0;130.0;20.0</additional_attributes>
|
||||
</element>
|
||||
<element>
|
||||
<id>Relation</id>
|
||||
<coordinates>
|
||||
<x>120</x>
|
||||
<y>90</y>
|
||||
<w>140</w>
|
||||
<h>40</h>
|
||||
</coordinates>
|
||||
<panel_attributes>lt=<-
|
||||
$10</panel_attributes>
|
||||
<additional_attributes>120.0;20.0;10.0;20.0</additional_attributes>
|
||||
</element>
|
||||
</diagram>
|
||||
61
content/img-sources/noripple-02.uxf
Normal file
@@ -0,0 +1,61 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<diagram program="umlet" version="13.2">
|
||||
<zoom_level>10</zoom_level>
|
||||
<element>
|
||||
<id>UMLUseCase</id>
|
||||
<coordinates>
|
||||
<x>420</x>
|
||||
<y>80</y>
|
||||
<w>60</w>
|
||||
<h>60</h>
|
||||
</coordinates>
|
||||
<panel_attributes>Bob</panel_attributes>
|
||||
<additional_attributes/>
|
||||
</element>
|
||||
<element>
|
||||
<id>UMLUseCase</id>
|
||||
<coordinates>
|
||||
<x>70</x>
|
||||
<y>80</y>
|
||||
<w>60</w>
|
||||
<h>60</h>
|
||||
</coordinates>
|
||||
<panel_attributes>Charlie</panel_attributes>
|
||||
<additional_attributes/>
|
||||
</element>
|
||||
<element>
|
||||
<id>UMLUseCase</id>
|
||||
<coordinates>
|
||||
<x>240</x>
|
||||
<y>80</y>
|
||||
<w>60</w>
|
||||
<h>60</h>
|
||||
</coordinates>
|
||||
<panel_attributes>Alice</panel_attributes>
|
||||
<additional_attributes/>
|
||||
</element>
|
||||
<element>
|
||||
<id>Relation</id>
|
||||
<coordinates>
|
||||
<x>290</x>
|
||||
<y>90</y>
|
||||
<w>150</w>
|
||||
<h>40</h>
|
||||
</coordinates>
|
||||
<panel_attributes>lt=->
|
||||
$17</panel_attributes>
|
||||
<additional_attributes>130.0;20.0;10.0;20.0</additional_attributes>
|
||||
</element>
|
||||
<element>
|
||||
<id>Relation</id>
|
||||
<coordinates>
|
||||
<x>120</x>
|
||||
<y>90</y>
|
||||
<w>140</w>
|
||||
<h>40</h>
|
||||
</coordinates>
|
||||
<panel_attributes>lt=->
|
||||
$13</panel_attributes>
|
||||
<additional_attributes>10.0;20.0;120.0;20.0</additional_attributes>
|
||||
</element>
|
||||
</diagram>
|
||||
109
content/img-sources/noripple-03.uxf
Normal file
@@ -0,0 +1,109 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<diagram program="umlet" version="13.1">
|
||||
<zoom_level>10</zoom_level>
|
||||
<element>
|
||||
<id>UMLUseCase</id>
|
||||
<coordinates>
|
||||
<x>450</x>
|
||||
<y>120</y>
|
||||
<w>60</w>
|
||||
<h>60</h>
|
||||
</coordinates>
|
||||
<panel_attributes>Emily</panel_attributes>
|
||||
<additional_attributes/>
|
||||
</element>
|
||||
<element>
|
||||
<id>UMLUseCase</id>
|
||||
<coordinates>
|
||||
<x>100</x>
|
||||
<y>120</y>
|
||||
<w>60</w>
|
||||
<h>60</h>
|
||||
</coordinates>
|
||||
<panel_attributes>Charlie</panel_attributes>
|
||||
<additional_attributes/>
|
||||
</element>
|
||||
<element>
|
||||
<id>UMLUseCase</id>
|
||||
<coordinates>
|
||||
<x>270</x>
|
||||
<y>110</y>
|
||||
<w>80</w>
|
||||
<h>80</h>
|
||||
</coordinates>
|
||||
<panel_attributes>Gateway
|
||||
A</panel_attributes>
|
||||
<additional_attributes/>
|
||||
</element>
|
||||
<element>
|
||||
<id>Relation</id>
|
||||
<coordinates>
|
||||
<x>340</x>
|
||||
<y>130</y>
|
||||
<w>130</w>
|
||||
<h>40</h>
|
||||
</coordinates>
|
||||
<panel_attributes>lt=<-
|
||||
$1</panel_attributes>
|
||||
<additional_attributes>10.0;20.0;110.0;20.0</additional_attributes>
|
||||
</element>
|
||||
<element>
|
||||
<id>Relation</id>
|
||||
<coordinates>
|
||||
<x>150</x>
|
||||
<y>130</y>
|
||||
<w>140</w>
|
||||
<h>40</h>
|
||||
</coordinates>
|
||||
<panel_attributes>lt=<-
|
||||
$10</panel_attributes>
|
||||
<additional_attributes>120.0;20.0;10.0;20.0</additional_attributes>
|
||||
</element>
|
||||
<element>
|
||||
<id>UMLUseCase</id>
|
||||
<coordinates>
|
||||
<x>620</x>
|
||||
<y>110</y>
|
||||
<w>80</w>
|
||||
<h>80</h>
|
||||
</coordinates>
|
||||
<panel_attributes>Gateway
|
||||
B</panel_attributes>
|
||||
<additional_attributes/>
|
||||
</element>
|
||||
<element>
|
||||
<id>Relation</id>
|
||||
<coordinates>
|
||||
<x>500</x>
|
||||
<y>130</y>
|
||||
<w>140</w>
|
||||
<h>40</h>
|
||||
</coordinates>
|
||||
<panel_attributes>lt=<-
|
||||
$100</panel_attributes>
|
||||
<additional_attributes>120.0;20.0;10.0;20.0</additional_attributes>
|
||||
</element>
|
||||
<element>
|
||||
<id>UMLUseCase</id>
|
||||
<coordinates>
|
||||
<x>810</x>
|
||||
<y>120</y>
|
||||
<w>60</w>
|
||||
<h>60</h>
|
||||
</coordinates>
|
||||
<panel_attributes>Daniel</panel_attributes>
|
||||
<additional_attributes/>
|
||||
</element>
|
||||
<element>
|
||||
<id>Relation</id>
|
||||
<coordinates>
|
||||
<x>690</x>
|
||||
<y>130</y>
|
||||
<w>140</w>
|
||||
<h>40</h>
|
||||
</coordinates>
|
||||
<panel_attributes>lt=<-
|
||||
$2</panel_attributes>
|
||||
<additional_attributes>10.0;20.0;120.0;20.0</additional_attributes>
|
||||
</element>
|
||||
</diagram>
|
||||
109
content/img-sources/noripple-04.uxf
Normal file
@@ -0,0 +1,109 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<diagram program="umlet" version="13.1">
|
||||
<zoom_level>10</zoom_level>
|
||||
<element>
|
||||
<id>UMLUseCase</id>
|
||||
<coordinates>
|
||||
<x>450</x>
|
||||
<y>120</y>
|
||||
<w>60</w>
|
||||
<h>60</h>
|
||||
</coordinates>
|
||||
<panel_attributes>Emily</panel_attributes>
|
||||
<additional_attributes/>
|
||||
</element>
|
||||
<element>
|
||||
<id>UMLUseCase</id>
|
||||
<coordinates>
|
||||
<x>100</x>
|
||||
<y>120</y>
|
||||
<w>60</w>
|
||||
<h>60</h>
|
||||
</coordinates>
|
||||
<panel_attributes>Charlie</panel_attributes>
|
||||
<additional_attributes/>
|
||||
</element>
|
||||
<element>
|
||||
<id>UMLUseCase</id>
|
||||
<coordinates>
|
||||
<x>270</x>
|
||||
<y>110</y>
|
||||
<w>80</w>
|
||||
<h>80</h>
|
||||
</coordinates>
|
||||
<panel_attributes>Gateway
|
||||
A</panel_attributes>
|
||||
<additional_attributes/>
|
||||
</element>
|
||||
<element>
|
||||
<id>Relation</id>
|
||||
<coordinates>
|
||||
<x>340</x>
|
||||
<y>130</y>
|
||||
<w>130</w>
|
||||
<h>40</h>
|
||||
</coordinates>
|
||||
<panel_attributes>lt=<-
|
||||
$11</panel_attributes>
|
||||
<additional_attributes>10.0;20.0;110.0;20.0</additional_attributes>
|
||||
</element>
|
||||
<element>
|
||||
<id>Relation</id>
|
||||
<coordinates>
|
||||
<x>150</x>
|
||||
<y>130</y>
|
||||
<w>140</w>
|
||||
<h>40</h>
|
||||
</coordinates>
|
||||
<panel_attributes>lt=<-
|
||||
$0</panel_attributes>
|
||||
<additional_attributes>120.0;20.0;10.0;20.0</additional_attributes>
|
||||
</element>
|
||||
<element>
|
||||
<id>UMLUseCase</id>
|
||||
<coordinates>
|
||||
<x>620</x>
|
||||
<y>110</y>
|
||||
<w>80</w>
|
||||
<h>80</h>
|
||||
</coordinates>
|
||||
<panel_attributes>Gateway
|
||||
B</panel_attributes>
|
||||
<additional_attributes/>
|
||||
</element>
|
||||
<element>
|
||||
<id>Relation</id>
|
||||
<coordinates>
|
||||
<x>500</x>
|
||||
<y>130</y>
|
||||
<w>140</w>
|
||||
<h>40</h>
|
||||
</coordinates>
|
||||
<panel_attributes>lt=<-
|
||||
$90</panel_attributes>
|
||||
<additional_attributes>120.0;20.0;10.0;20.0</additional_attributes>
|
||||
</element>
|
||||
<element>
|
||||
<id>UMLUseCase</id>
|
||||
<coordinates>
|
||||
<x>810</x>
|
||||
<y>120</y>
|
||||
<w>60</w>
|
||||
<h>60</h>
|
||||
</coordinates>
|
||||
<panel_attributes>Daniel</panel_attributes>
|
||||
<additional_attributes/>
|
||||
</element>
|
||||
<element>
|
||||
<id>Relation</id>
|
||||
<coordinates>
|
||||
<x>690</x>
|
||||
<y>130</y>
|
||||
<w>140</w>
|
||||
<h>40</h>
|
||||
</coordinates>
|
||||
<panel_attributes>lt=<-
|
||||
$12</panel_attributes>
|
||||
<additional_attributes>10.0;20.0;120.0;20.0</additional_attributes>
|
||||
</element>
|
||||
</diagram>
|
||||
111
content/img-sources/noripple-05.uxf
Normal file
@@ -0,0 +1,111 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<diagram program="umlet" version="13.1">
|
||||
<zoom_level>10</zoom_level>
|
||||
<element>
|
||||
<id>UMLUseCase</id>
|
||||
<coordinates>
|
||||
<x>450</x>
|
||||
<y>120</y>
|
||||
<w>60</w>
|
||||
<h>60</h>
|
||||
</coordinates>
|
||||
<panel_attributes>Emily</panel_attributes>
|
||||
<additional_attributes/>
|
||||
</element>
|
||||
<element>
|
||||
<id>UMLUseCase</id>
|
||||
<coordinates>
|
||||
<x>100</x>
|
||||
<y>120</y>
|
||||
<w>60</w>
|
||||
<h>60</h>
|
||||
</coordinates>
|
||||
<panel_attributes>Charlie</panel_attributes>
|
||||
<additional_attributes/>
|
||||
</element>
|
||||
<element>
|
||||
<id>UMLUseCase</id>
|
||||
<coordinates>
|
||||
<x>270</x>
|
||||
<y>110</y>
|
||||
<w>80</w>
|
||||
<h>80</h>
|
||||
</coordinates>
|
||||
<panel_attributes>Gateway
|
||||
A</panel_attributes>
|
||||
<additional_attributes/>
|
||||
</element>
|
||||
<element>
|
||||
<id>Relation</id>
|
||||
<coordinates>
|
||||
<x>340</x>
|
||||
<y>130</y>
|
||||
<w>130</w>
|
||||
<h>50</h>
|
||||
</coordinates>
|
||||
<panel_attributes>lt=<-
|
||||
$1
|
||||
NoRipple</panel_attributes>
|
||||
<additional_attributes>10.0;20.0;110.0;20.0</additional_attributes>
|
||||
</element>
|
||||
<element>
|
||||
<id>Relation</id>
|
||||
<coordinates>
|
||||
<x>150</x>
|
||||
<y>130</y>
|
||||
<w>140</w>
|
||||
<h>40</h>
|
||||
</coordinates>
|
||||
<panel_attributes>lt=<-
|
||||
$10</panel_attributes>
|
||||
<additional_attributes>120.0;20.0;10.0;20.0</additional_attributes>
|
||||
</element>
|
||||
<element>
|
||||
<id>UMLUseCase</id>
|
||||
<coordinates>
|
||||
<x>620</x>
|
||||
<y>110</y>
|
||||
<w>80</w>
|
||||
<h>80</h>
|
||||
</coordinates>
|
||||
<panel_attributes>Gateway
|
||||
B</panel_attributes>
|
||||
<additional_attributes/>
|
||||
</element>
|
||||
<element>
|
||||
<id>Relation</id>
|
||||
<coordinates>
|
||||
<x>500</x>
|
||||
<y>130</y>
|
||||
<w>140</w>
|
||||
<h>50</h>
|
||||
</coordinates>
|
||||
<panel_attributes>lt=<-
|
||||
$100
|
||||
NoRipple</panel_attributes>
|
||||
<additional_attributes>120.0;20.0;10.0;20.0</additional_attributes>
|
||||
</element>
|
||||
<element>
|
||||
<id>UMLUseCase</id>
|
||||
<coordinates>
|
||||
<x>810</x>
|
||||
<y>120</y>
|
||||
<w>60</w>
|
||||
<h>60</h>
|
||||
</coordinates>
|
||||
<panel_attributes>Daniel</panel_attributes>
|
||||
<additional_attributes/>
|
||||
</element>
|
||||
<element>
|
||||
<id>Relation</id>
|
||||
<coordinates>
|
||||
<x>690</x>
|
||||
<y>130</y>
|
||||
<w>140</w>
|
||||
<h>40</h>
|
||||
</coordinates>
|
||||
<panel_attributes>lt=<-
|
||||
$2</panel_attributes>
|
||||
<additional_attributes>10.0;20.0;120.0;20.0</additional_attributes>
|
||||
</element>
|
||||
</diagram>
|
||||
474
content/img-sources/noripple-06.uxf
Normal file
@@ -0,0 +1,474 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<diagram program="umlet" version="13.2">
|
||||
<zoom_level>10</zoom_level>
|
||||
<element>
|
||||
<id>UMLUseCase</id>
|
||||
<coordinates>
|
||||
<x>570</x>
|
||||
<y>70</y>
|
||||
<w>60</w>
|
||||
<h>60</h>
|
||||
</coordinates>
|
||||
<panel_attributes>Emily</panel_attributes>
|
||||
<additional_attributes/>
|
||||
</element>
|
||||
<element>
|
||||
<id>UMLUseCase</id>
|
||||
<coordinates>
|
||||
<x>220</x>
|
||||
<y>70</y>
|
||||
<w>60</w>
|
||||
<h>60</h>
|
||||
</coordinates>
|
||||
<panel_attributes>Charlie</panel_attributes>
|
||||
<additional_attributes/>
|
||||
</element>
|
||||
<element>
|
||||
<id>UMLUseCase</id>
|
||||
<coordinates>
|
||||
<x>390</x>
|
||||
<y>60</y>
|
||||
<w>80</w>
|
||||
<h>80</h>
|
||||
</coordinates>
|
||||
<panel_attributes>Gateway
|
||||
A</panel_attributes>
|
||||
<additional_attributes/>
|
||||
</element>
|
||||
<element>
|
||||
<id>Relation</id>
|
||||
<coordinates>
|
||||
<x>460</x>
|
||||
<y>80</y>
|
||||
<w>130</w>
|
||||
<h>50</h>
|
||||
</coordinates>
|
||||
<panel_attributes>lt=<-
|
||||
$1
|
||||
NoRipple</panel_attributes>
|
||||
<additional_attributes>10.0;20.0;110.0;20.0</additional_attributes>
|
||||
</element>
|
||||
<element>
|
||||
<id>Relation</id>
|
||||
<coordinates>
|
||||
<x>270</x>
|
||||
<y>80</y>
|
||||
<w>140</w>
|
||||
<h>40</h>
|
||||
</coordinates>
|
||||
<panel_attributes>lt=<-
|
||||
$10</panel_attributes>
|
||||
<additional_attributes>120.0;20.0;10.0;20.0</additional_attributes>
|
||||
</element>
|
||||
<element>
|
||||
<id>UMLUseCase</id>
|
||||
<coordinates>
|
||||
<x>740</x>
|
||||
<y>60</y>
|
||||
<w>80</w>
|
||||
<h>80</h>
|
||||
</coordinates>
|
||||
<panel_attributes>Gateway
|
||||
B</panel_attributes>
|
||||
<additional_attributes/>
|
||||
</element>
|
||||
<element>
|
||||
<id>Relation</id>
|
||||
<coordinates>
|
||||
<x>620</x>
|
||||
<y>80</y>
|
||||
<w>140</w>
|
||||
<h>50</h>
|
||||
</coordinates>
|
||||
<panel_attributes>lt=<-
|
||||
$100
|
||||
NoRipple .</panel_attributes>
|
||||
<additional_attributes>120.0;20.0;10.0;20.0</additional_attributes>
|
||||
</element>
|
||||
<element>
|
||||
<id>UMLUseCase</id>
|
||||
<coordinates>
|
||||
<x>930</x>
|
||||
<y>70</y>
|
||||
<w>60</w>
|
||||
<h>60</h>
|
||||
</coordinates>
|
||||
<panel_attributes>Daniel</panel_attributes>
|
||||
<additional_attributes/>
|
||||
</element>
|
||||
<element>
|
||||
<id>Relation</id>
|
||||
<coordinates>
|
||||
<x>810</x>
|
||||
<y>80</y>
|
||||
<w>140</w>
|
||||
<h>40</h>
|
||||
</coordinates>
|
||||
<panel_attributes>lt=<-
|
||||
$2</panel_attributes>
|
||||
<additional_attributes>10.0;20.0;120.0;20.0</additional_attributes>
|
||||
</element>
|
||||
<element>
|
||||
<id>UMLClass</id>
|
||||
<coordinates>
|
||||
<x>50</x>
|
||||
<y>80</y>
|
||||
<w>150</w>
|
||||
<h>40</h>
|
||||
</coordinates>
|
||||
<panel_attributes>Invalid path
|
||||
(Cannot ripple)
|
||||
bg=red
|
||||
</panel_attributes>
|
||||
<additional_attributes/>
|
||||
</element>
|
||||
<element>
|
||||
<id>UMLUseCase</id>
|
||||
<coordinates>
|
||||
<x>220</x>
|
||||
<y>190</y>
|
||||
<w>60</w>
|
||||
<h>60</h>
|
||||
</coordinates>
|
||||
<panel_attributes>Charlie</panel_attributes>
|
||||
<additional_attributes/>
|
||||
</element>
|
||||
<element>
|
||||
<id>Relation</id>
|
||||
<coordinates>
|
||||
<x>270</x>
|
||||
<y>200</y>
|
||||
<w>140</w>
|
||||
<h>40</h>
|
||||
</coordinates>
|
||||
<panel_attributes>lt=<-
|
||||
$10</panel_attributes>
|
||||
<additional_attributes>120.0;20.0;10.0;20.0</additional_attributes>
|
||||
</element>
|
||||
<element>
|
||||
<id>UMLUseCase</id>
|
||||
<coordinates>
|
||||
<x>390</x>
|
||||
<y>180</y>
|
||||
<w>80</w>
|
||||
<h>80</h>
|
||||
</coordinates>
|
||||
<panel_attributes>Gateway
|
||||
A</panel_attributes>
|
||||
<additional_attributes/>
|
||||
</element>
|
||||
<element>
|
||||
<id>Relation</id>
|
||||
<coordinates>
|
||||
<x>460</x>
|
||||
<y>200</y>
|
||||
<w>130</w>
|
||||
<h>50</h>
|
||||
</coordinates>
|
||||
<panel_attributes>lt=<-
|
||||
$1
|
||||
NoRipple</panel_attributes>
|
||||
<additional_attributes>10.0;20.0;110.0;20.0</additional_attributes>
|
||||
</element>
|
||||
<element>
|
||||
<id>UMLUseCase</id>
|
||||
<coordinates>
|
||||
<x>570</x>
|
||||
<y>190</y>
|
||||
<w>60</w>
|
||||
<h>60</h>
|
||||
</coordinates>
|
||||
<panel_attributes>Emily</panel_attributes>
|
||||
<additional_attributes/>
|
||||
</element>
|
||||
<element>
|
||||
<id>Relation</id>
|
||||
<coordinates>
|
||||
<x>620</x>
|
||||
<y>200</y>
|
||||
<w>140</w>
|
||||
<h>40</h>
|
||||
</coordinates>
|
||||
<panel_attributes>lt=<-
|
||||
$100</panel_attributes>
|
||||
<additional_attributes>120.0;20.0;10.0;20.0</additional_attributes>
|
||||
</element>
|
||||
<element>
|
||||
<id>UMLUseCase</id>
|
||||
<coordinates>
|
||||
<x>740</x>
|
||||
<y>180</y>
|
||||
<w>80</w>
|
||||
<h>80</h>
|
||||
</coordinates>
|
||||
<panel_attributes>Gateway
|
||||
B</panel_attributes>
|
||||
<additional_attributes/>
|
||||
</element>
|
||||
<element>
|
||||
<id>Relation</id>
|
||||
<coordinates>
|
||||
<x>810</x>
|
||||
<y>200</y>
|
||||
<w>140</w>
|
||||
<h>40</h>
|
||||
</coordinates>
|
||||
<panel_attributes>lt=<-
|
||||
$2</panel_attributes>
|
||||
<additional_attributes>10.0;20.0;120.0;20.0</additional_attributes>
|
||||
</element>
|
||||
<element>
|
||||
<id>UMLUseCase</id>
|
||||
<coordinates>
|
||||
<x>930</x>
|
||||
<y>190</y>
|
||||
<w>60</w>
|
||||
<h>60</h>
|
||||
</coordinates>
|
||||
<panel_attributes>Daniel</panel_attributes>
|
||||
<additional_attributes/>
|
||||
</element>
|
||||
<element>
|
||||
<id>UMLClass</id>
|
||||
<coordinates>
|
||||
<x>50</x>
|
||||
<y>190</y>
|
||||
<w>150</w>
|
||||
<h>50</h>
|
||||
</coordinates>
|
||||
<panel_attributes>Valid path
|
||||
(Rippling possible)
|
||||
bg=green
|
||||
</panel_attributes>
|
||||
<additional_attributes/>
|
||||
</element>
|
||||
<element>
|
||||
<id>UMLUseCase</id>
|
||||
<coordinates>
|
||||
<x>220</x>
|
||||
<y>320</y>
|
||||
<w>60</w>
|
||||
<h>60</h>
|
||||
</coordinates>
|
||||
<panel_attributes>Charlie</panel_attributes>
|
||||
<additional_attributes/>
|
||||
</element>
|
||||
<element>
|
||||
<id>Relation</id>
|
||||
<coordinates>
|
||||
<x>270</x>
|
||||
<y>330</y>
|
||||
<w>140</w>
|
||||
<h>40</h>
|
||||
</coordinates>
|
||||
<panel_attributes>lt=<-
|
||||
$10</panel_attributes>
|
||||
<additional_attributes>120.0;20.0;10.0;20.0</additional_attributes>
|
||||
</element>
|
||||
<element>
|
||||
<id>UMLUseCase</id>
|
||||
<coordinates>
|
||||
<x>390</x>
|
||||
<y>310</y>
|
||||
<w>80</w>
|
||||
<h>80</h>
|
||||
</coordinates>
|
||||
<panel_attributes>Gateway
|
||||
A</panel_attributes>
|
||||
<additional_attributes/>
|
||||
</element>
|
||||
<element>
|
||||
<id>Relation</id>
|
||||
<coordinates>
|
||||
<x>460</x>
|
||||
<y>330</y>
|
||||
<w>130</w>
|
||||
<h>40</h>
|
||||
</coordinates>
|
||||
<panel_attributes>lt=<-
|
||||
$1</panel_attributes>
|
||||
<additional_attributes>10.0;20.0;110.0;20.0</additional_attributes>
|
||||
</element>
|
||||
<element>
|
||||
<id>UMLUseCase</id>
|
||||
<coordinates>
|
||||
<x>570</x>
|
||||
<y>320</y>
|
||||
<w>60</w>
|
||||
<h>60</h>
|
||||
</coordinates>
|
||||
<panel_attributes>Emily</panel_attributes>
|
||||
<additional_attributes/>
|
||||
</element>
|
||||
<element>
|
||||
<id>Relation</id>
|
||||
<coordinates>
|
||||
<x>620</x>
|
||||
<y>330</y>
|
||||
<w>140</w>
|
||||
<h>40</h>
|
||||
</coordinates>
|
||||
<panel_attributes>lt=<-
|
||||
$100</panel_attributes>
|
||||
<additional_attributes>120.0;20.0;10.0;20.0</additional_attributes>
|
||||
</element>
|
||||
<element>
|
||||
<id>Relation</id>
|
||||
<coordinates>
|
||||
<x>810</x>
|
||||
<y>330</y>
|
||||
<w>140</w>
|
||||
<h>40</h>
|
||||
</coordinates>
|
||||
<panel_attributes>lt=<-
|
||||
$2</panel_attributes>
|
||||
<additional_attributes>10.0;20.0;120.0;20.0</additional_attributes>
|
||||
</element>
|
||||
<element>
|
||||
<id>UMLUseCase</id>
|
||||
<coordinates>
|
||||
<x>740</x>
|
||||
<y>310</y>
|
||||
<w>80</w>
|
||||
<h>80</h>
|
||||
</coordinates>
|
||||
<panel_attributes>Gateway
|
||||
B</panel_attributes>
|
||||
<additional_attributes/>
|
||||
</element>
|
||||
<element>
|
||||
<id>UMLUseCase</id>
|
||||
<coordinates>
|
||||
<x>930</x>
|
||||
<y>320</y>
|
||||
<w>60</w>
|
||||
<h>60</h>
|
||||
</coordinates>
|
||||
<panel_attributes>Daniel</panel_attributes>
|
||||
<additional_attributes/>
|
||||
</element>
|
||||
<element>
|
||||
<id>UMLUseCase</id>
|
||||
<coordinates>
|
||||
<x>220</x>
|
||||
<y>450</y>
|
||||
<w>60</w>
|
||||
<h>60</h>
|
||||
</coordinates>
|
||||
<panel_attributes>Charlie</panel_attributes>
|
||||
<additional_attributes/>
|
||||
</element>
|
||||
<element>
|
||||
<id>Relation</id>
|
||||
<coordinates>
|
||||
<x>270</x>
|
||||
<y>460</y>
|
||||
<w>140</w>
|
||||
<h>40</h>
|
||||
</coordinates>
|
||||
<panel_attributes>lt=<-
|
||||
$10</panel_attributes>
|
||||
<additional_attributes>120.0;20.0;10.0;20.0</additional_attributes>
|
||||
</element>
|
||||
<element>
|
||||
<id>UMLUseCase</id>
|
||||
<coordinates>
|
||||
<x>390</x>
|
||||
<y>440</y>
|
||||
<w>80</w>
|
||||
<h>80</h>
|
||||
</coordinates>
|
||||
<panel_attributes>Gateway
|
||||
A</panel_attributes>
|
||||
<additional_attributes/>
|
||||
</element>
|
||||
<element>
|
||||
<id>Relation</id>
|
||||
<coordinates>
|
||||
<x>460</x>
|
||||
<y>460</y>
|
||||
<w>130</w>
|
||||
<h>50</h>
|
||||
</coordinates>
|
||||
<panel_attributes>lt=<-
|
||||
$1
|
||||
NoRipple</panel_attributes>
|
||||
<additional_attributes>10.0;20.0;110.0;20.0</additional_attributes>
|
||||
</element>
|
||||
<element>
|
||||
<id>UMLUseCase</id>
|
||||
<coordinates>
|
||||
<x>570</x>
|
||||
<y>450</y>
|
||||
<w>60</w>
|
||||
<h>60</h>
|
||||
</coordinates>
|
||||
<panel_attributes>Emily</panel_attributes>
|
||||
<additional_attributes/>
|
||||
</element>
|
||||
<element>
|
||||
<id>Relation</id>
|
||||
<coordinates>
|
||||
<x>620</x>
|
||||
<y>460</y>
|
||||
<w>140</w>
|
||||
<h>50</h>
|
||||
</coordinates>
|
||||
<panel_attributes>lt=<-
|
||||
$100
|
||||
NoRipple</panel_attributes>
|
||||
<additional_attributes>10.0;20.0;120.0;20.0</additional_attributes>
|
||||
</element>
|
||||
<element>
|
||||
<id>UMLUseCase</id>
|
||||
<coordinates>
|
||||
<x>740</x>
|
||||
<y>450</y>
|
||||
<w>60</w>
|
||||
<h>60</h>
|
||||
</coordinates>
|
||||
<panel_attributes>Daniel</panel_attributes>
|
||||
<additional_attributes/>
|
||||
</element>
|
||||
<element>
|
||||
<id>UMLClass</id>
|
||||
<coordinates>
|
||||
<x>50</x>
|
||||
<y>330</y>
|
||||
<w>150</w>
|
||||
<h>50</h>
|
||||
</coordinates>
|
||||
<panel_attributes>Valid path
|
||||
(Rippling possible)
|
||||
bg=green
|
||||
</panel_attributes>
|
||||
<additional_attributes/>
|
||||
</element>
|
||||
<element>
|
||||
<id>UMLClass</id>
|
||||
<coordinates>
|
||||
<x>50</x>
|
||||
<y>460</y>
|
||||
<w>150</w>
|
||||
<h>50</h>
|
||||
</coordinates>
|
||||
<panel_attributes>Valid path
|
||||
(Rippling possible)
|
||||
bg=green
|
||||
</panel_attributes>
|
||||
<additional_attributes/>
|
||||
</element>
|
||||
<element>
|
||||
<id>UMLNote</id>
|
||||
<coordinates>
|
||||
<x>830</x>
|
||||
<y>430</y>
|
||||
<w>160</w>
|
||||
<h>110</h>
|
||||
</coordinates>
|
||||
<panel_attributes>This path is valid
|
||||
because Daniel, but not Emily, has set the NoRipple flag on the trust line between them
|
||||
bg=yellow</panel_attributes>
|
||||
<additional_attributes/>
|
||||
</element>
|
||||
</diagram>
|
||||
499
content/img-sources/paths.uxf
Normal file
@@ -0,0 +1,499 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<diagram program="umlet" version="13.3">
|
||||
<zoom_level>10</zoom_level>
|
||||
<element>
|
||||
<id>UMLUseCase</id>
|
||||
<coordinates>
|
||||
<x>620</x>
|
||||
<y>240</y>
|
||||
<w>100</w>
|
||||
<h>100</h>
|
||||
</coordinates>
|
||||
<panel_attributes>Account:
|
||||
--
|
||||
rf1BiGe...
|
||||
</panel_attributes>
|
||||
<additional_attributes/>
|
||||
</element>
|
||||
<element>
|
||||
<id>Relation</id>
|
||||
<coordinates>
|
||||
<x>570</x>
|
||||
<y>270</y>
|
||||
<w>70</w>
|
||||
<h>40</h>
|
||||
</coordinates>
|
||||
<panel_attributes/>
|
||||
<additional_attributes>50.0;20.0;10.0;20.0</additional_attributes>
|
||||
</element>
|
||||
<element>
|
||||
<id>UMLUseCase</id>
|
||||
<coordinates>
|
||||
<x>60</x>
|
||||
<y>240</y>
|
||||
<w>100</w>
|
||||
<h>100</h>
|
||||
</coordinates>
|
||||
<panel_attributes>Sender:
|
||||
r9cZA1m...
|
||||
Currency:
|
||||
USD
|
||||
lt=.</panel_attributes>
|
||||
<additional_attributes/>
|
||||
</element>
|
||||
<element>
|
||||
<id>UMLUseCase</id>
|
||||
<coordinates>
|
||||
<x>200</x>
|
||||
<y>240</y>
|
||||
<w>100</w>
|
||||
<h>100</h>
|
||||
</coordinates>
|
||||
<panel_attributes>Account:
|
||||
--
|
||||
rvYAfWj...
|
||||
</panel_attributes>
|
||||
<additional_attributes/>
|
||||
</element>
|
||||
<element>
|
||||
<id>UMLClass</id>
|
||||
<coordinates>
|
||||
<x>340</x>
|
||||
<y>240</y>
|
||||
<w>100</w>
|
||||
<h>100</h>
|
||||
</coordinates>
|
||||
<panel_attributes>Order Book:
|
||||
--
|
||||
USD
|
||||
rvYAfWj...
|
||||
--
|
||||
USD
|
||||
rMwjYe...</panel_attributes>
|
||||
<additional_attributes/>
|
||||
</element>
|
||||
<element>
|
||||
<id>UMLUseCase</id>
|
||||
<coordinates>
|
||||
<x>480</x>
|
||||
<y>240</y>
|
||||
<w>100</w>
|
||||
<h>100</h>
|
||||
</coordinates>
|
||||
<panel_attributes>Account:
|
||||
--
|
||||
rMwjYe...
|
||||
</panel_attributes>
|
||||
<additional_attributes/>
|
||||
</element>
|
||||
<element>
|
||||
<id>UMLUseCase</id>
|
||||
<coordinates>
|
||||
<x>760</x>
|
||||
<y>240</y>
|
||||
<w>100</w>
|
||||
<h>100</h>
|
||||
</coordinates>
|
||||
<panel_attributes>Receiver:
|
||||
ra5nK24...
|
||||
Currency:
|
||||
USD
|
||||
lt=.</panel_attributes>
|
||||
<additional_attributes/>
|
||||
</element>
|
||||
<element>
|
||||
<id>Relation</id>
|
||||
<coordinates>
|
||||
<x>430</x>
|
||||
<y>270</y>
|
||||
<w>70</w>
|
||||
<h>40</h>
|
||||
</coordinates>
|
||||
<panel_attributes/>
|
||||
<additional_attributes>50.0;20.0;10.0;20.0</additional_attributes>
|
||||
</element>
|
||||
<element>
|
||||
<id>Relation</id>
|
||||
<coordinates>
|
||||
<x>710</x>
|
||||
<y>280</y>
|
||||
<w>70</w>
|
||||
<h>30</h>
|
||||
</coordinates>
|
||||
<panel_attributes>lt=.</panel_attributes>
|
||||
<additional_attributes>50.0;10.0;10.0;10.0</additional_attributes>
|
||||
</element>
|
||||
<element>
|
||||
<id>Relation</id>
|
||||
<coordinates>
|
||||
<x>290</x>
|
||||
<y>270</y>
|
||||
<w>70</w>
|
||||
<h>40</h>
|
||||
</coordinates>
|
||||
<panel_attributes/>
|
||||
<additional_attributes>50.0;20.0;10.0;20.0</additional_attributes>
|
||||
</element>
|
||||
<element>
|
||||
<id>Relation</id>
|
||||
<coordinates>
|
||||
<x>150</x>
|
||||
<y>280</y>
|
||||
<w>70</w>
|
||||
<h>30</h>
|
||||
</coordinates>
|
||||
<panel_attributes>lt=.</panel_attributes>
|
||||
<additional_attributes>50.0;10.0;10.0;10.0</additional_attributes>
|
||||
</element>
|
||||
<element>
|
||||
<id>UMLNote</id>
|
||||
<coordinates>
|
||||
<x>920</x>
|
||||
<y>230</y>
|
||||
<w>140</w>
|
||||
<h>120</h>
|
||||
</coordinates>
|
||||
<panel_attributes>Same-currency paths can connect through rippling or through order books.
|
||||
bg=yellow</panel_attributes>
|
||||
<additional_attributes/>
|
||||
</element>
|
||||
<element>
|
||||
<id>UMLUseCase</id>
|
||||
<coordinates>
|
||||
<x>60</x>
|
||||
<y>410</y>
|
||||
<w>100</w>
|
||||
<h>100</h>
|
||||
</coordinates>
|
||||
<panel_attributes>Sender:
|
||||
r9cZA1m...
|
||||
Currency:
|
||||
USD
|
||||
lt=.</panel_attributes>
|
||||
<additional_attributes/>
|
||||
</element>
|
||||
<element>
|
||||
<id>Relation</id>
|
||||
<coordinates>
|
||||
<x>150</x>
|
||||
<y>450</y>
|
||||
<w>70</w>
|
||||
<h>30</h>
|
||||
</coordinates>
|
||||
<panel_attributes>lt=.</panel_attributes>
|
||||
<additional_attributes>50.0;10.0;10.0;10.0</additional_attributes>
|
||||
</element>
|
||||
<element>
|
||||
<id>UMLUseCase</id>
|
||||
<coordinates>
|
||||
<x>200</x>
|
||||
<y>410</y>
|
||||
<w>100</w>
|
||||
<h>100</h>
|
||||
</coordinates>
|
||||
<panel_attributes>Account:
|
||||
--
|
||||
rvYAfWj...
|
||||
</panel_attributes>
|
||||
<additional_attributes/>
|
||||
</element>
|
||||
<element>
|
||||
<id>Relation</id>
|
||||
<coordinates>
|
||||
<x>290</x>
|
||||
<y>440</y>
|
||||
<w>70</w>
|
||||
<h>40</h>
|
||||
</coordinates>
|
||||
<panel_attributes/>
|
||||
<additional_attributes>50.0;20.0;10.0;20.0</additional_attributes>
|
||||
</element>
|
||||
<element>
|
||||
<id>UMLClass</id>
|
||||
<coordinates>
|
||||
<x>340</x>
|
||||
<y>410</y>
|
||||
<w>100</w>
|
||||
<h>100</h>
|
||||
</coordinates>
|
||||
<panel_attributes>Order Book:
|
||||
--
|
||||
USD
|
||||
rvYAfWj...
|
||||
--
|
||||
XRP</panel_attributes>
|
||||
<additional_attributes/>
|
||||
</element>
|
||||
<element>
|
||||
<id>UMLUseCase</id>
|
||||
<coordinates>
|
||||
<x>620</x>
|
||||
<y>410</y>
|
||||
<w>100</w>
|
||||
<h>100</h>
|
||||
</coordinates>
|
||||
<panel_attributes>Account:
|
||||
--
|
||||
rMwjYe...
|
||||
</panel_attributes>
|
||||
<additional_attributes/>
|
||||
</element>
|
||||
<element>
|
||||
<id>Relation</id>
|
||||
<coordinates>
|
||||
<x>710</x>
|
||||
<y>440</y>
|
||||
<w>70</w>
|
||||
<h>40</h>
|
||||
</coordinates>
|
||||
<panel_attributes/>
|
||||
<additional_attributes>50.0;20.0;10.0;20.0</additional_attributes>
|
||||
</element>
|
||||
<element>
|
||||
<id>UMLUseCase</id>
|
||||
<coordinates>
|
||||
<x>760</x>
|
||||
<y>410</y>
|
||||
<w>100</w>
|
||||
<h>100</h>
|
||||
</coordinates>
|
||||
<panel_attributes>Account:
|
||||
--
|
||||
rf1BiGe...
|
||||
</panel_attributes>
|
||||
<additional_attributes/>
|
||||
</element>
|
||||
<element>
|
||||
<id>Relation</id>
|
||||
<coordinates>
|
||||
<x>850</x>
|
||||
<y>450</y>
|
||||
<w>70</w>
|
||||
<h>30</h>
|
||||
</coordinates>
|
||||
<panel_attributes>lt=.</panel_attributes>
|
||||
<additional_attributes>50.0;10.0;10.0;10.0</additional_attributes>
|
||||
</element>
|
||||
<element>
|
||||
<id>UMLUseCase</id>
|
||||
<coordinates>
|
||||
<x>900</x>
|
||||
<y>410</y>
|
||||
<w>100</w>
|
||||
<h>100</h>
|
||||
</coordinates>
|
||||
<panel_attributes>Receiver:
|
||||
ra5nK24...
|
||||
Currency:
|
||||
USD
|
||||
lt=.</panel_attributes>
|
||||
<additional_attributes/>
|
||||
</element>
|
||||
<element>
|
||||
<id>UMLClass</id>
|
||||
<coordinates>
|
||||
<x>480</x>
|
||||
<y>410</y>
|
||||
<w>100</w>
|
||||
<h>100</h>
|
||||
</coordinates>
|
||||
<panel_attributes>Order Book:
|
||||
--
|
||||
XRP
|
||||
--
|
||||
USD
|
||||
rMwjYe...</panel_attributes>
|
||||
<additional_attributes/>
|
||||
</element>
|
||||
<element>
|
||||
<id>Relation</id>
|
||||
<coordinates>
|
||||
<x>430</x>
|
||||
<y>440</y>
|
||||
<w>70</w>
|
||||
<h>40</h>
|
||||
</coordinates>
|
||||
<panel_attributes/>
|
||||
<additional_attributes>50.0;20.0;10.0;20.0</additional_attributes>
|
||||
</element>
|
||||
<element>
|
||||
<id>Relation</id>
|
||||
<coordinates>
|
||||
<x>570</x>
|
||||
<y>440</y>
|
||||
<w>70</w>
|
||||
<h>40</h>
|
||||
</coordinates>
|
||||
<panel_attributes/>
|
||||
<additional_attributes>50.0;20.0;10.0;20.0</additional_attributes>
|
||||
</element>
|
||||
<element>
|
||||
<id>UMLUseCase</id>
|
||||
<coordinates>
|
||||
<x>60</x>
|
||||
<y>60</y>
|
||||
<w>100</w>
|
||||
<h>100</h>
|
||||
</coordinates>
|
||||
<panel_attributes>Sender:
|
||||
r9cZA1m...
|
||||
Currency:
|
||||
USD
|
||||
lt=.</panel_attributes>
|
||||
<additional_attributes/>
|
||||
</element>
|
||||
<element>
|
||||
<id>UMLUseCase</id>
|
||||
<coordinates>
|
||||
<x>340</x>
|
||||
<y>60</y>
|
||||
<w>100</w>
|
||||
<h>100</h>
|
||||
</coordinates>
|
||||
<panel_attributes>Receiver:
|
||||
ra5nK24...
|
||||
Currency:
|
||||
USD
|
||||
lt=.</panel_attributes>
|
||||
<additional_attributes/>
|
||||
</element>
|
||||
<element>
|
||||
<id>UMLUseCase</id>
|
||||
<coordinates>
|
||||
<x>200</x>
|
||||
<y>60</y>
|
||||
<w>100</w>
|
||||
<h>100</h>
|
||||
</coordinates>
|
||||
<panel_attributes>Account:
|
||||
--
|
||||
rvYAfWj...
|
||||
</panel_attributes>
|
||||
<additional_attributes/>
|
||||
</element>
|
||||
<element>
|
||||
<id>Relation</id>
|
||||
<coordinates>
|
||||
<x>150</x>
|
||||
<y>100</y>
|
||||
<w>70</w>
|
||||
<h>30</h>
|
||||
</coordinates>
|
||||
<panel_attributes>lt=.</panel_attributes>
|
||||
<additional_attributes>50.0;10.0;10.0;10.0</additional_attributes>
|
||||
</element>
|
||||
<element>
|
||||
<id>Relation</id>
|
||||
<coordinates>
|
||||
<x>290</x>
|
||||
<y>90</y>
|
||||
<w>70</w>
|
||||
<h>40</h>
|
||||
</coordinates>
|
||||
<panel_attributes/>
|
||||
<additional_attributes>50.0;20.0;10.0;20.0</additional_attributes>
|
||||
</element>
|
||||
<element>
|
||||
<id>UMLNote</id>
|
||||
<coordinates>
|
||||
<x>500</x>
|
||||
<y>60</y>
|
||||
<w>130</w>
|
||||
<h>100</h>
|
||||
</coordinates>
|
||||
<panel_attributes>A simple path, which ripples through an issuer trusted by both parties
|
||||
bg=yellow</panel_attributes>
|
||||
<additional_attributes/>
|
||||
</element>
|
||||
<element>
|
||||
<id>UMLNote</id>
|
||||
<coordinates>
|
||||
<x>1050</x>
|
||||
<y>400</y>
|
||||
<w>140</w>
|
||||
<h>120</h>
|
||||
</coordinates>
|
||||
<panel_attributes>XRP can bridge two order books
|
||||
bg=yellow</panel_attributes>
|
||||
<additional_attributes/>
|
||||
</element>
|
||||
<element>
|
||||
<id>UMLClass</id>
|
||||
<coordinates>
|
||||
<x>1010</x>
|
||||
<y>30</y>
|
||||
<w>170</w>
|
||||
<h>180</h>
|
||||
</coordinates>
|
||||
<panel_attributes>Legend
|
||||
--</panel_attributes>
|
||||
<additional_attributes/>
|
||||
</element>
|
||||
<element>
|
||||
<id>Text</id>
|
||||
<coordinates>
|
||||
<x>1060</x>
|
||||
<y>60</y>
|
||||
<w>120</w>
|
||||
<h>40</h>
|
||||
</coordinates>
|
||||
<panel_attributes>Implied path step/link</panel_attributes>
|
||||
<additional_attributes/>
|
||||
</element>
|
||||
<element>
|
||||
<id>UMLUseCase</id>
|
||||
<coordinates>
|
||||
<x>1020</x>
|
||||
<y>120</y>
|
||||
<w>30</w>
|
||||
<h>30</h>
|
||||
</coordinates>
|
||||
<panel_attributes>
|
||||
</panel_attributes>
|
||||
<additional_attributes/>
|
||||
</element>
|
||||
<element>
|
||||
<id>Text</id>
|
||||
<coordinates>
|
||||
<x>1060</x>
|
||||
<y>110</y>
|
||||
<w>120</w>
|
||||
<h>50</h>
|
||||
</coordinates>
|
||||
<panel_attributes>Path step - account</panel_attributes>
|
||||
<additional_attributes/>
|
||||
</element>
|
||||
<element>
|
||||
<id>UMLClass</id>
|
||||
<coordinates>
|
||||
<x>1020</x>
|
||||
<y>170</y>
|
||||
<w>30</w>
|
||||
<h>30</h>
|
||||
</coordinates>
|
||||
<panel_attributes/>
|
||||
<additional_attributes/>
|
||||
</element>
|
||||
<element>
|
||||
<id>Text</id>
|
||||
<coordinates>
|
||||
<x>1060</x>
|
||||
<y>160</y>
|
||||
<w>120</w>
|
||||
<h>50</h>
|
||||
</coordinates>
|
||||
<panel_attributes>Path step - order book</panel_attributes>
|
||||
<additional_attributes/>
|
||||
</element>
|
||||
<element>
|
||||
<id>Relation</id>
|
||||
<coordinates>
|
||||
<x>1010</x>
|
||||
<y>70</y>
|
||||
<w>60</w>
|
||||
<h>30</h>
|
||||
</coordinates>
|
||||
<panel_attributes>lt=.</panel_attributes>
|
||||
<additional_attributes>40.0;10.0;10.0;10.0</additional_attributes>
|
||||
</element>
|
||||
</diagram>
|
||||
112
content/img-sources/quality.uxf
Normal file
@@ -0,0 +1,112 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<diagram program="umlet" version="13.2">
|
||||
<zoom_level>10</zoom_level>
|
||||
<element>
|
||||
<id>UMLUseCase</id>
|
||||
<coordinates>
|
||||
<x>600</x>
|
||||
<y>20</y>
|
||||
<w>80</w>
|
||||
<h>80</h>
|
||||
</coordinates>
|
||||
<panel_attributes>SnapSwap</panel_attributes>
|
||||
<additional_attributes/>
|
||||
</element>
|
||||
<element>
|
||||
<id>Relation</id>
|
||||
<coordinates>
|
||||
<x>470</x>
|
||||
<y>40</y>
|
||||
<w>150</w>
|
||||
<h>50</h>
|
||||
</coordinates>
|
||||
<panel_attributes>lt=<-
|
||||
qual_in=
|
||||
qual_out=</panel_attributes>
|
||||
<additional_attributes>130.0;20.0;10.0;20.0</additional_attributes>
|
||||
</element>
|
||||
<element>
|
||||
<id>UMLUseCase</id>
|
||||
<coordinates>
|
||||
<x>420</x>
|
||||
<y>30</y>
|
||||
<w>60</w>
|
||||
<h>60</h>
|
||||
</coordinates>
|
||||
<panel_attributes>Middle
|
||||
Man</panel_attributes>
|
||||
<additional_attributes/>
|
||||
</element>
|
||||
<element>
|
||||
<id>Relation</id>
|
||||
<coordinates>
|
||||
<x>310</x>
|
||||
<y>40</y>
|
||||
<w>130</w>
|
||||
<h>50</h>
|
||||
</coordinates>
|
||||
<panel_attributes>lt=<-
|
||||
qual_in=
|
||||
qual_out=</panel_attributes>
|
||||
<additional_attributes>10.0;20.0;110.0;20.0</additional_attributes>
|
||||
</element>
|
||||
<element>
|
||||
<id>UMLUseCase</id>
|
||||
<coordinates>
|
||||
<x>240</x>
|
||||
<y>20</y>
|
||||
<w>80</w>
|
||||
<h>80</h>
|
||||
</coordinates>
|
||||
<panel_attributes>Bitstamp</panel_attributes>
|
||||
<additional_attributes/>
|
||||
</element>
|
||||
<element>
|
||||
<id>Relation</id>
|
||||
<coordinates>
|
||||
<x>120</x>
|
||||
<y>40</y>
|
||||
<w>140</w>
|
||||
<h>40</h>
|
||||
</coordinates>
|
||||
<panel_attributes>lt=<-
|
||||
$10 USD</panel_attributes>
|
||||
<additional_attributes>120.0;20.0;10.0;20.0</additional_attributes>
|
||||
</element>
|
||||
<element>
|
||||
<id>UMLUseCase</id>
|
||||
<coordinates>
|
||||
<x>70</x>
|
||||
<y>30</y>
|
||||
<w>60</w>
|
||||
<h>60</h>
|
||||
</coordinates>
|
||||
<panel_attributes>Alice
|
||||
fontsize=11</panel_attributes>
|
||||
<additional_attributes/>
|
||||
</element>
|
||||
<element>
|
||||
<id>UMLUseCase</id>
|
||||
<coordinates>
|
||||
<x>760</x>
|
||||
<y>30</y>
|
||||
<w>60</w>
|
||||
<h>60</h>
|
||||
</coordinates>
|
||||
<panel_attributes>Bob
|
||||
fontsize=11</panel_attributes>
|
||||
<additional_attributes/>
|
||||
</element>
|
||||
<element>
|
||||
<id>Relation</id>
|
||||
<coordinates>
|
||||
<x>670</x>
|
||||
<y>40</y>
|
||||
<w>110</w>
|
||||
<h>40</h>
|
||||
</coordinates>
|
||||
<panel_attributes>lt=<-
|
||||
$0 USD</panel_attributes>
|
||||
<additional_attributes>10.0;20.0;90.0;20.0</additional_attributes>
|
||||
</element>
|
||||
</diagram>
|
||||
BIN
content/img-sources/transfer_fees.odp
Normal file
@@ -1,30 +0,0 @@
|
||||
# Introduction #
|
||||
|
||||
Ripple is a decentralized, peer-to-peer network for moving value using cryptographic technology. For more on the big picture, consult [ripple.com](https://ripple.com/) and check out [our blog](https://ripple.com/blog/).
|
||||
|
||||
# Ripple Client Applications #
|
||||
|
||||
The official web client for the Ripple Network is available at [https://rippletrade.com/](). There is also an official downloadable client at [http://download.ripple.com/]().
|
||||
|
||||
In order to activate your account, you must fund it with enough XRP to meet the account reserve (currently 20 XRP). You can do this in a few different ways:
|
||||
|
||||
* You can buy XRP with Bitcoins in the Ripple Trade client, under the [Fund](https://www.rippletrade.com/#/fund) tab.
|
||||
* You can have someone who is already on the network send a payment to your account's address.
|
||||
* Keep an eye out for promotions that give away free XRP to developers.
|
||||
|
||||
# Ripple APIs #
|
||||
|
||||
If you intend to act as a gateway, or if you are a developer with great ideas of how to use the Ripple Network, you will probably want to build a custom client application that you or your customers can use to send, receive, or observe funds on the Ripple Network.
|
||||
|
||||
Connecting to the Ripple Network generally means communicating with the Ripple Server software, [`rippled`](https://github.com/ripple/rippled) (pronounced "ripple-dee"). To get started, you can try running a few calls to retrieve information from public servers using the [Ripple API Tool](https://ripple.com/tools/api) or you try downloading and running your own instance of `rippled`.
|
||||
|
||||
If you are building your own client, you have several options of interfaces that you can use to interact with the Ripple Network:
|
||||
|
||||
| Tool | Summary | Interface | Abstraction Level | Pros | Cons |
|
||||
|------|---------|-----------------------|-------------------|------|------|
|
||||
| [gatewayd](https://github.com/ripple/gatewayd) | Skeleton for implementing gateway functionality as a Node.js application | HTTP interface | Very high abstraction | ✓ Most functionality needed to operate a gateway is already implemented | ✗ Only intended for gateways <br> ✗ Requires Node.js |
|
||||
| [Ripple-REST](?p=ripple-rest-api) | RESTful interface to `rippled` as a Node.js application | HTTP interface | High abstraction | ✓ Simple robust transaction submission <br> ✓ Broad HTTP-client support | ✗ Lacks access to a few features like viewing currency exchange offers <br> ✗ Requires Node.js |
|
||||
| [ripple-lib](https://github.com/ripple/ripple-lib) | Reference implementation for accessing the WebSocket API | Javascript library | Moderate abstraction | ✓ Simple robust transaction submission<br> ✓ Good balance of simplicity and power | ✗ Javascript only (Clients for other languages are in progress) |
|
||||
| [rippled WebSocket API](?p=web-sockets-api) | Powerful, asynchronous API built on the WebSocket protocol | [WebSocket](http://en.wikipedia.org/wiki/Websocket) interface | Low abstraction | ✓ Access to all Ripple functionality <br> ✓ Can be pushed ordered stream data | ✗ Fewer convenient abstractions <br> ✗ WebSocket clients are rare outside of Javascript |
|
||||
| [rippled JSON-RPC API](?p=web-sockets-api) <!--note: that's not a typo, the websocket and json-rpc docs are on the same page--> | Powerful, synchronous API built on the [JSON-RPC convention](http://json-rpc.org/) | HTTP interface | Low abstraction | ✓ Access to almost all Ripple functionality <br> ✓ Broad HTTP-client support | ✗ Fewer convenient abstractions <br> ✗ Callbacks may arrive out of order <br> ✗ No incremental pathfinding |
|
||||
|
||||