Compare commits
708 Commits
v2014-09-2
...
DataAPI-v2
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9e12ef118f | ||
|
|
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 | ||
|
|
00e9665730 | ||
|
|
48601d13d2 | ||
|
|
8a1f683b3b | ||
|
|
f97e8d9ef0 | ||
|
|
cbc956c015 | ||
|
|
9514c28dc6 | ||
|
|
dd7aefc4e5 | ||
|
|
9848b259f4 | ||
|
|
a74f1962e7 | ||
|
|
a03e374f43 | ||
|
|
c9feda2490 | ||
|
|
fa337c9615 | ||
|
|
71a2bd6587 | ||
|
|
51252e3e63 | ||
|
|
f9656c01b6 | ||
|
|
654b8d1bea | ||
|
|
34108d86c1 | ||
|
|
917c734527 | ||
|
|
9b73e2ff00 | ||
|
|
ce66bec2a0 | ||
|
|
cfd4831bca | ||
|
|
2284991d61 | ||
|
|
5102105c16 | ||
|
|
5092095399 | ||
|
|
d5ba2b6789 | ||
|
|
9b6e2261e8 | ||
|
|
96da39d641 | ||
|
|
4c48b4ce7b | ||
|
|
7cbd38c5a3 | ||
|
|
ef395720c4 | ||
|
|
a81abed071 | ||
|
|
12483174e3 | ||
|
|
efa7f97715 | ||
|
|
12f0470ff4 | ||
|
|
8c35fa9f32 | ||
|
|
559e40f6b5 | ||
|
|
1bf6d56252 | ||
|
|
831bbe7c6c | ||
|
|
59bdf67d68 | ||
|
|
3077fe89e0 | ||
|
|
79f59d7a13 | ||
|
|
d4fc93adf1 | ||
|
|
d51e34aaa1 | ||
|
|
fd44f61d54 | ||
|
|
af8e0502f2 | ||
|
|
2f69b95a44 | ||
|
|
2cb5936186 | ||
|
|
862481c155 | ||
|
|
0132fa6649 | ||
|
|
affef65e32 | ||
|
|
487bdec13a | ||
|
|
ea096e504c | ||
|
|
0b4ffd06c5 | ||
|
|
6b74c11eec | ||
|
|
69468e9dda | ||
|
|
9d494ba5d7 | ||
|
|
a59b1728e8 | ||
|
|
510ed630bf | ||
|
|
54855eb4d7 | ||
|
|
343916614b | ||
|
|
36fefffd1d | ||
|
|
3cf6f20bc7 | ||
|
|
580c935c27 | ||
|
|
cb50bce21d | ||
|
|
ae286f5d51 | ||
|
|
a4fa58c355 | ||
|
|
d2f82ee1f7 | ||
|
|
3d28b7819e | ||
|
|
da25e369e8 | ||
|
|
5ce709051f | ||
|
|
86a58d4033 | ||
|
|
a23c0927f5 | ||
|
|
3ec91ea30c | ||
|
|
1e6e1c40e3 | ||
|
|
7eb74525fd | ||
|
|
bbb45174b2 | ||
|
|
286c0684e3 | ||
|
|
50a5fc6ae1 | ||
|
|
daec5d512e | ||
|
|
a28840a1c1 | ||
|
|
3984e2bd98 | ||
|
|
7d91e17edc | ||
|
|
7c2d7b4b70 | ||
|
|
d6dd6bb0b8 | ||
|
|
fcbf127913 | ||
|
|
6659bed3f7 | ||
|
|
f29fad0aa7 | ||
|
|
a9fc508165 | ||
|
|
3011430b0d | ||
|
|
46f0a9c54e | ||
|
|
e0eb913ace | ||
|
|
d485f26978 | ||
|
|
94064e5880 | ||
|
|
040739bbe7 | ||
|
|
a6e2417617 | ||
|
|
e514f256b3 | ||
|
|
b77825dc3b | ||
|
|
b9d532b513 | ||
|
|
a9f4bd0d37 | ||
|
|
e343ac196c | ||
|
|
0c71b95c3c | ||
|
|
15644c8832 | ||
|
|
7aab439c38 | ||
|
|
69ff7d2b77 | ||
|
|
9256dc4f80 | ||
|
|
33eb4878ef | ||
|
|
17577597c1 | ||
|
|
74adf01e7d | ||
|
|
c91c184e9b | ||
|
|
b85f77d877 | ||
|
|
7e6569744b | ||
|
|
a3a2e7fc82 | ||
|
|
22c0767cd5 | ||
|
|
733ac991bd | ||
|
|
26ee51443c | ||
|
|
62f8e230bc | ||
|
|
406eb1a3ff | ||
|
|
cc6644c453 | ||
|
|
8b3d7ce4b3 | ||
|
|
c9e809ac3e | ||
|
|
3d5390b13a | ||
|
|
a4e8da9022 | ||
|
|
960b058296 | ||
|
|
1fbfedcc44 | ||
|
|
864a4666e1 | ||
|
|
c11fa144f8 | ||
|
|
89ee1a68ad | ||
|
|
bf0936ba3e | ||
|
|
6ea12180ff | ||
|
|
80dd20fbc2 | ||
|
|
e9f94d5b29 | ||
|
|
2b973a8021 | ||
|
|
5ab734aa76 | ||
|
|
253474ed78 | ||
|
|
a1deb58f82 | ||
|
|
d22b8f8e62 | ||
|
|
d5b60a5917 | ||
|
|
466e93eab0 | ||
|
|
22f2ef8ad7 | ||
|
|
8fc64a8aad | ||
|
|
bcf3b05fc8 | ||
|
|
2d31a001a6 | ||
|
|
7685f0eec1 | ||
|
|
59e7877856 | ||
|
|
e9ccd7e300 | ||
|
|
c9395695ed | ||
|
|
2e985d7525 | ||
|
|
3a07fdac5e | ||
|
|
d722d1f8ae | ||
|
|
17f0285881 | ||
|
|
cb2ae4e0c7 | ||
|
|
4940018e70 | ||
|
|
ad335133a2 | ||
|
|
a5b9750006 | ||
|
|
9da64424f6 | ||
|
|
290cf49df1 | ||
|
|
467ad01556 | ||
|
|
315352a1fc | ||
|
|
5770e7d3e2 | ||
|
|
1f2be06eef | ||
|
|
9c64b787ff | ||
|
|
07fd5ce872 | ||
|
|
af8f2ed50e | ||
|
|
6b75c9ee83 | ||
|
|
0a8bdf387e | ||
|
|
092d715bfa | ||
|
|
63246c37c2 | ||
|
|
e1fc112df1 | ||
|
|
eb33c7e446 | ||
|
|
5bca4a1319 | ||
|
|
07a92022b3 | ||
|
|
ec74ec90cb | ||
|
|
2aa95a4023 | ||
|
|
fd0354f957 | ||
|
|
5e229a1138 | ||
|
|
723e70a5ea | ||
|
|
44c9340902 | ||
|
|
e4374c3214 | ||
|
|
844640f141 | ||
|
|
8fe388de6f | ||
|
|
7228faf419 | ||
|
|
dff1e04c18 | ||
|
|
c43c2f0915 | ||
|
|
d99b264cff | ||
|
|
e6f753aa72 | ||
|
|
b909e200fa | ||
|
|
10fa680688 | ||
|
|
b689061d89 | ||
|
|
8303508670 | ||
|
|
c7c7f30845 | ||
|
|
96164d68e2 | ||
|
|
3abd182ea8 | ||
|
|
a4a9b734f8 | ||
|
|
39f4a1cb08 | ||
|
|
7582184ea5 | ||
|
|
4e6adb1f34 | ||
|
|
71932be386 | ||
|
|
d79b84ed43 | ||
|
|
1aebd976ea | ||
|
|
2430809517 | ||
|
|
daf5bca353 | ||
|
|
bd99c824c7 | ||
|
|
e0f404ecd7 | ||
|
|
42d9aee9d0 | ||
|
|
c3ac69f2a3 | ||
|
|
28d13c4459 | ||
|
|
63c3feba9e |
2
.gitignore
vendored
@@ -1,3 +1,5 @@
|
||||
/node_modules/
|
||||
*~
|
||||
.DS_Store
|
||||
content/code_samples/*/node_modules/
|
||||
__pycache__
|
||||
|
||||
24
LICENSE
@@ -1,9 +1,31 @@
|
||||
The Ripple Dev Portal and all its original contents are provided under the MIT License. Additional libraries and resources used by the Ripple Dev Portal are subject to their own licenses, as described below.
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c)
|
||||
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/
|
||||
|
||||
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:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
-----
|
||||
|
||||
Fonts included in this site use the following licenses:
|
||||
|
||||
Montserrat: Copyright (c) 2011-2012, Julieta Ulanovsky (julieta.ulanovsky@gmail.com), with Reserved Font Names 'Montserrat'
|
||||
Used under the SIL Open Font License, 1.1
|
||||
http://scripts.sil.org/OFL
|
||||
|
||||
Open Sans: Digitized data copyright © 2010-2011, Google Corporation.
|
||||
Used under the Apache License, version 2.0
|
||||
http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
|
||||
Font Awesome by Dave Gandy - http://fontawesome.io
|
||||
Font used under the SIL Open Font License, 1.1
|
||||
http://scripts.sil.org/OFL
|
||||
Code licensed under the MIT License
|
||||
|
||||
|
||||
87
README.md
@@ -1,12 +1,89 @@
|
||||
ripple-dev-portal
|
||||
=================
|
||||
|
||||
This Ripple Developer Portal is focused solely on documentation for the [`ripple-rest`](https://github.com/ripple/ripple-rest) API. The developer portal is a static site leveraging a fork of [`flatdoc`](https://github.com/rstacruz/flatdoc).
|
||||
|
||||
The documentation is stored in the "API.md" file in the root of the `ripple-dev-portal` repository. Versioning for the documentation will match the tagged release version for `ripple-rest`.
|
||||
|
||||
### The ripple-dev-portal is currently hosted at https://dev.ripple.com ###
|
||||
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.
|
||||
|
||||
|
||||
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,9 +53,9 @@ h2 {
|
||||
border-spacing:24px 0;
|
||||
width:96%;
|
||||
height: 100%;
|
||||
margin-top: 30px;
|
||||
}
|
||||
#io_wrapper > div {
|
||||
display:table-row;
|
||||
width:100%;
|
||||
margin:0;
|
||||
padding:0;
|
||||
@@ -98,7 +71,7 @@ h2 {
|
||||
#output {
|
||||
width: 60%;
|
||||
}
|
||||
p, h3 {
|
||||
h3 {
|
||||
margin:16px 0;
|
||||
font-family:'open sans';
|
||||
font-weight:300;
|
||||
@@ -150,37 +123,7 @@ p, 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;
|
||||
}
|
||||
#request_button {
|
||||
background:#3a87ad;
|
||||
}
|
||||
#request_button.depressed {
|
||||
background:#295F7A;
|
||||
margin-top: 5px;
|
||||
}
|
||||
#sign_button {
|
||||
display:none;
|
||||
@@ -207,9 +150,8 @@ p, h3 {
|
||||
}
|
||||
#online_state {
|
||||
position:absolute;
|
||||
top:100px;
|
||||
/* right:20px; */
|
||||
line-height:50px;
|
||||
top:10px;
|
||||
line-height:30px;
|
||||
font-size:14px;
|
||||
font-style:italic;
|
||||
}
|
||||
@@ -280,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;
|
||||
@@ -410,7 +339,8 @@ span.cm-atom {
|
||||
#rest_url_wrapper {
|
||||
font-family: sans-serif;
|
||||
display: inline-block;
|
||||
margin-bottom: -11px;
|
||||
text-indent: -2em;
|
||||
padding-left: 2.5em;
|
||||
}
|
||||
|
||||
#rest_url {
|
||||
@@ -418,4 +348,38 @@ span.cm-atom {
|
||||
border: 0;
|
||||
background: none;
|
||||
font-size:13px;
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
#rest_url .editable {
|
||||
font-weight: bold;
|
||||
font-family:'inconsolata',monospace;
|
||||
border-width: 0 0px 1px 0;
|
||||
border-style: dotted;
|
||||
border-color: #aaa;
|
||||
min-width: 5em;
|
||||
background: none;
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
#rest_url .non_editable {
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
#rest_url_wrapper p {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
#rest_url div {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
#rest_url input {
|
||||
margin: 0 !important;
|
||||
}
|
||||
|
||||
#rest_url div label,
|
||||
#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
BIN
assets/font/OpenSans-Bold-webfont.woff
Normal file
BIN
assets/font/OpenSans-Regular-webfont.woff
Normal 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,14 +138,16 @@
|
||||
accounts: [ ],
|
||||
streams: [ 'server', 'ledger' ],
|
||||
_description: 'Start receiving selected streams from the server.',
|
||||
_link: 'rippled-apis.html#subscribe'
|
||||
_link: DOC_BASE + '#subscribe',
|
||||
_stream: true
|
||||
});
|
||||
|
||||
Request('unsubscribe', {
|
||||
accounts: [ ],
|
||||
streams: [ 'server', 'ledger' ],
|
||||
_description: 'Stop receiving selected streams from the server.',
|
||||
_link: 'rippled-apis.html#unsubscribe'
|
||||
_link: DOC_BASE + '#unsubscribe',
|
||||
_stream: true
|
||||
});
|
||||
|
||||
/* ---- ---- */
|
||||
@@ -132,7 +160,7 @@
|
||||
transactions: true,
|
||||
accounts: true,
|
||||
_description: 'Returns ledger information.',
|
||||
_link: 'rippled-apis.html#ledger'
|
||||
_link: DOC_BASE + '#ledger'
|
||||
});
|
||||
|
||||
Request('ledger_entry', {
|
||||
@@ -140,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', {
|
||||
@@ -184,13 +212,30 @@
|
||||
ledger_index_max: -1,
|
||||
binary: false,
|
||||
count: false,
|
||||
descending: false,
|
||||
offset: 0,
|
||||
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,39 +244,50 @@
|
||||
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', {
|
||||
ledger_hash: void(0),
|
||||
ledger_index: void(0),
|
||||
taker: sample_address,
|
||||
taker_gets: ripple.Amount.from_json('1/EUR/rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B').to_json(),
|
||||
taker_pays: ripple.Amount.from_json('1/USD/rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B').to_json(),
|
||||
_description: 'Returns the offers for an order book as one or more pages.',
|
||||
_link: 'rippled-apis.html#book-offers'
|
||||
taker_gets: {
|
||||
currency: 'XRP'
|
||||
},
|
||||
taker_pays: {
|
||||
currency: 'USD',
|
||||
issuer: 'rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B'
|
||||
},
|
||||
limit: 10,
|
||||
_description: 'Returns a snapshot of the offers for an order book.',
|
||||
_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(),
|
||||
_description: 'Find or modify a payment pathway between specified accounts.',
|
||||
_link: 'rippled-apis.html#path-find'
|
||||
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: DOC_BASE + '#path-find',
|
||||
_stream: true
|
||||
});
|
||||
|
||||
Request('ripple_path_find', {
|
||||
@@ -239,24 +295,29 @@
|
||||
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(),
|
||||
_description: 'Find a path and estimated costs. For non-interactive use, such as automated payment sending from business integrations, ripple_path_find gives you single response that you can use immediately. However, for uses that need updated paths as new ledgers close, repeated calls becomes expensive. In those cases, when possible, use the RPC path_find in place of this API.',
|
||||
_link: 'rippled-apis.html#ripple-path-find'
|
||||
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: 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. <span class="btn-danger">Please, only use test accounts here.</span>',
|
||||
_link: 'rippled-apis.html#submit'
|
||||
_description: 'Submits a transaction to the network.',
|
||||
_link: DOC_BASE + '#submit',
|
||||
_takes_secret: true
|
||||
});
|
||||
|
||||
Request('sign', {
|
||||
@@ -270,10 +331,12 @@
|
||||
"issuer" : "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn"
|
||||
}
|
||||
},
|
||||
secret : "sssssssssssssssssssssssssssss",
|
||||
secret : "sn3nxiW7v8KXzPzAqzyHXbSSKNuN9",
|
||||
offline: false,
|
||||
_description: 'Sends a transaction to be signed by the server. <span class="btn-danger">Please, only use test accounts here.</span>',
|
||||
_link: 'rippled-apis.html#sign'
|
||||
fee_mult_max: 1000,
|
||||
_description: 'Sends a transaction to be signed by the server.',
|
||||
_link: DOC_BASE + '#sign',
|
||||
_takes_secret: true
|
||||
});
|
||||
|
||||
/* ---- ---- ---- ---- ---- */
|
||||
@@ -316,7 +379,8 @@
|
||||
|
||||
if (command._description) {
|
||||
//$(description).html(command._description).show();
|
||||
$(description).html($('<a>').attr('href', command._link).html(command._description));
|
||||
$(description).html(command._description);
|
||||
$(description).append(" <a class='button btn btn-primary' href='"+command._link+"'>Read more</a>");
|
||||
} else {
|
||||
$(description).hide();
|
||||
}
|
||||
@@ -390,6 +454,18 @@
|
||||
// return;
|
||||
// }
|
||||
|
||||
if (selected_request._takes_secret === true) {
|
||||
$("#test_warning").show();
|
||||
} else {
|
||||
$("#test_warning").hide();
|
||||
}
|
||||
|
||||
if (selected_request._stream === true) {
|
||||
$("#stream_output").show();
|
||||
} else {
|
||||
$("#stream_output").hide();
|
||||
}
|
||||
|
||||
if (!remote._connected) {
|
||||
remote.once('connected', function() {
|
||||
select_request(request);
|
||||
@@ -607,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);
|
||||
}
|
||||
});
|
||||
1
assets/js/jquery.autosize.input.min.js
vendored
Normal file
@@ -0,0 +1 @@
|
||||
var Plugins;(function(n){var t=function(){function n(n){typeof n=="undefined"&&(n=30);this.space=n}return n}(),i;n.AutosizeInputOptions=t;i=function(){function n(t,i){var r=this;this._input=$(t);this._options=$.extend({},n.getDefaultOptions(),i);this._mirror=$('<span style="position:absolute; top:-999px; left:0; white-space:pre;"/>');$.each(["fontFamily","fontSize","fontWeight","fontStyle","letterSpacing","textTransform","wordSpacing","textIndent"],function(n,t){r._mirror[0].style[t]=r._input.css(t)});$("body").append(this._mirror);this._input.on("keydown keyup input propertychange change",function(){r.update()});(function(){r.update()})()}return n.prototype.getOptions=function(){return this._options},n.prototype.update=function(){var n=this._input.val()||"",t;n!==this._mirror.text()&&(this._mirror.text(n),t=this._mirror.width()+this._options.space,this._input.width(t))},n.getDefaultOptions=function(){return this._defaultOptions},n.getInstanceKey=function(){return"autosizeInputInstance"},n._defaultOptions=new t,n}();n.AutosizeInput=i,function(t){var i="autosize-input",r=["text","password","search","url","tel","email","number"];t.fn.autosizeInput=function(u){return this.each(function(){if(this.tagName=="INPUT"&&t.inArray(this.type,r)>-1){var f=t(this);f.data(n.AutosizeInput.getInstanceKey())||(u==undefined&&(u=f.data(i)),f.data(n.AutosizeInput.getInstanceKey(),new n.AutosizeInput(this,u)))}})};t(function(){t("input[data-"+i+"]").autosizeInput()})}(jQuery)})(Plugins||(Plugins={}))
|
||||
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,10 +1,9 @@
|
||||
// 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) {
|
||||
@@ -13,21 +12,19 @@ jQuery.fn.multicode_tabs = function() {
|
||||
// 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) {
|
||||
cb_area.children('pre').each(function(index2,el2) {
|
||||
var linkid = 'code-'+index+'-'+index2;
|
||||
// $(el2).attr('id', linkid);
|
||||
$(el2).wrap("<div id='"+linkid+"'><pre>");
|
||||
$(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>");
|
||||
});
|
||||
|
||||
//use the ems to fill in the tab headers for each block
|
||||
$(el).children('em').each(function(index2, el2) {
|
||||
$(el).find('em').each(function(index2, el2) {
|
||||
$('ul li:eq('+index2+') a', cb_area).text($(el2).text());
|
||||
});
|
||||
});
|
||||
$('.multicode em').remove();
|
||||
$('.multicode p').hide();
|
||||
$('.multicode .code_sample').css("position","static");
|
||||
|
||||
$('.multicode').minitabs();
|
||||
}
|
||||
12
assets/js/ripple-0.11.0-min.js
vendored
Normal file
4
assets/vendor/codemirror.min.js
vendored
Normal file
1
assets/vendor/docco.min.css
vendored
Normal file
@@ -0,0 +1 @@
|
||||
.hljs{display:block;overflow-x:auto;padding:0.5em;color:#000;background:#f8f8ff;-webkit-text-size-adjust:none}.hljs-comment,.hljs-template_comment,.diff .hljs-header,.hljs-javadoc{color:#408080;font-style:italic}.hljs-keyword,.assignment,.hljs-literal,.css .rule .hljs-keyword,.hljs-winutils,.javascript .hljs-title,.lisp .hljs-title,.hljs-subst{color:#954121}.hljs-number,.hljs-hexcolor{color:#40a070}.hljs-string,.hljs-tag .hljs-value,.hljs-phpdoc,.hljs-dartdoc,.tex .hljs-formula{color:#219161}.hljs-title,.hljs-id{color:#19469d}.hljs-params{color:#00f}.javascript .hljs-title,.lisp .hljs-title,.hljs-subst{font-weight:normal}.hljs-class .hljs-title,.haskell .hljs-label,.tex .hljs-command{color:#458;font-weight:bold}.hljs-tag,.hljs-tag .hljs-title,.hljs-rules .hljs-property,.django .hljs-tag .hljs-keyword{color:#000080;font-weight:normal}.hljs-attribute,.hljs-variable,.instancevar,.lisp .hljs-body{color:#008080}.hljs-regexp{color:#b68}.hljs-class{color:#458;font-weight:bold}.hljs-symbol,.ruby .hljs-symbol .hljs-string,.ruby .hljs-symbol .hljs-keyword,.ruby .hljs-symbol .keymethods,.lisp .hljs-keyword,.tex .hljs-special,.input_number{color:#990073}.builtin,.constructor,.hljs-built_in,.lisp .hljs-title{color:#0086b3}.hljs-preprocessor,.hljs-pragma,.hljs-pi,.hljs-doctype,.hljs-shebang,.hljs-cdata{color:#999;font-weight:bold}.hljs-deletion{background:#fdd}.hljs-addition{background:#dfd}.diff .hljs-change{background:#0086b3}.hljs-chunk{color:#aaa}.tex .hljs-formula{opacity:0.5}
|
||||
4
assets/vendor/font-awesome.min.css
vendored
Normal file
2
assets/vendor/highlight.min.js
vendored
Normal file
4
assets/vendor/jquery-1.11.1.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,207 +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>
|
||||
-->
|
||||
<!-- Temporary shims until I modify the css directly -->
|
||||
<link type='text/css' rel='stylesheet' href='css/mod.css' />
|
||||
<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="active"><a href="/">Resources</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/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.
|
||||
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
3937
content/reference-data-api.md
Normal file
474
content/reference-ledger-format.md
Normal file
@@ -0,0 +1,474 @@
|
||||
# The Ledger #
|
||||
|
||||
The point of the Ripple software is to maintain a shared, global ledger that is open to all, so that individual participants can trust the integrity of the ledger without having to trust any single institution to manage it. The `rippled` server software accomplishes this by maintaining a ledger database that can only be updated according to very specific rules. Each instance of `rippled` maintains a full copy of the ledger, and the peer-to-peer network of `rippled` servers distributes candidate transactions among themselves. The consensus process determines which transactions get applied to each new version of the ledger. See also: [The Consensus Process](https://ripple.com/knowledge_center/the-ripple-ledger-consensus-process/).
|
||||
|
||||

|
||||
|
||||
The shared global ledger is actually a series of individual ledgers, or ledger versions, which `rippled` keeps in its internal database. Every ledger version has a [ledger index](#ledger-index) which identifies the order in which ledgers occur. Each closed ledger version also has an identifying hash value, which uniquely identifies the contents of that ledger. At any given time, a `rippled` instance has an in-progress "current" open ledger, plus some number of closed ledgers that have not yet been approved by consensus, and any number of historical ledgers that have been validated by consensus. Only the validated ledgers are certain to be accurate and immutable.
|
||||
|
||||
A single ledger version consists of several components:
|
||||
|
||||

|
||||
|
||||
* A **header** - The [ledger index](#ledger-index), hashes of its other contents, and other metadata.
|
||||
* A **transaction tree** - The [transactions](reference-transaction-format.html) that were applied to the previous ledger to make this one. Transactions are the _only_ way to modify the ledger.
|
||||
* A **state tree** - All the [ledger nodes](#ledger-node-types) that contain the settings, balances, and objects in the ledger as of this version.
|
||||
|
||||
|
||||
## Tree Format ##
|
||||
|
||||
As its name might suggest, a ledger's state tree is a tree data structure, with each node identified by a 256-bit value called an `index`. In JSON, a ledger node's index value is represented as a 64-character hexadecimal string like `"193C591BF62482468422313F9D3274B5927CA80B4DD3707E42015DD609E39C94"`. Every node in the state tree has an index that you can use as a key to look up the node in the state tree; every transaction has an indentifying hash that you can use to look up the transaction in the transaction tree. Do not confuse the `index` (key) of a ledger node with the [`ledger_index` (sequence number) of a ledger](#ledger-index).
|
||||
|
||||
In the case of transactions, the identifying hash is based on the signed transaction instructions, but the contents of the transaction object when you look it up also contain the results and metadata of the transaction, which are not taken into account when generating the hash.
|
||||
|
||||
In the case of state nodes, `rippled` usually includes the `index` of the node along with its contents. However, the index itself is not part of the contents. The index is derived by hashing important contents of the node, along with a [namespace identifier](https://github.com/ripple/rippled/blob/ceff6bc2713eaf80feafe56a02f4d636827b89a9/src/ripple/protocol/LedgerFormats.h#L94). The ledger node type determines which namespace identifier to use as well as which contents to include in the hash. This ensures every index is unique. For a hash function, `rippled` uses SHA-512 and then truncates the result to the first 256 bytes. This algorithm, informally called SHA-512Half, provides an output that has comparable security to SHA-256, but runs faster on 64-bit processors.
|
||||
|
||||

|
||||
|
||||
|
||||
## Header Format ##
|
||||
[[Source]<br>](https://github.com/ripple/rippled/blob/5d2d88209f1732a0f8d592012094e345cbe3e675/src/ripple/ledger/ReadView.h#L68 "Source")
|
||||
|
||||
Every ledger version has a unique header that describes the contents. You can look up a ledger's header information with the [`ledger` command](reference-rippled.html#ledger). The contents of the ledger header are as follows:
|
||||
|
||||
| Field | JSON Type | [Internal Type][] | Description |
|
||||
|-----------------|-----------|-------------------|-------------|
|
||||
| [ledger\_index](#ledger-index) | String | UInt32 | The sequence number of the ledger. Some API methods display this as a quoted integer; some display it as a native JSON number. |
|
||||
| ledger\_hash | String | Hash256 | The SHA-512Half of the ledger header, excluding the `ledger_hash` itself. This serves as a unique identifier for this ledger and all its contents. |
|
||||
| account\_hash | String | Hash256 | The SHA-512Half of this ledger's state tree information. |
|
||||
| close\_time | Number | UInt32 | The approximate time this ledger closed, as the number of seconds since the Ripple Epoch of 2000-01-01 00:00:00. This value is rounded based on the `close_time_resolution`, so it is possible for subsequent ledgers to have the same value. |
|
||||
| closed | Boolean | bool | If true, this transaction is no longer accepting new transactions. (However, unless this ledger is validated, it might be replaced by a different ledger with a different set of transactions.) |
|
||||
| parent\_hash | String | Hash256 | The `ledger_hash` value of the previous ledger that was used to build this one. If there are different versions of the previous ledger index, this indicates from which one the ledger was derived. |
|
||||
| total\_coins | String | UInt64 | The total number of drops of XRP owned by accounts in the ledger. This subtracts XRP that has been destroyed by transaction fees. The actual amount of XRP in circulation is lower because some accounts are "black holes" whose keys are not known by anyone. |
|
||||
| transaction\_hash | String | Hash256 | The SHA-512Half of the transactions included in this ledger. |
|
||||
| close\_time\_resolution | Number | Uint8 | An integer in the range \[2,120\] indicating the maximum number of seconds by which the `close_time` could be rounded. |
|
||||
| [closeFlags](#close-flags) | (Omitted) | UInt8 | A bit-map of flags relating to the closing of this ledger. |
|
||||
|
||||
[Internal Type]: https://wiki.ripple.com/Binary_Format
|
||||
|
||||
|
||||
### Ledger Index ###
|
||||
{% include 'data_types/ledger_index.md' %}
|
||||
[Hash]: reference-rippled.html#hashes
|
||||
|
||||
### Close Flags ###
|
||||
|
||||
Currently, the ledger has only one flag defined for closeFlags: **sLCF_NoConsensusTime** (value `1`). If this flag is enabled, it means that validators were in conflict regarding the correct close time for the ledger, but built otherwise the same ledger, so they declared consensus while "agreeing to disagree" on the close time. In this case, the consensus ledger contains a `close_time` value that is 1 second after that of the previous ledger. (In this case, there is no official close time, but the actual real-world close time is probably 3-6 seconds later than the specified `close_time`.)
|
||||
|
||||
The `closeFlags` field is not included in any JSON representations of a ledger, but it is a part of the binary representation of a ledger, and is one of the fields that determine the ledger's hash.
|
||||
|
||||
|
||||
|
||||
# Ledger Node Types #
|
||||
|
||||
There are several different kinds of nodes that can appear in the ledger's state tree:
|
||||
|
||||
* [**AccountRoot** - The settings, XRP balance, and other metadata for one account.](#accountroot)
|
||||
* [**DirectoryNode** - Contains links to other nodes.](#directorynode)
|
||||
* [**Offer** - An offer to exchange currencies, known in finance as an _order_.](#offer)
|
||||
* [**RippleState** - Links two accounts, tracking the balance of one currency between them. The concept of a _trust line_ is really an abstraction of this node type.](#ripplestate)
|
||||
|
||||
Each ledger node consists of several fields. In the peer protocol that `rippled` servers use to communicate with each other, ledger nodes are represented in their raw binary format. In other [`rippled` APIs](reference-rippled.html), ledger nodes are represented as JSON objects.
|
||||
|
||||
## AccountRoot ##
|
||||
[[Source]<br>](https://github.com/ripple/rippled/blob/5d2d88209f1732a0f8d592012094e345cbe3e675/src/ripple/protocol/impl/LedgerFormats.cpp#L27 "Source")
|
||||
|
||||
The `AccountRoot` node type describes a single _account_ object. Example `AccountRoot` node:
|
||||
|
||||
```
|
||||
{
|
||||
"Account": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn",
|
||||
"AccountTxnID": "0D5FB50FA65C9FE1538FD7E398FFFE9D1908DFA4576D8D7A020040686F93C77D",
|
||||
"Balance": "148446663",
|
||||
"Domain": "6D64756F31332E636F6D",
|
||||
"EmailHash": "98B4375E1D753E5B91627516F6D70977",
|
||||
"Flags": 8388608,
|
||||
"LedgerEntryType": "AccountRoot",
|
||||
"MessageKey": "0000000000000000000000070000000300",
|
||||
"OwnerCount": 3,
|
||||
"PreviousTxnID": "0D5FB50FA65C9FE1538FD7E398FFFE9D1908DFA4576D8D7A020040686F93C77D",
|
||||
"PreviousTxnLgrSeq": 14091160,
|
||||
"Sequence": 336,
|
||||
"TransferRate": 1004999999,
|
||||
"index": "13F1A95D7AAB7108D5CE7EEAF504B2894B8C674E6D68499076441C4837282BF8"
|
||||
}
|
||||
```
|
||||
|
||||
The `AccountRoot` node has the following fields:
|
||||
|
||||
| Field | JSON Type | [Internal Type][] | Description |
|
||||
|-----------------|-----------|---------------|-------------|
|
||||
| LedgerEntryType | String | UInt16 | The value `0x61`, mapped to the string `AccountRoot`, indicates that this node is an AccountRoot object. |
|
||||
| Account | String | AccountID | The identifying address of this account, such as rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn. |
|
||||
| [Flags](#accountroot-flags) | Number | UInt32 | A bit-map of boolean flags enabled for this account. |
|
||||
| Sequence | Number | UInt32 | The sequence number of the next valid transaction for this account. (Each account starts with Sequence = 1 and increases each time a transaction is made.) |
|
||||
| Balance | String | Amount | The account's current XRP balance in drops, represented as a string. |
|
||||
| OwnerCount | Number | UInt32 | The number of objects this account owns in the ledger, which contributes to its owner reserve. |
|
||||
| PreviousTxnID | String | Hash256 | The identifying hash of the transaction that most recently modified this node. |
|
||||
| PreviousTxnLgrSeq | Number | UInt32 | The [index of the ledger](#ledger-index) that contains the transaction that most recently modified this node. |
|
||||
| AccountTxnID | String | Hash256 | (Optional) The identifying hash of the transaction most recently submitted by this account. |
|
||||
| RegularKey | String | AccountID | (Optional) The address of a keypair that can be used to sign transactions for this account instead of the master key. Use a [SetRegularKey transaction](reference-transaction-format.html#setregularkey) to change this value. |
|
||||
| EmailHash | String | Hash128 | (Optional) The md5 hash of an email address. Clients can use this to look up an avatar through services such as [Gravatar](https://en.gravatar.com/). |
|
||||
| WalletLocator | String | Hash256 | (Optional) **DEPRECATED**. Do not use. |
|
||||
| WalletSize | Number | UInt32 | (Optional) **DEPRECATED**. Do not use. |
|
||||
| MessageKey | String | VariableLength | (Optional) A public key that may be used to send encrypted messages to this account. In JSON, uses hexadecimal. No more than 33 bytes. |
|
||||
| TransferRate | Number | UInt32 | (Optional) A [transfer fee](https://ripple.com/knowledge_center/transfer-fees/) to charge other users for sending currency issued by this account to each other. |
|
||||
| Domain | String | VariableLength | (Optional) A domain associated with this account. In JSON, this is the hexadecimal for the ASCII representation of the domain. |
|
||||
|
||||
### AccountRoot Flags ###
|
||||
|
||||
There are several options which can be either enabled or disabled for an account. These options can be changed with an [AccountSet transaction](reference-transaction-format.html#accountset). In the ledger, flags are represented as binary values that can be combined with bitwise-or operations. The bit values for the flags in the ledger are different than the values used to enable or disable those flags in a transaction. Ledger flags have names that begin with _lsf_.
|
||||
|
||||
AccountRoot nodes can have the following flag values:
|
||||
|
||||
| Flag Name | Hex Value | Decimal Value | Description | Corresponding [AccountSet Flag](reference-transaction-format.html#accountset-flags) |
|
||||
|-----------|-----------|---------------|-------------|-------------------------------|
|
||||
| lsfPasswordSpent | 0x00010000 | 65536 | Indicates that the account has used its free SetRegularKey transaction. | (None) |
|
||||
| lsfRequireDestTag | 0x00020000 | 131072 | Requires incoming payments to specify a Destination Tag. | asfRequireDest |
|
||||
| lsfRequireAuth | 0x00040000 | 262144 | This account must individually approve other users in order for those users to hold this account's issuances. | asfRequireAuth |
|
||||
| lsfDisallowXRP | 0x00080000 | 524288 | Client applications should not send XRP to this account. Not enforced by `rippled`. | asfDisallowXRP |
|
||||
| lsfDisableMaster | 0x00100000 | 1048576 | Disallows use of the master key to sign transactions for this account. | asfDisableMaster |
|
||||
| lsfNoFreeze | 0x00200000 | 209715 | This account cannot freeze trust lines connected to it. Once enabled, cannot be disabled. | asfNoFreeze |
|
||||
| lsfGlobalFreeze | 0x00400000 | 4194304 | All assets issued by this account are frozen. | asfGlobalFreeze |
|
||||
| lsfDefaultRipple | 0x00800000 | 8388608 | Enable [rippling](https://ripple.com/knowledge_center/understanding-the-noripple-flag/) on this account's trust lines by default. Required for gateways; discouraged for other accounts. | asfDefaultRipple |
|
||||
|
||||
### AccountRoot Index Format ###
|
||||
|
||||
The `index` of an AccountRoot node is the SHA-512Half of the following values put together:
|
||||
|
||||
* The Account space key (`a`)
|
||||
* The AccountID of the account
|
||||
|
||||
|
||||
## DirectoryNode ##
|
||||
[[Source]<br>](https://github.com/ripple/rippled/blob/5d2d88209f1732a0f8d592012094e345cbe3e675/src/ripple/protocol/impl/LedgerFormats.cpp#L44 "Source")
|
||||
|
||||
The `DirectoryNode` node type provides a list of links to other nodes in the ledger's state tree. A single conceptual _Directory_ takes the form of a doubly linked list, with one or more DirectoryNode objects each containing up to 32 [indexes](#tree-format) of other nodes. The first node is called the root of the directory, and all nodes other than the root node can be added or deleted as necessary.
|
||||
|
||||
There are two kinds of Directories:
|
||||
|
||||
* **Owner directories** list other nodes owned by an account, such as RippleState or Offer nodes.
|
||||
* **Offer directories** list the offers currently available in the distributed exchange. A single Offer Directory contains all the offers that have the same exchange rate for the same issuances.
|
||||
|
||||
Example Directories:
|
||||
|
||||
<!-- <div class='multicode'> -->
|
||||
|
||||
*Offer Directory*
|
||||
|
||||
```
|
||||
{
|
||||
"ExchangeRate": "4F069BA8FF484000",
|
||||
"Flags": 0,
|
||||
"Indexes": [
|
||||
"AD7EAE148287EF12D213A251015F86E6D4BD34B3C4A0A1ED9A17198373F908AD"
|
||||
],
|
||||
"LedgerEntryType": "DirectoryNode",
|
||||
"RootIndex": "1BBEF97EDE88D40CEE2ADE6FEF121166AFE80D99EBADB01A4F069BA8FF484000",
|
||||
"TakerGetsCurrency": "0000000000000000000000000000000000000000",
|
||||
"TakerGetsIssuer": "0000000000000000000000000000000000000000",
|
||||
"TakerPaysCurrency": "0000000000000000000000004A50590000000000",
|
||||
"TakerPaysIssuer": "5BBC0F22F61D9224A110650CFE21CC0C4BE13098",
|
||||
"index": "1BBEF97EDE88D40CEE2ADE6FEF121166AFE80D99EBADB01A4F069BA8FF484000"
|
||||
}
|
||||
```
|
||||
|
||||
*Owner Directory*
|
||||
|
||||
```
|
||||
{
|
||||
"Flags": 0,
|
||||
"Indexes": [
|
||||
"AD7EAE148287EF12D213A251015F86E6D4BD34B3C4A0A1ED9A17198373F908AD",
|
||||
"E83BBB58949A8303DF07172B16FB8EFBA66B9191F3836EC27A4568ED5997BAC5"
|
||||
],
|
||||
"LedgerEntryType": "DirectoryNode",
|
||||
"Owner": "rpR95n1iFkTqpoy1e878f4Z1pVHVtWKMNQ",
|
||||
"RootIndex": "193C591BF62482468422313F9D3274B5927CA80B4DD3707E42015DD609E39C94",
|
||||
"index": "193C591BF62482468422313F9D3274B5927CA80B4DD3707E42015DD609E39C94"
|
||||
}
|
||||
```
|
||||
|
||||
<!-- </div> -->
|
||||
|
||||
| Name | JSON Type | [Internal Type][] | Description |
|
||||
|-------------------|-----------|---------------|-------------|
|
||||
| LedgerEntryType | Number | UInt16 | The value `0x64`, mapped to the string `DirectoryNode`, indicates that this node is part of a Directory. |
|
||||
| Flags | Number | UInt32 | A bit-map of boolean flags enabled for this directory. Currently, the protocol defines no flags for DirectoryNode objects. |
|
||||
| RootIndex | Number | Hash256 | The index of root node for this directory. |
|
||||
| Indexes | Array | Vector256 | The contents of this Directory: an array of indexes to other nodes. |
|
||||
| IndexNext | Number | UInt64 | (Optional) If this Directory consists of multiple nodes, this index links to the next node in the chain, wrapping around at the end. |
|
||||
| IndexPrevious | Number | UInt64 | (Optional) If this Directory consists of multiple nodes, this index links to the previous node in the chain, wrapping around at the beginning. |
|
||||
| Owner | String | AccountID | (Owner Directories only) The address of the account that owns the objects in this directory. |
|
||||
| ExchangeRate | Number | UInt64 | (Offer Directories only) **DEPRECATED**. Do not use. |
|
||||
| TakerPaysCurrency | String | Hash160 | (Offer Directories only) The currency code of the TakerPays amount from the offers in this directory. |
|
||||
| TakerPaysIssuer | String | Hash160 | (Offer Directories only) The issuer of the TakerPays amount from the offers in this directory. |
|
||||
| TakerGetsCurrency | String | Hash160 | (Offer Directories only) The currency code of the TakerGets amount from the offers in this directory. |
|
||||
| TakerGetsIssuer | String | Hash160 | (Offer Directories only) The issuer of the TakerGets amount from the offers in this directory. |
|
||||
|
||||
### Directory Index Formats ###
|
||||
|
||||
There are three different formulas for creating the index of a DirectoryNode, depending on whether the DirectoryNode represents:
|
||||
|
||||
* The first page (also called the root) of an Owner Directory,
|
||||
* The first page of an Offer Directory, _or_
|
||||
* Subsequent pages of either type
|
||||
|
||||
**The first page of an Owner Directory** has an `index` that is the SHA-512Half of the following values put together:
|
||||
|
||||
* The Owner Directory space key (`O`, capital letter O)
|
||||
* The AccountID from the `Owner` field.
|
||||
|
||||
**The first page of an Offer Directory** has a special `index`: the higher 192 bits define the order book, and the remaining 64 bits define the exchange rate of the offers in that directory. (An index is big-endian, so the book is in the more significant bits, which come first, and the quality is in the less significant bits which come last.) This provides a way to iterate through an order book from best offers to worst. Specifically: the first 192 bits are the first 192 bits of the SHA-512Half of the following values put together:
|
||||
|
||||
* The Book Directory space key (`B`)
|
||||
* The 160-bit currency code from the `TakerPaysCurrency`
|
||||
* The 160-bit currency code from the `TakerGetsCurrency`
|
||||
* The AccountID from the `TakerPaysIssuer`
|
||||
* The AccountID from the `TakerGetsIssuer`
|
||||
|
||||
The lower 64 bits of an Offer Directory's index represent the TakerPays amount divided by TakerGets amount from the offer(s) in that directory as a 64-bit number in Ripple's internal amount format.
|
||||
|
||||
**If the DirectoryNode is not the first page in the Directory** (regardless of whether it is an Owner Directory or an Offer Directory), then it has an `index` that is the SHA-512Half of the following values put together:
|
||||
|
||||
* The Directory Node space key (`d`)
|
||||
* The `index` of the root DirectoryNode
|
||||
* The page number of this node. (Since 0 is the root DirectoryNode, this value is an integer 1 or higher.)
|
||||
|
||||
|
||||
## Offer ##
|
||||
[[Source]<br>](https://github.com/ripple/rippled/blob/5d2d88209f1732a0f8d592012094e345cbe3e675/src/ripple/protocol/impl/LedgerFormats.cpp#L57 "Source")
|
||||
|
||||
The `Offer` node type describes an offer to exchange currencies, more traditionally known as an _order_, which is currently in an order book in Ripple's distributed exchange. An [OfferCreate transaction](reference-transaction-format.html#offercreate) only creates an Offer node in the ledger when the offer cannot be fully executed immediately by consuming other offers already in the ledger.
|
||||
|
||||
An offer can become unfunded through other activities in the network, while remaining in the ledger. However, `rippled` will automatically prune any unfunded offers it happens across in the course of transaction processing (and _only_ transaction processing, because the ledger state must only be changed by transactions). For more information, see [lifecycle of an offer](reference-transaction-format.html#lifecycle-of-an-offer).
|
||||
|
||||
Example Offer node:
|
||||
|
||||
```
|
||||
{
|
||||
"Account": "rBqb89MRQJnMPq8wTwEbtz4kvxrEDfcYvt",
|
||||
"BookDirectory": "ACC27DE91DBA86FC509069EAF4BC511D73128B780F2E54BF5E07A369E2446000",
|
||||
"BookNode": "0000000000000000",
|
||||
"Flags": 131072,
|
||||
"LedgerEntryType": "Offer",
|
||||
"OwnerNode": "0000000000000000",
|
||||
"PreviousTxnID": "F0AB71E777B2DA54B86231E19B82554EF1F8211F92ECA473121C655BFC5329BF",
|
||||
"PreviousTxnLgrSeq": 14524914,
|
||||
"Sequence": 866,
|
||||
"TakerGets": {
|
||||
"currency": "XAG",
|
||||
"issuer": "r9Dr5xwkeLegBeXq6ujinjSBLQzQ1zQGjH",
|
||||
"value": "37"
|
||||
},
|
||||
"TakerPays": "79550000000",
|
||||
"index": "96F76F27D8A327FC48753167EC04A46AA0E382E6F57F32FD12274144D00F1797"
|
||||
}
|
||||
```
|
||||
|
||||
An Offer node has the following fields:
|
||||
|
||||
| Name | JSON Type | [Internal Type][] | Description |
|
||||
|-------------------|-----------|---------------|-------------|
|
||||
| LedgerEntryType | String | UInt16 | The value `0x6F`, mapped to the string `Offer`, indicates that this node is an Offer object. |
|
||||
| Flags | Number | UInt32 | A bit-map of boolean flags enabled for this offer. |
|
||||
| Account | String | AccountID | The address of the account that owns this offer. |
|
||||
| Sequence | Number | UInt32 | The `Sequence` value of the [OfferCreate](reference-transaction-format.html#offercreate) transaction that created this Offer node. Used in combination with the `Account` to identify this Offer. |
|
||||
| TakerPays | String or Object | Amount | The remaining amount and type of currency requested by the offer creator. |
|
||||
| TakerGets | String or Object | Amount | The remaining amount and type of currency being provided by the offer creator. |
|
||||
| BookDirectory | String | UInt256 | The index of the [Offer Directory](#directorynode) that links to this offer. |
|
||||
| BookNode | String | UInt64 | A hint indicating which page of the offer directory links to this node, in case the directory consists of multiple nodes. |
|
||||
| OwnerNode | String | UInt64 | A hint indicating which page of the owner directory links to this node, in case the directory consists of multiple nodes. **Note:** The offer does not contain a direct link to the owner directory containing it, since that value can be derived from the `Account`. |
|
||||
| PreviousTxnID | String | Hash256 | The identifying hash of the transaction that most recently modified this node. |
|
||||
| PreviousTxnLgrSeq | Number | UInt32 | The [index of the ledger](#ledger-index) that contains the transaction that most recently modified this node. |
|
||||
| Expiration | Number | UInt32 | (Optional) Indicates the time after which this offer will be considered unfunded. See [Specifying Time](reference-rippled.html#specifying-time) for details. |
|
||||
|
||||
### Offer Flags ###
|
||||
|
||||
There are several options which can be either enabled or disabled when an [OfferCreate transaction](reference-transaction-format.html#offercreate) creates an offer node. In the ledger, flags are represented as binary values that can be combined with bitwise-or operations. The bit values for the flags in the ledger are different than the values used to enable or disable those flags in a transaction. Ledger flags have names that begin with _lsf_.
|
||||
|
||||
Offer nodes can have the following flag values:
|
||||
|
||||
| Flag Name | Hex Value | Decimal Value | Description | Corresponding [OfferCreate Flag](reference-transaction-format.html#offercreate-flags) |
|
||||
|-----------|-----------|---------------|-------------|------------------------|
|
||||
| lsfPassive | 0x00010000 | 65536 | The node was placed as a passive offer. This has no effect on the node in the ledger. | tfPassive |
|
||||
| lsfSell | 0x00020000 | 131072 | The node was placed as a sell offer. This has no effect on the node in the ledger (because tfSell only matters if you get a better rate than you asked for, which cannot happen after the node enters the ledger). | tfSell |
|
||||
|
||||
### Offer Index Format ###
|
||||
|
||||
The `index` of an Offer node is the SHA-512Half of the following values put together:
|
||||
|
||||
* The Offer space key (`o`)
|
||||
* The AccountID of the account placing the offer
|
||||
* The Sequence number of the transaction that created the offer
|
||||
|
||||
|
||||
## RippleState ##
|
||||
[[Source]<br>](https://github.com/ripple/rippled/blob/5d2d88209f1732a0f8d592012094e345cbe3e675/src/ripple/protocol/impl/LedgerFormats.cpp#L70 "Source")
|
||||
|
||||
The `RippleState` node type connects two accounts in a single currency. Conceptually, a RippleState node represents two _trust lines_ between the accounts, one from each side. Each account can modify the settings for its side of the RippleState node, but the balance is a single shared value. A trust line that is entirely in its default state is considered the same as trust line that does not exist, so `rippled` deletes RippleState nodes when their properties are entirely default.
|
||||
|
||||
Since no account is privileged in the Ripple ledger, a RippleState node sorts their account addresses numerically, to ensure a canonical form. Whichever address is numerically lower is deemed the "low account" and the other is the "high account".
|
||||
|
||||
Example RippleState node:
|
||||
|
||||
```
|
||||
{
|
||||
"Balance": {
|
||||
"currency": "USD",
|
||||
"issuer": "rrrrrrrrrrrrrrrrrrrrBZbvji",
|
||||
"value": "-10"
|
||||
},
|
||||
"Flags": 393216,
|
||||
"HighLimit": {
|
||||
"currency": "USD",
|
||||
"issuer": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn",
|
||||
"value": "110"
|
||||
},
|
||||
"HighNode": "0000000000000000",
|
||||
"LedgerEntryType": "RippleState",
|
||||
"LowLimit": {
|
||||
"currency": "USD",
|
||||
"issuer": "rsA2LpzuawewSBQXkiju3YQTMzW13pAAdW",
|
||||
"value": "0"
|
||||
},
|
||||
"LowNode": "0000000000000000",
|
||||
"PreviousTxnID": "E3FE6EA3D48F0C2B639448020EA4F03D4F4F8FFDB243A852A0F59177921B4879",
|
||||
"PreviousTxnLgrSeq": 14090896,
|
||||
"index": "9CA88CDEDFF9252B3DE183CE35B038F57282BC9503CDFA1923EF9A95DF0D6F7B"
|
||||
}
|
||||
```
|
||||
|
||||
A RippleState node has the following fields:
|
||||
|
||||
| Name | JSON Type | Internal Type | Description |
|
||||
|-----------------|-----------|---------------|-------------|
|
||||
| LedgerEntryType | String | UInt16 | The value `0x72`, mapped to the string `RippleState`, indicates that this node is a RippleState object. |
|
||||
| Flags | Number | UInt32 | A bit-map of boolean options enabled for this node. |
|
||||
| Balance | Object | Amount | The balance of the trust line, from the perspective of the low account. A negative balance indicates that the low account has issued currency to the high account. The issuer in this is always set to the neutral value [ACCOUNT_ONE](https://wiki.ripple.com/Accounts#ACCOUNT_ONE). |
|
||||
| LowLimit | Object | Amount | The limit that the low account has set on the trust line. The `issuer` is the address of the low account that set this limit. |
|
||||
| HighLimit | Object | Amount | The limit that the high account has set on the trust line. The `issuer` is the address of the high account that set this limit. |
|
||||
| PreviousTxnID | String | Hash256 | The identifying hash of the transaction that most recently modified this node. |
|
||||
| PreviousTxnLgrSeq | Number | UInt32 | The [index of the ledger](#ledger-index) that contains the transaction that most recently modified this node. |
|
||||
| LowNode | String | UInt64 | (Omitted in some historical ledgers) A hint indicating which page of the low account's owner directory links to this node, in case the directory consists of multiple nodes. |
|
||||
| HighNode | String | UInt64 | (Omitted in some historical ledgers) A hint indicating which page of the high account's owner directory links to this node, in case the directory consists of multiple nodes. |
|
||||
| LowQualityIn | Number | UInt32 | (Optional) The inbound quality set by the low account, as an integer in the implied ratio LowQualityIn:1,000,000,000. The value 0 is equivalent to 1 billion, or face value. |
|
||||
| LowQualityOut | Number | UInt32 | (Optional) The outbound quality set by the low account, as an integer in the implied ratio LowQualityOut:1,000,000,000. The value 0 is equivalent to 1 billion, or face value. |
|
||||
| HighQualityIn | Number | UInt32 | (Optional) The inbound quality set by the high account, as an integer in the implied ratio HighQualityIn:1,000,000,000. The value 0 is equivalent to 1 billion, or face value. |
|
||||
| HighQualityOut | Number | UInt32 | (Optional) The outbound quality set by the high account, as an integer in the implied ratio HighQualityOut:1,000,000,000. The value 0 is equivalent to 1 billion, or face value. |
|
||||
|
||||
### RippleState Flags ###
|
||||
|
||||
There are several options which can be either enabled or disabled for a trust line. These options can be changed with a [TrustSet transaction](reference-transaction-format.html#trustset). In the ledger, flags are represented as binary values that can be combined with bitwise-or operations. The bit values for the flags in the ledger are different than the values used to enable or disable those flags in a transaction. Ledger flags have names that begin with _lsf_.
|
||||
|
||||
RippleState nodes can have the following flag values:
|
||||
|
||||
| Flag Name | Hex Value | Decimal Value | Description | Corresponding [TrustSet Flag](reference-transaction-format.html#trustset-flags) |
|
||||
|-----------|-----------|---------------|-------------|------------------------|
|
||||
| lsfLowReserve | 0x00010000 | 65536 | This RippleState node [contributes to the low account's owner reserve](#contributing-to-the-owner-reserve). | (None) |
|
||||
| lsfHighReserve | 0x00020000 |131072 | This RippleState node [contributes to the high account's owner reserve](#contributing-to-the-owner-reserve). | (None) |
|
||||
| lsfLowAuth | 0x00040000 | 262144 | The low account has authorized the high account to hold the low account's issuances. | tfSetAuth |
|
||||
| lsfHighAuth | 0x00080000 | 524288 | The high account has authorized the low account to hold the high account's issuances. | tfSetAuth |
|
||||
| lsfLowNoRipple | 0x00100000 | 1048576 | The low account [has disabled rippling](https://ripple.com/knowledge_center/understanding-the-noripple-flag/) from this trust line to other trust lines with the same account's NoRipple flag set. | tfSetNoRipple |
|
||||
| lsfHighNoRipple | 0x00200000 | 2097152 | The high account [has disabled rippling](https://ripple.com/knowledge_center/understanding-the-noripple-flag/) from this trust line to other trust lines with the same account's NoRipple flag set. | tfSetNoRipple |
|
||||
| lsfLowFreeze | 0x00400000 | 4194304 | The low account has frozen the trust line, preventing the high account from transferring the asset. | tfSetFreeze |
|
||||
| lsfHighFreeze | 0x00800000 | 8388608 | The high account has frozen the trust line, preventing the low account from transferring the asset. | tfSetFreeze |
|
||||
|
||||
### Contributing to the Owner Reserve ###
|
||||
|
||||
If an account modifies a trust line to put it in a non-default state, then that trust line counts towards the account's [owner reserve](concept-reserves.html#owner-reserves). In a RippleState node, the `lsfLowReserve` and `lsfHighReserve` flags indicate which account(s) are responsible for the owner reserve. The `rippled` server automatically sets these flags when it modifies a trust line.
|
||||
|
||||
The values that count towards a trust line's non-default state are as follows:
|
||||
|
||||
| High account responsible if... | Low account responsible if... |
|
||||
|-----------------------|----------------------|
|
||||
| `Balance` is negative (the high account holds currency) | `Balance` is positive (the low account holds currency) |
|
||||
| `HighLimit` is not `0` | `LowLimit` is not `0` |
|
||||
| `LowQualityIn` is not `0` and not `1000000000` | `HighQualityIn` is not `0` and not `1000000000` |
|
||||
| `LowQualityOut` is not `0` and not `1000000000` | `HighQualityOut` is not `0` and not `1000000000` |
|
||||
| **lsfHighNoRipple** flag is not in its default state | **lsfLowNoRipple** flag is not in its default state |
|
||||
| **lsfHighFreeze** flag is enabled | **lsfLowFreeze** flag is enabled |
|
||||
|
||||
The **lsfLowAuth** and **lsfHighAuth** flags do not count against the default state, because they cannot be disabled.
|
||||
|
||||
The default state of the two NoRipple flags depends on the state of the [lsfDefaultRipple flag](#accountroot-flags) in their corresponding AccountRoot nodes. If DefaultRipple is disabled (the default), then the default state of the lsfNoRipple flag is _enabled_ for all of an account's trust lines. If an account enables DefaultRipple, then the lsfNoRipple flag is _disabled_ (rippling is enabled) for an account's trust lines by default. **Note:** Prior to the introduction of the DefaultRipple flags in `rippled` version 0.27.3 (March 10, 2015), the default state for all trust lines was with lsfNoRipple disabled (rippling enabled).
|
||||
|
||||
Fortunately, `rippled` uses lazy evaluation to calculate the owner reserve. This means that even if an account changes the default state of all its trust lines by changing the DefaultRipple flag, that account's reserve stays the same initially. If an account modifies a trust line, `rippled` re-evaluates whether that individual trust line is in its default state and should contribute the owner reserve.
|
||||
|
||||
### RippleState Index Format ###
|
||||
|
||||
The `index` of a RippleState node is the SHA-512Half of the following values put together:
|
||||
|
||||
* The RippleState space key (`r`)
|
||||
* The AccountID of the low account
|
||||
* The AccountID of the high account
|
||||
* The 160-bit currency code of the trust line(s)
|
||||
|
||||
|
||||
## SignerList ##
|
||||
[[Source]<br>](https://github.com/ripple/rippled/blob/6d2e3da30696bd10e3bb11a5ff6d45d2c4dae90f/src/ripple/protocol/impl/LedgerFormats.cpp#L127 "Source")
|
||||
|
||||
The `SignerList` node type represents a list of parties that, as a group, are authorized to sign a transaction in place of an individual account. You can create, replace, or remove a SignerList using the [SignerListSet transaction type](reference-transaction-format.html#signerlistset) This node type is introduced by the [MultiSign amendment](concept-amendments.html#multisign). _(New in [version 0.31.0][])_
|
||||
|
||||
Example SignerList node:
|
||||
|
||||
```
|
||||
{
|
||||
"Flags": 0,
|
||||
"LedgerEntryType": "SignerList",
|
||||
"OwnerNode": "0000000000000000",
|
||||
"PreviousTxnID": "5904C0DC72C58A83AEFED2FFC5386356AA83FCA6A88C89D00646E51E687CDBE4",
|
||||
"PreviousTxnLgrSeq": 16061435,
|
||||
"SignerEntries": [
|
||||
{
|
||||
"SignerEntry": {
|
||||
"Account": "rsA2LpzuawewSBQXkiju3YQTMzW13pAAdW",
|
||||
"SignerWeight": 2
|
||||
}
|
||||
},
|
||||
{
|
||||
"SignerEntry": {
|
||||
"Account": "raKEEVSGnKSD9Zyvxu4z6Pqpm4ABH8FS6n",
|
||||
"SignerWeight": 1
|
||||
}
|
||||
},
|
||||
{
|
||||
"SignerEntry": {
|
||||
"Account": "rUpy3eEg8rqjqfUoLeBnZkscbKbFsKXC3v",
|
||||
"SignerWeight": 1
|
||||
}
|
||||
}
|
||||
],
|
||||
"SignerListID": 0,
|
||||
"SignerQuorum": 3,
|
||||
"index": "A9C28A28B85CD533217F5C0A0C7767666B093FA58A0F2D80026FCC4CD932DDC7"
|
||||
}
|
||||
```
|
||||
|
||||
A SignerList node has the following fields:
|
||||
|
||||
| Name | JSON Type | Internal Type | Description |
|
||||
|-----------------|-----------|---------------|-------------|
|
||||
| OwnerNode | String | UInt64 | A hint indicating which page of the owner directory links to this node, in case the directory consists of multiple nodes. |
|
||||
| SignerQuorum | Number | UInt32 | A target number for signer weights. To produce a valid signature for the owner of this SignerList, the signers must provide valid signatures whose weights sum to this value or more. |
|
||||
| SignerEntries | Array | Array | An array of SignerEntry objects representing the parties who are part of this signer list. |
|
||||
| SignerListID | Number | UInt32 | An ID for this signer list. Currently always set to `0`. If a future [amendment](concept-amendments.html) allows multiple signer lists for an account, this may change. |
|
||||
| PreviousTxnID | String | Hash256 | The identifying hash of the transaction that most recently modified this node. |
|
||||
| PreviousTxnLgrSeq | Number | UInt32 | The [index of the ledger](#ledger-index) that contains the transaction that most recently modified this node. |
|
||||
|
||||
The `SignerEntries` may be any combination of funded and unfunded addresses that use either secp256k1 or ed25519 keys.
|
||||
|
||||
### SignerEntry Object ###
|
||||
|
||||
Each member of the `SignerEntries` field is an object that describes that signer in the list. A SignerEntry has the following fields:
|
||||
|
||||
| Name | JSON Type | Internal Type | Description |
|
||||
|-----------------|-----------|---------------|-------------|
|
||||
| Account | String | AccountID | A Ripple address whose signature contributes to the multi-signature. It does not need to be a funded address in the ledger. |
|
||||
| SignerWeight | Number | UInt16 | The weight of a signature from this signer. A multi-signature is only valid if the sum weight of the signatures provided meets or exceeds the SignerList's `SignerQuorum` value. |
|
||||
|
||||
When processing a multi-signed transaction, the server dereferences the `Account` values with respect to the ledger at the time of transaction execution. If the address _does not_ correspond to a funded [AccountRoot node](#accountroot), then only the master secret associated with that address can be used to produce a valid signature. If the account _does_ exist in the ledger, then it depends on the state of that account. If the account has a Regular Key configured, the Regular Key can be used. The account's master key can only be used if it is not disabled. A multi-signature cannot be used as a component of another multi-signature.
|
||||
|
||||
### SignerLists and Reserves ###
|
||||
|
||||
A SignerList contributes to its owner's [reserve requirement](concept-reserves.html). The SignerList itself counts as two objects, and each member of the list counts as one. As a result, the total owner reserve associated with a SignerList is anywhere from 3 times to 10 times the reserve required by a single trust line ([RippleState](#ripplestate)) or [Offer](#offer) node in the ledger.
|
||||