mirror of
https://github.com/Xahau/xahau.js.git
synced 2025-11-05 05:15:48 +00:00
Compare commits
375 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
362bb13da1 | ||
|
|
d76a5fc87a | ||
|
|
824f87a692 | ||
|
|
fa2385ee1c | ||
|
|
2be7a8fa94 | ||
|
|
7d6a3a7518 | ||
|
|
61692a5e34 | ||
|
|
e82c585955 | ||
|
|
bc50603111 | ||
|
|
debb9cb3a5 | ||
|
|
4fd74b3671 | ||
|
|
eb4ac74ce6 | ||
|
|
cf4d2b2c1a | ||
|
|
c79b044aaa | ||
|
|
32718d583b | ||
|
|
c3965f325b | ||
|
|
7b77177962 | ||
|
|
3781b798a1 | ||
|
|
31314212a5 | ||
|
|
7d36cfa068 | ||
|
|
848c179fd4 | ||
|
|
e2cecd07e4 | ||
|
|
08b76fba22 | ||
|
|
2642589ea4 | ||
|
|
965dc4bd87 | ||
|
|
c9689ec2a8 | ||
|
|
9a3ef216f9 | ||
|
|
e8817d9e0b | ||
|
|
abb1d23ee2 | ||
|
|
9636849c63 | ||
|
|
4aa76b38f9 | ||
|
|
03655b4ed2 | ||
|
|
f1ec45769b | ||
|
|
5db1f5668c | ||
|
|
dd4c6a0353 | ||
|
|
95a2655501 | ||
|
|
2ba31c5b75 | ||
|
|
33fb35138f | ||
|
|
ed26f9a763 | ||
|
|
415a61f06a | ||
|
|
4eb64b5e72 | ||
|
|
9e96fa3473 | ||
|
|
1c1a3fa583 | ||
|
|
c985838cdd | ||
|
|
81dfd99642 | ||
|
|
9f6fa6a4fd | ||
|
|
6b4fa159ea | ||
|
|
782787a5b9 | ||
|
|
fd0f64fe54 | ||
|
|
c7e08378ac | ||
|
|
382cf4cb1f | ||
|
|
be71af5c55 | ||
|
|
97f9812876 | ||
|
|
dcc50e1b36 | ||
|
|
ae8824fb11 | ||
|
|
337ab2993b | ||
|
|
a4782764dd | ||
|
|
0a4c28f799 | ||
|
|
1470a0d234 | ||
|
|
bc19db9ddd | ||
|
|
d96b0d3986 | ||
|
|
a5c35586f7 | ||
|
|
a54655c0ff | ||
|
|
2681e81d6b | ||
|
|
2a0234e5ce | ||
|
|
6b326a6efd | ||
|
|
48d2bf849f | ||
|
|
4ab808b6de | ||
|
|
e5496e84a6 | ||
|
|
83b5c7f678 | ||
|
|
e6c9617e01 | ||
|
|
6c5fcc3dc6 | ||
|
|
2931bb2863 | ||
|
|
d745b128e3 | ||
|
|
73b952ec0d | ||
|
|
be961fb9a7 | ||
|
|
851d84bde8 | ||
|
|
854c4ebfdd | ||
|
|
a77448f7c0 | ||
|
|
0dc33f3d88 | ||
|
|
aaff0257b0 | ||
|
|
3557a57bbd | ||
|
|
051d23edff | ||
|
|
ccb91c1268 | ||
|
|
6c1c0eee59 | ||
|
|
f1c1c7033a | ||
|
|
bc352c4cf0 | ||
|
|
1980fa9fa4 | ||
|
|
6cabb2e935 | ||
|
|
05411527ee | ||
|
|
3c13da66b3 | ||
|
|
5d6af09508 | ||
|
|
15bf721d24 | ||
|
|
14351c9512 | ||
|
|
3b13de5310 | ||
|
|
f92eff2df8 | ||
|
|
a65ac5f8f0 | ||
|
|
0e36a1c505 | ||
|
|
f5bed635e0 | ||
|
|
905ab9f2e4 | ||
|
|
547b63b891 | ||
|
|
c26ddb497e | ||
|
|
2e81cfb56f | ||
|
|
337cb6574a | ||
|
|
abcb6bfecb | ||
|
|
797fda3363 | ||
|
|
bd920ee5bb | ||
|
|
2720970e1f | ||
|
|
b7a12d4bbb | ||
|
|
b4f6135b96 | ||
|
|
7d65bf4641 | ||
|
|
656c81a72c | ||
|
|
bfd0374ef6 | ||
|
|
bf1a772e40 | ||
|
|
8ede100594 | ||
|
|
927f1f6d9a | ||
|
|
0be4c6f233 | ||
|
|
912eea5037 | ||
|
|
06a029b89c | ||
|
|
df708a77d2 | ||
|
|
31232ad50c | ||
|
|
7abaf61e11 | ||
|
|
903a6e31b8 | ||
|
|
2eb5898e8b | ||
|
|
dc2bc0291b | ||
|
|
1357f7eeb4 | ||
|
|
b0cb0a759b | ||
|
|
19d0ca6bfc | ||
|
|
26d03fe2a5 | ||
|
|
dfa61df40a | ||
|
|
d154cced14 | ||
|
|
80b96d9bc9 | ||
|
|
8fa30f71eb | ||
|
|
804094b1ce | ||
|
|
9caf077b58 | ||
|
|
1a5ba06ca3 | ||
|
|
657cad9ffd | ||
|
|
a338a936db | ||
|
|
226e10bca2 | ||
|
|
3a5a989011 | ||
|
|
c9720ef061 | ||
|
|
b6927f178f | ||
|
|
6b40e4fe9d | ||
|
|
59ec56db4c | ||
|
|
a8119d678a | ||
|
|
8e38e313b2 | ||
|
|
b7b75d78ae | ||
|
|
824efb6b59 | ||
|
|
c151ca202c | ||
|
|
b9a64c92e7 | ||
|
|
bcaa06721a | ||
|
|
06227ef12b | ||
|
|
c17827e030 | ||
|
|
97ca0f0b21 | ||
|
|
e4e6419e50 | ||
|
|
fd8c883cf4 | ||
|
|
6b66a59673 | ||
|
|
46177338c2 | ||
|
|
6fcff9b106 | ||
|
|
208f5f6c5c | ||
|
|
de3e2a9867 | ||
|
|
40eea3c659 | ||
|
|
4f9b6b9186 | ||
|
|
4a848ec527 | ||
|
|
10414e169c | ||
|
|
1a6c68d028 | ||
|
|
9156734ced | ||
|
|
0dfe3ff4ac | ||
|
|
3a8c7f02cc | ||
|
|
e03b192fcc | ||
|
|
cf40bd2c30 | ||
|
|
4082e88416 | ||
|
|
27abc10d93 | ||
|
|
d6474d71f2 | ||
|
|
d57603e854 | ||
|
|
ac92584678 | ||
|
|
c234be0a8c | ||
|
|
7c6b8398cf | ||
|
|
7de677c953 | ||
|
|
aa23f44555 | ||
|
|
901d75a1eb | ||
|
|
aa95286810 | ||
|
|
f6b3f661d6 | ||
|
|
0850d85791 | ||
|
|
c564400ac4 | ||
|
|
94ab545ffe | ||
|
|
e10df203b7 | ||
|
|
eea20a6eab | ||
|
|
5f208801ee | ||
|
|
0a22697e5d | ||
|
|
30cf4f0b00 | ||
|
|
e4bb88a725 | ||
|
|
e3822e6bc3 | ||
|
|
20d3be0d1d | ||
|
|
1785863686 | ||
|
|
ea4ced3cc1 | ||
|
|
149008d18b | ||
|
|
55a21d2eec | ||
|
|
c7491e631a | ||
|
|
468a205e36 | ||
|
|
bebe951a57 | ||
|
|
85a8ab32ef | ||
|
|
34ddbe170c | ||
|
|
e9846eb249 | ||
|
|
7cc418ac93 | ||
|
|
69532a4f23 | ||
|
|
f59419d96f | ||
|
|
7f288d0555 | ||
|
|
53afa8c276 | ||
|
|
22f4dd2f75 | ||
|
|
0989152024 | ||
|
|
f74809d361 | ||
|
|
9724cf7776 | ||
|
|
909e5438a8 | ||
|
|
3c534d87c0 | ||
|
|
4022a59705 | ||
|
|
138e7942da | ||
|
|
d7d26a3ae1 | ||
|
|
23504821cf | ||
|
|
b09da3e8f1 | ||
|
|
f3dd2fec99 | ||
|
|
462e375800 | ||
|
|
ca8c881375 | ||
|
|
96605a57d4 | ||
|
|
491ce40081 | ||
|
|
f33eb07bdd | ||
|
|
8bb1dc9b47 | ||
|
|
78b50472da | ||
|
|
e0259b37ed | ||
|
|
bf863a2594 | ||
|
|
edd174881e | ||
|
|
0bf747f6fc | ||
|
|
ab4d2b5d58 | ||
|
|
1b81280358 | ||
|
|
32f4eea3b8 | ||
|
|
1a3a49decb | ||
|
|
416717aff6 | ||
|
|
769d955a40 | ||
|
|
6de85b841d | ||
|
|
66db127245 | ||
|
|
b4c6af29e4 | ||
|
|
7192606e21 | ||
|
|
932be02e9e | ||
|
|
fc524894c6 | ||
|
|
f5196389e8 | ||
|
|
27be06c5c9 | ||
|
|
1d3ddb5e85 | ||
|
|
2145c104fd | ||
|
|
64e0d098e7 | ||
|
|
50d8cbb0ee | ||
|
|
9580397558 | ||
|
|
cf544b74f5 | ||
|
|
312f831efb | ||
|
|
f5bad5d28e | ||
|
|
9b7d255200 | ||
|
|
7a027bdd93 | ||
|
|
439a611a9e | ||
|
|
5f92b230aa | ||
|
|
29bc5303ae | ||
|
|
5314e5e7e9 | ||
|
|
c88462c99b | ||
|
|
0b552f1a7e | ||
|
|
552635a3c7 | ||
|
|
ca769bee39 | ||
|
|
b7ca0a0a14 | ||
|
|
84097a3179 | ||
|
|
8ba36b2588 | ||
|
|
e1d4ebc5f6 | ||
|
|
9e712d6089 | ||
|
|
90bea3dc6b | ||
|
|
bf480bb971 | ||
|
|
a94b48be50 | ||
|
|
abed42d848 | ||
|
|
3d6e795ca5 | ||
|
|
a3cbe8e9d4 | ||
|
|
0a2000098a | ||
|
|
a2348b5133 | ||
|
|
20d2f9d894 | ||
|
|
321f908e76 | ||
|
|
49875cb0e5 | ||
|
|
fa6a2c5bbb | ||
|
|
1074c00b60 | ||
|
|
8a8b10541e | ||
|
|
46cf4d677c | ||
|
|
94587d7515 | ||
|
|
14ec58ef9a | ||
|
|
8f4f6f3de0 | ||
|
|
f8c0ac3ce0 | ||
|
|
8ebad98912 | ||
|
|
08429b6110 | ||
|
|
0e128e15f1 | ||
|
|
b77a12fd0d | ||
|
|
a98526b398 | ||
|
|
5639bf9d48 | ||
|
|
c626685103 | ||
|
|
e233d15fbb | ||
|
|
a5d83900d9 | ||
|
|
d8dbeedcc2 | ||
|
|
56b67d62a3 | ||
|
|
dc084b4bd9 | ||
|
|
1bc0eab7ae | ||
|
|
ca14d1b108 | ||
|
|
d6757aced2 | ||
|
|
5c84eed292 | ||
|
|
b648387a57 | ||
|
|
5232f95c3f | ||
|
|
0742960ec4 | ||
|
|
4c41b7f8df | ||
|
|
c5d0c24237 | ||
|
|
8b5c51ceaa | ||
|
|
c09bceb66a | ||
|
|
e7afd3ec76 | ||
|
|
3d30be3472 | ||
|
|
e08367365f | ||
|
|
6692fbeed4 | ||
|
|
36a9e7a7cf | ||
|
|
49b5ff5fd9 | ||
|
|
1bde56a11a | ||
|
|
f47d7b6935 | ||
|
|
2dbad40a34 | ||
|
|
39f6a51794 | ||
|
|
7ec128c2e4 | ||
|
|
b55f0e849e | ||
|
|
f158390ba1 | ||
|
|
e4b245104a | ||
|
|
789497b07e | ||
|
|
5cf01ba099 | ||
|
|
e8669891f8 | ||
|
|
ac0f265a5b | ||
|
|
fcd6b430e1 | ||
|
|
f3ad8a9b80 | ||
|
|
43ff824da1 | ||
|
|
b8022610ca | ||
|
|
03defe203a | ||
|
|
aedcbe56b3 | ||
|
|
c365db460a | ||
|
|
cfdc4752d0 | ||
|
|
e1964ac5ed | ||
|
|
e17ab9cd8f | ||
|
|
edc15b8727 | ||
|
|
034f8d41fc | ||
|
|
0fa70db1e1 | ||
|
|
fa7ba9b72b | ||
|
|
3a20123e0f | ||
|
|
03510d1bc4 | ||
|
|
8b116f637a | ||
|
|
9c49de6552 | ||
|
|
842347bcab | ||
|
|
628b9c4853 | ||
|
|
d60b6ee33f | ||
|
|
4f4fcbbc70 | ||
|
|
cc896670dc | ||
|
|
eb2a497dee | ||
|
|
0cf5ce1416 | ||
|
|
988381d584 | ||
|
|
0b163eae23 | ||
|
|
3a3ff8a65e | ||
|
|
9f183a6dfc | ||
|
|
fadfd4e06c | ||
|
|
eb521faa8d | ||
|
|
6b572ca862 | ||
|
|
d075ec6716 | ||
|
|
14e6bf5ef9 | ||
|
|
b6bddd3b0e | ||
|
|
d5ed9b6cf5 | ||
|
|
7a9912d4e0 | ||
|
|
4d2ddceb4e | ||
|
|
ae2aed675a | ||
|
|
1d7cb41218 | ||
|
|
76db002eb5 | ||
|
|
ebb64ba177 | ||
|
|
1a685e2b68 | ||
|
|
9c561885a1 | ||
|
|
612e98b198 | ||
|
|
0c98082b25 |
26
.eslintrc.json
Normal file
26
.eslintrc.json
Normal file
@@ -0,0 +1,26 @@
|
||||
{
|
||||
"env": {
|
||||
"browser": true,
|
||||
"es6": true,
|
||||
"node": true,
|
||||
"mocha": true
|
||||
},
|
||||
"extends": [
|
||||
"eslint:recommended"
|
||||
],
|
||||
"parser": "@typescript-eslint/parser",
|
||||
"parserOptions": {
|
||||
"ecmaVersion": 2018,
|
||||
"sourceType": "module"
|
||||
},
|
||||
"plugins": [
|
||||
"@typescript-eslint"
|
||||
],
|
||||
"rules": {
|
||||
"no-useless-constructor": 0,
|
||||
"no-unused-vars": 0,
|
||||
"no-prototype-builtins": 0,
|
||||
"require-atomic-updates": 0,
|
||||
"no-dupe-class-members": 0
|
||||
}
|
||||
}
|
||||
13
.github/dependabot.yml
vendored
Normal file
13
.github/dependabot.yml
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
version: 2
|
||||
updates:
|
||||
- package-ecosystem: npm
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: monthly
|
||||
time: "15:00"
|
||||
open-pull-requests-limit: 10
|
||||
ignore:
|
||||
- dependency-name: jsonschema
|
||||
versions:
|
||||
- "> 1.2.2"
|
||||
- "< 2"
|
||||
67
.github/workflows/codeql-analysis.yml
vendored
Normal file
67
.github/workflows/codeql-analysis.yml
vendored
Normal file
@@ -0,0 +1,67 @@
|
||||
# For most projects, this workflow file will not need changing; you simply need
|
||||
# to commit it to your repository.
|
||||
#
|
||||
# You may wish to alter this file to override the set of languages analyzed,
|
||||
# or to provide custom queries or build logic.
|
||||
#
|
||||
# ******** NOTE ********
|
||||
# We have attempted to detect the languages in your repository. Please check
|
||||
# the `language` matrix defined below to confirm you have the correct set of
|
||||
# supported CodeQL languages.
|
||||
#
|
||||
name: "CodeQL"
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ develop, master ]
|
||||
pull_request:
|
||||
# The branches below must be a subset of the branches above
|
||||
branches: [ develop ]
|
||||
schedule:
|
||||
- cron: '44 5 * * 6'
|
||||
|
||||
jobs:
|
||||
analyze:
|
||||
name: Analyze
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
language: [ 'javascript' ]
|
||||
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python' ]
|
||||
# Learn more:
|
||||
# https://docs.github.com/en/free-pro-team@latest/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#changing-the-languages-that-are-analyzed
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v2
|
||||
|
||||
# Initializes the CodeQL tools for scanning.
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@v1
|
||||
with:
|
||||
languages: ${{ matrix.language }}
|
||||
# If you wish to specify custom queries, you can do so here or in a config file.
|
||||
# By default, queries listed here will override any specified in a config file.
|
||||
# Prefix the list here with "+" to use these queries and those in the config file.
|
||||
# queries: ./path/to/local/query, your-org/your-repo/queries@main
|
||||
|
||||
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
|
||||
# If this step fails, then you should remove it and run the build manually (see below)
|
||||
- name: Autobuild
|
||||
uses: github/codeql-action/autobuild@v1
|
||||
|
||||
# ℹ️ Command-line programs to run using the OS shell.
|
||||
# 📚 https://git.io/JvXDl
|
||||
|
||||
# ✏️ If the Autobuild fails above, remove it and uncomment the following three lines
|
||||
# and modify them (or add more) to build your code if your project
|
||||
# uses a compiled language
|
||||
|
||||
#- run: |
|
||||
# make bootstrap
|
||||
# make release
|
||||
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@v1
|
||||
@@ -1,4 +0,0 @@
|
||||
lib-cov
|
||||
coverage.html
|
||||
src
|
||||
dist/bower
|
||||
10
.prettierrc
Normal file
10
.prettierrc
Normal file
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"parser": "typescript",
|
||||
"printWidth": 80,
|
||||
"tabWidth": 2,
|
||||
"semi": false,
|
||||
"singleQuote": true,
|
||||
"trailingComma": "none",
|
||||
"quoteProps": "consistent",
|
||||
"bracketSpacing": false
|
||||
}
|
||||
@@ -1,11 +1,9 @@
|
||||
language: node_js
|
||||
node_js:
|
||||
- 6
|
||||
- 8
|
||||
- 10
|
||||
- 11
|
||||
- 12
|
||||
- 13
|
||||
script:
|
||||
- yarn compile
|
||||
- yarn test
|
||||
- yarn build
|
||||
- yarn lint
|
||||
|
||||
@@ -10,9 +10,19 @@ These sites are independent of Ripple and have not been authorized, endorsed, sp
|
||||
|
||||
Warning: Use at your own risk.
|
||||
|
||||
## Exchanges
|
||||
|
||||
- **[The World Exchange](https://www.theworldexchange.net/)**
|
||||
|
||||
Trade, issue, and send directly on the XRP Ledger. A user interface for the XRPL's decentralized exchange.
|
||||
|
||||
- **[Bitso](https://bitso.com/)**
|
||||
|
||||
Exchange allowing clients to buy and sell XRP, based in Mexico.
|
||||
|
||||
## Data and visualizations
|
||||
|
||||
- **[Wipple - XRP Intelligence](https://wipple.devnull.network/)**
|
||||
- **[xrpintel - XRP Intelligence](https://xrpintel.com/)**
|
||||
|
||||
Monitor the XRP Network in real time and explore historical statistics.
|
||||
|
||||
@@ -32,34 +42,40 @@ Warning: Use at your own risk.
|
||||
|
||||
Real-time XRP price, trades, and orderbook data from the XRP Ledger.
|
||||
|
||||
- **[Bithomp - XRP Explorer](https://bithomp.com/explorer/)**
|
||||
|
||||
Look up information by entering an address, transaction hash, username, or PayID.
|
||||
|
||||
- **[Bithomp - XRPL validators](https://bithomp.com/validators)**
|
||||
|
||||
List of XRPL validators, nodes, and testnet validators.
|
||||
|
||||
- **[XRP Scan - XRP Ledger explorer](https://http://xrpscan.com)**
|
||||
- **[XRP Scan - XRP Ledger explorer](https://xrpscan.com)**
|
||||
|
||||
XRP Ledger explorer, metrics and analytics.
|
||||
|
||||
- **[xrplorer](https://xrplorer.com)**
|
||||
|
||||
## Send and request payments
|
||||
XRP Ledger explorer, API, metrics, and analytics using a graph database that is synchronized live with the XRPL.
|
||||
|
||||
- **[XRP Tip Bot](https://www.xrptipbot.com/)**
|
||||
- **[zerptracker](https://zerptracker.com)**
|
||||
|
||||
A bot that enables users on reddit, Twitter and Discord to send XRP to each other through reddit comments and Twitter tweets.
|
||||
|
||||
- **[XRP Text](https://xrptext.com/)**
|
||||
|
||||
Send XRP using SMS text messages.
|
||||
|
||||
- **[XRParrot](https://xrparrot.com/)** (uses `ripple-address-codec`)
|
||||
|
||||
Easy EUR (SEPA) to XRP transfer (currency conversion).
|
||||
|
||||
- **[XRP Payment](https://xrpayments.co/)** (xrpayments.co)
|
||||
|
||||
Tool for generating a XRP payment request URI in a QR code, with currency converter.
|
||||
Monitor the XRPL using powerful JSONPath expressions, and receive notifications via email, SMS, webhooks, and more.
|
||||
|
||||
## Wallets and wallet tools
|
||||
|
||||
- **[XUMM](https://xumm.app/)**
|
||||
|
||||
Users can use the xumm application to track their accounts, balances and transactions. The true power of xumm is the platform available for developers.
|
||||
|
||||
- **[Xpring Wallet](https://xpring.io)** (uses `ripple-keypairs`)
|
||||
|
||||
Non-custodial XRP wallet.
|
||||
|
||||
- **[XRP Toolkit](https://www.xrptoolkit.com)**
|
||||
|
||||
A web interface to the XRP Ledger, supporting both hardware and software wallets.
|
||||
|
||||
- **[Toast Wallet](https://toastwallet.com/)**
|
||||
|
||||
A free, open source XRP Wallet for iOS, Android, Windows, Mac and Linux.
|
||||
@@ -84,11 +100,29 @@ Warning: Use at your own risk.
|
||||
|
||||
Recover a 24 word mnemonic if one word is wrong or one word is missing.
|
||||
|
||||
## Send and request payments
|
||||
|
||||
- **[XRP Tip Bot](https://www.xrptipbot.com/)**
|
||||
|
||||
A bot that enables users on reddit, Twitter and Discord to send XRP to each other through reddit comments and Twitter tweets.
|
||||
|
||||
- **[XRP Text](https://xrptext.com/)**
|
||||
|
||||
Send XRP using SMS text messages.
|
||||
|
||||
- **[XRParrot](https://xrparrot.com/)** (uses `ripple-address-codec`)
|
||||
|
||||
Easy EUR (SEPA) to XRP transfer (currency conversion).
|
||||
|
||||
- **[XRP Payment](https://xrpayments.co/)** (xrpayments.co)
|
||||
|
||||
Tool for generating a XRP payment request URI in a QR code, with currency converter.
|
||||
|
||||
## Development tools
|
||||
|
||||
- **[XRP Test Net Faucet](https://developers.ripple.com/xrp-test-net-faucet.html)**
|
||||
- **[XRP Faucets for Testnet and Devnet](https://xrpl.org/xrp-testnet-faucet.html)**
|
||||
|
||||
Get some test funds for development on the test network. The faucet was built using `ripple-lib`.
|
||||
Get some test funds for development on the test network. The faucet uses `ripple-lib`.
|
||||
|
||||
## Code samples and libraries
|
||||
|
||||
@@ -117,7 +151,3 @@ Warning: Use at your own risk.
|
||||
- **[XRP Stats](https://ledger.exposed/)** (ledger.exposed)
|
||||
|
||||
Rich list, live ledger stats and XRP distribution. Visualize escrows and flow of funds.
|
||||
|
||||
- **[XRP Vanity](https://xrpvanity.com/)** (xrpvanity.com)
|
||||
|
||||
Custom XRP addresses for sale, delivered by SetRegularKey.
|
||||
|
||||
151
Gulpfile.js
151
Gulpfile.js
@@ -1,151 +0,0 @@
|
||||
/* eslint-disable no-var, no-param-reassign */
|
||||
/* these eslint rules are disabled because gulp does not support babel yet */
|
||||
'use strict';
|
||||
const _ = require('lodash');
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const assert = require('assert');
|
||||
const gulp = require('gulp');
|
||||
const webpack = require('webpack');
|
||||
const UglifyJsPlugin = require('uglifyjs-webpack-plugin');
|
||||
|
||||
const pkg = require('./package.json');
|
||||
|
||||
const uglifyOptions = {
|
||||
mangle: {
|
||||
reserved: ['_', 'RippleError', 'RippledError', 'UnexpectedError',
|
||||
'LedgerVersionError', 'ConnectionError', 'NotConnectedError',
|
||||
'DisconnectedError', 'TimeoutError', 'ResponseFormatError',
|
||||
'ValidationError', 'NotFoundError', 'MissingLedgerHistoryError',
|
||||
'PendingLedgerVersionError'
|
||||
]
|
||||
}
|
||||
};
|
||||
|
||||
function getWebpackConfig(extension, overrides) {
|
||||
overrides = overrides || {};
|
||||
let defaults = {
|
||||
cache: true,
|
||||
externals: [{
|
||||
'lodash': '_'
|
||||
}],
|
||||
entry: './src/index.ts',
|
||||
output: {
|
||||
library: 'ripple',
|
||||
path: path.join(__dirname, 'build/'),
|
||||
filename: `ripple-${pkg.version}${extension}`
|
||||
},
|
||||
plugins: [
|
||||
new webpack.NormalModuleReplacementPlugin(/^ws$/, './wswrapper'),
|
||||
new webpack.NormalModuleReplacementPlugin(/^\.\/wallet$/, './wallet-web'),
|
||||
new webpack.NormalModuleReplacementPlugin(/^.*setup-api$/,
|
||||
'./setup-api-web')
|
||||
],
|
||||
module: {
|
||||
rules: [{
|
||||
test: /jayson/,
|
||||
use: 'null',
|
||||
}, {
|
||||
test: /\.ts$/,
|
||||
use: [{
|
||||
loader: 'ts-loader',
|
||||
options: {
|
||||
compilerOptions: {
|
||||
composite: false,
|
||||
declaration: false,
|
||||
declarationMap: false
|
||||
}
|
||||
},
|
||||
}],
|
||||
}]
|
||||
},
|
||||
resolve: {
|
||||
extensions: [ '.ts', '.js' ]
|
||||
},
|
||||
};
|
||||
return _.assign({}, defaults, overrides);
|
||||
}
|
||||
|
||||
function webpackConfigForWebTest(testFileName) {
|
||||
var match = testFileName.match(/\/?([^\/]*)-test.js$/);
|
||||
if (!match) {
|
||||
assert(false, 'wrong filename:' + testFileName);
|
||||
}
|
||||
var configOverrides = {
|
||||
externals: [{
|
||||
'lodash': '_',
|
||||
'ripple-api': 'ripple',
|
||||
'net': 'null'
|
||||
}],
|
||||
entry: testFileName,
|
||||
output: {
|
||||
library: match[1].replace(/-/g, '_'),
|
||||
path: path.join(__dirname, 'test-compiled-for-web/'),
|
||||
filename: match[1] + '-test.js'
|
||||
}
|
||||
};
|
||||
return getWebpackConfig('.js', configOverrides);
|
||||
}
|
||||
|
||||
function createLink(from, to) {
|
||||
if (fs.existsSync(to)) {
|
||||
fs.unlinkSync(to);
|
||||
}
|
||||
fs.linkSync(from, to);
|
||||
}
|
||||
|
||||
function createBuildLink(callback) {
|
||||
return function(err, res) {
|
||||
createLink('./build/ripple-' + pkg.version + '.js',
|
||||
'./build/ripple-latest.js');
|
||||
callback(err, res);
|
||||
};
|
||||
}
|
||||
|
||||
function watch(callback) {
|
||||
gulp.watch('src/*', gulp.series(buildDebug));
|
||||
callback();
|
||||
}
|
||||
|
||||
function build(callback) {
|
||||
webpack(getWebpackConfig('.js'), createBuildLink(callback));
|
||||
}
|
||||
|
||||
function buildDebug(callback) {
|
||||
const webpackConfig = getWebpackConfig('-debug.js', {devtool: 'eval'});
|
||||
webpackConfig.plugins.unshift(new webpack.LoaderOptionsPlugin({debug: true}));
|
||||
webpack(webpackConfig, callback);
|
||||
}
|
||||
|
||||
function buildMin(callback) {
|
||||
const webpackConfig = getWebpackConfig('-min.js');
|
||||
webpackConfig.plugins.push(new UglifyJsPlugin({uglifyOptions}));
|
||||
webpack(webpackConfig, function() {
|
||||
createLink('./build/ripple-' + pkg.version + '-min.js',
|
||||
'./build/ripple-latest-min.js');
|
||||
callback();
|
||||
});
|
||||
}
|
||||
|
||||
function buildTests(callback) {
|
||||
var times = 0;
|
||||
function done() {
|
||||
if (++times >= 5) {
|
||||
callback();
|
||||
}
|
||||
}
|
||||
webpack(webpackConfigForWebTest('./test/rangeset-test.js'), done);
|
||||
webpack(webpackConfigForWebTest('./test/connection-test.js'), done);
|
||||
webpack(webpackConfigForWebTest('./test/api-test.js'), done);
|
||||
webpack(webpackConfigForWebTest('./test/broadcast-api-test.js'), done);
|
||||
webpack(webpackConfigForWebTest('./test/integration/integration-test.js',
|
||||
'integration/'), done);
|
||||
}
|
||||
|
||||
exports.watch = watch;
|
||||
exports.build = build;
|
||||
exports.buildDebug = buildDebug;
|
||||
exports.buildMin = buildMin;
|
||||
exports.buildTests = buildTests;
|
||||
|
||||
exports.default = gulp.parallel(build, buildDebug, buildMin);
|
||||
338
HISTORY.md
338
HISTORY.md
@@ -1,5 +1,341 @@
|
||||
# ripple-lib Release History
|
||||
|
||||
Subscribe to [the **ripple-lib-announce** mailing list](https://groups.google.com/forum/#!forum/ripple-lib-announce) for release announcements. We recommend that ripple-lib users stay up-to-date with the latest stable release.
|
||||
|
||||
## 1.9.3 (2021-03-16)
|
||||
|
||||
* Expose ripple-address-codec methods. These are static methods on RippleAPI, so you do not need to create a RippleAPI instance.
|
||||
* `classicAddressToXAddress` / `xAddressToClassicAddress`
|
||||
* `isValidXAddress` / `isValidClassicAddress`
|
||||
* `encodeSeed` / `decodeSeed`
|
||||
* `encodeAccountID` / `decodeAccountID`
|
||||
* `encodeNodePublic` / `decodeNodePublic`
|
||||
* `encodeAccountPublic` / `decodeAccountPublic`
|
||||
* `encodeXAddress` / `decodeXAddress`
|
||||
|
||||
Example 1. Encode an X-address with tag 4294967295:
|
||||
```js
|
||||
const RippleAPI = require('ripple-lib').RippleAPI
|
||||
const xAddress = RippleAPI.classicAddressToXAddress('rGWrZyQqhTp9Xu7G5Pkayo7bXjH4k4QYpf', 4294967295)
|
||||
console.log(xAddress)
|
||||
```
|
||||
|
||||
Output for Example 1:
|
||||
```
|
||||
XVLhHMPHU98es4dbozjVtdWzVrDjtV18pX8yuPT7y4xaEHi
|
||||
```
|
||||
|
||||
Example 2. Encode a test address for use with Testnet or Devnet:
|
||||
```js
|
||||
const RippleAPI = require('ripple-lib').RippleAPI
|
||||
const address = RippleAPI.classicAddressToXAddress('r3SVzk8ApofDJuVBPKdmbbLjWGCCXpBQ2g', 123, true)
|
||||
console.log(address)
|
||||
```
|
||||
|
||||
Output for Example 2:
|
||||
```
|
||||
T7oKJ3q7s94kDH6tpkBowhetT1JKfcfdSCmAXbS75iATyLD
|
||||
```
|
||||
|
||||
Example 3. Decode an X-address:
|
||||
```js
|
||||
const RippleAPI = require('ripple-lib').RippleAPI
|
||||
const address = RippleAPI.xAddressToClassicAddress('XVLhHMPHU98es4dbozjVtdWzVrDjtV18pX8yuPT7y4xaEHi')
|
||||
console.log(address)
|
||||
```
|
||||
|
||||
Output for Example 3:
|
||||
```js
|
||||
{
|
||||
classicAddress: 'rGWrZyQqhTp9Xu7G5Pkayo7bXjH4k4QYpf',
|
||||
tag: 4294967295,
|
||||
test: false
|
||||
}
|
||||
```
|
||||
|
||||
## 1.9.2 (2021-03-12)
|
||||
|
||||
* Docs
|
||||
* Add missing transaction type links (#1378)
|
||||
* Bug fixes
|
||||
* Deserialization and verification of payment paths (#1382) (#1347) (#1376)
|
||||
* Dependencies
|
||||
* Bump ripple-binary-codec to 1.1.2
|
||||
* Bump lodash, ripple-address-codec
|
||||
|
||||
The SHA-256 checksums for the browser version of this release can be found below.
|
||||
```
|
||||
% shasum -a 256 build/*
|
||||
a1fd24b65d81ea5dbc36d74da7a6317267a048bba084effff5380d47299c3c63 build/ripple-latest-min.js
|
||||
fc17a5572001d814ea6b81aa701fcb66882ec031c68afb769a8ea8b71c6529a6 build/ripple-latest-min.js.LICENSE.txt
|
||||
410f78105c4f23c13671ec94f963ef47179393bfcad65ff610bc838c5a3c6a65 build/ripple-latest.js
|
||||
```
|
||||
|
||||
## 1.9.1 (2021-02-25)
|
||||
|
||||
* Docs
|
||||
* Add transaction specifications: (#1352)
|
||||
* Ticket Create
|
||||
* Account Delete
|
||||
* Deposit Preauth
|
||||
* Update link to subscribe page (#1354)
|
||||
* Bug fixes
|
||||
* Allow connectionTimeout option to be customized (#1355)
|
||||
* Dependencies
|
||||
* Bump ripple-keypairs to 1.0.3
|
||||
* Bump elliptic to 6.5.4 (this patches a potential security issue, although we do not believe that the issue affects ripple-lib: [details](https://github.com/ripple/ripple-keypairs/security/advisories/GHSA-w6x3-9ph2-7x54))
|
||||
|
||||
The SHA-256 checksums for the browser version of this release can be found below.
|
||||
```
|
||||
% shasum -a 256 build/*
|
||||
f59e0221a7218460eea59b0441a0ee2d2a14484dd473ed5373283852798516c7 build/ripple-latest-min.js
|
||||
fc17a5572001d814ea6b81aa701fcb66882ec031c68afb769a8ea8b71c6529a6 build/ripple-latest-min.js.LICENSE.txt
|
||||
731ed44cbff8db26bcf256e0e3f3ac3fe90a10b6c227701d67918a5d643c5b29 build/ripple-latest.js
|
||||
```
|
||||
|
||||
## 1.9.0 (2020-12-07)
|
||||
|
||||
* New features
|
||||
* Support for tickets (TicketBatch amendment required - not yet activated on live/main network)
|
||||
* `prepareTicketCreate`
|
||||
* Types: Add LedgerClosedEvent and export more types
|
||||
* Docs
|
||||
* Improve descriptions of get-ledger response time fields
|
||||
* Applications
|
||||
* Add Bithomp explorer
|
||||
* Add example of reliable transaction submission
|
||||
* Node.js
|
||||
* Require Node.js version 10.13.0+
|
||||
* Internal
|
||||
* Update webpack, webpack-cli, mocha, nyc, ripple-binary-codec
|
||||
* Run prettier to format code
|
||||
|
||||
The SHA-256 checksums for the browser version of this release can be found below.
|
||||
```
|
||||
% shasum -a 256 build/*
|
||||
2d3ae057ad637df272f98cfe940ea9e1317588e5bbf4fee47c8b16d6e6e71d85 build/ripple-latest-min.js
|
||||
8cbbc7bb482f68bcc8d411bae2e42effdb14ddfa562fcbc329a373910b85cf8c build/ripple-latest.js
|
||||
```
|
||||
|
||||
## 1.8.2 (2020-10-23)
|
||||
|
||||
* Bug fixes
|
||||
* Browser compatibility: Use ripple-binary-codec 0.2.x to prevent browser issues (#1321)
|
||||
* Memory leak: Clear awaiting response promises to prevent memory leak (#1302)
|
||||
* Feature: getSettings() - allow ledgerVersion to be 'validated', 'closed', or 'current' (#1298)
|
||||
* Docs: Update APPLICATIONS.md
|
||||
|
||||
The SHA-256 checksums for the browser version of this release can be found below.
|
||||
```
|
||||
% shasum -a 256 *
|
||||
ba760c36028b8a3ce267386e188a422890dfb1b03bc87c852a4c2034ea9bac2e ripple-latest-min.js
|
||||
7e5281eb9623602284b9f11564f0f3a36cfde305f2c2f7a32e0d29a04913c817 ripple-latest.js
|
||||
```
|
||||
|
||||
## 1.8.1 (2020-09-25)
|
||||
|
||||
* Internal
|
||||
* Bump elliptic to 6.5.3 (this patches a potential security issue, although we do not believe that the issue affects ripple-lib)
|
||||
* Bump ripple-binary-codec to 1.0.2
|
||||
* Bump lodash to 4.17.19
|
||||
|
||||
The SHA-256 checksums for the browser version of this release can be found below.
|
||||
```
|
||||
% shasum -a 256 *
|
||||
0895f349944fa11bb1976b2c350c0eb143dfd09abbfc7c2be33aed5c2a4b9ee8 ripple-latest-min.js
|
||||
7c00188a28f9d295d8e66aa08b340294d2fe49f635d154fb0df049ae8572c195 ripple-latest.js
|
||||
```
|
||||
|
||||
## 1.8.0 (2020-07-06)
|
||||
|
||||
* [Document `request('submit', ...)` method](https://github.com/ripple/ripple-lib/blob/develop/docs/index.md#submit), which includes additional useful information in the response
|
||||
* Update [list of applications using ripple-lib](https://github.com/ripple/ripple-lib/blob/1.7.0/APPLICATIONS.md)
|
||||
|
||||
## 1.7.1 (2020-05-26)
|
||||
|
||||
* Fix preparePayment when using source.amount/destination.minAmount (#1295) (Fix #1237) (Thanks to @leobel)
|
||||
* Docs
|
||||
* Fix generateXAddress example (#1286)
|
||||
* Update Transaction Streams link (#1278)
|
||||
* Dependencies
|
||||
* Update assert-diff, mocha, webpack-bundle-analyzer, @typescript-eslint/parser, @typescript-eslint/eslint-plugin, @types/ws, @types/node, ws, ts-node, eventemitter2
|
||||
|
||||
## 1.7.0 (2020-04-28)
|
||||
|
||||
* Export hashing functions (#1275)
|
||||
* Add failHard (fail_hard) option in `submit` method (#1029)
|
||||
* Add type for parseAccountFlags (#1258)
|
||||
* Add api.connection.getReserveBase() (#1259)
|
||||
* Travis: remove node 8 (#1257)
|
||||
* Dependencies
|
||||
* Update ripple-address-codec, @types/ws, @types/lodash, https-proxy-agent
|
||||
* Update devDependencies: eventemitter2, nyc, ejs, @types/node, webpack, ts-node, prettier, @typescript-eslint/eslint-plugin
|
||||
|
||||
## 1.6.5 (2020-03-23)
|
||||
|
||||
* APPLICATIONS.md: Add xrplorer.com
|
||||
* Internal: Fix typos
|
||||
* Dependencies
|
||||
* Update @types/ws, @types/node, @typescript-eslint/eslint-plugin, @types/mocha, webpack, typescript, mocha, assert-diff
|
||||
* Remove mocha-junit-reporter
|
||||
|
||||
## 1.6.4 (2020-02-18)
|
||||
|
||||
* Fix generateXAddress() and generateAddress() with no entropy (#1211, #1209)
|
||||
* Internal
|
||||
* Improve unit tests
|
||||
* Dependencies
|
||||
* Update webpack-cli, @types/node, webpack, @typescript-eslint/eslint-plugin,
|
||||
typescript, ripple-keypairs
|
||||
|
||||
## 1.6.3 (2020-02-05)
|
||||
|
||||
* Update ripple-keypairs to 1.0.0
|
||||
* Bug fix: Assign event listener to socket close event on open before attempting post-open logic (#1186)
|
||||
* Protects against possible unhandled rejection in disconnect
|
||||
* Adds the Connection `_ws.close` event listener post `_ws.open` before executing any post `_ws.open` logic, i.e. `Connection._subscribeToLedger`
|
||||
* This prevents a reconnection error loop that occurs if `Connection._ws` is never cleaned up by the unreachable `_ws.close` event listener
|
||||
* Also ensures that a possible disconnect() promise rejection is not unhandled if any `_ws.open` logic in `Connection.connect()` throws
|
||||
* Dependencies
|
||||
* Update mocha-junit-reporter, @types/node, mocha, @typescript-eslint/eslint-plugin, ripple-address-codec
|
||||
|
||||
## 1.6.2 (2020-01-17)
|
||||
|
||||
* Bug fix: Catch possible error in reconnect() on _heartbeat(), emit reconnect error (#1179)
|
||||
* Docs: Fix whitespace
|
||||
* Dependencies
|
||||
* Update @typescript-eslint/eslint-plugin, ts-node, @types/node, @types/ws, typescript
|
||||
|
||||
## 1.6.1 (2020-01-14)
|
||||
|
||||
> **Update Note:** In this release we refactored the internal connection logic of ripple-lib to improve resiliency across dropped messages and reconnects. The external interface remains the same, with zero changes to public methods/properties. However, If you experience any problems around connections, requests, and request retries, please [file an issue]( https://github.com/ripple/ripple-lib/issues/new) with the repo (and be sure to test against v1.6.0 to confirm that the problem was introduced in this version).
|
||||
|
||||
* Documentation
|
||||
* Document message type 'path_find' (#1121) (thanks @r0bertz)
|
||||
* Improve documentation for address generation; functions that can be called offline; generateXAddress() (#1158, #1159, #1169) (thanks @hbergren)
|
||||
* Add [Security Policy](https://github.com/ripple/ripple-lib/blob/develop/SECURITY.md)
|
||||
* Bug fixes
|
||||
* Types: Fix AccountObjectsResponse structure (#1127) (thanks @you21979)
|
||||
* In some cases, ripple-lib would fail to wait for the connection to be ready (#1119)
|
||||
* Dependencies
|
||||
* Update docs dependencies, ejs and doctoc (#1153)
|
||||
* Update eslint, ripple-lib-transactionparser, typescript, nyc, ws, @types/node, ripple-binary-codec, mocha, mocha-junit-reporter
|
||||
* Internal
|
||||
* Add LedgerHistory to Connection (#1119): Moved ledger logic into its own Ledger class
|
||||
|
||||
## 1.6.0 (2020-01-06)
|
||||
|
||||
* Add support for AccountDelete (#1120)
|
||||
* Improve error type given on rejected message _send to be DisconnectedError (#1098)
|
||||
* Internal
|
||||
* Add unit test for unhandled promise rejection warning on message _send (#1098)
|
||||
* Dependencies
|
||||
* Update @types/node, @typescript-eslint/parser
|
||||
|
||||
## 1.5.1 (2019-12-28)
|
||||
|
||||
* Fix support for CDNs (#1142)
|
||||
* Internal
|
||||
* Clean up connection trace logic (#1114)
|
||||
* Clean up the connection config (#1115)
|
||||
* Run prettier format (#1116)
|
||||
* Update eslint command (#1118)
|
||||
* Dependencies
|
||||
* Update webpack-cli, webpack, ts-node, @types/lodash, @types/ws, @types/node, @typescript-eslint/parser, @typescript-eslint/eslint-plugin, https-proxy-agent, mocha, eventemitter2
|
||||
|
||||
## 1.5.0 (2019-12-14)
|
||||
|
||||
* Add support for `WalletLocator` (#1083)
|
||||
* Types: Move and de-dupe `TransactionJSON` type (#1096)
|
||||
* This resolves an error surfaced by [TypeScript 3.7](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-7.html#local-and-imported-type-declarations-now-conflict)
|
||||
* Add a heartbeat to detect hung connections (#1101)
|
||||
* Dependencies
|
||||
* Update TypeScript version (#1096)
|
||||
* Update ripple-lib-transactionparser to 0.8.1 (#1097)
|
||||
* Update ripple-binary-codec to 0.2.5
|
||||
* Update webpack (#1112)
|
||||
* Require node 8 and yarn (#1107)
|
||||
* Testing: Refactor and add unit tests
|
||||
* Fix some errors caught by the improved tests
|
||||
|
||||
## 1.4.2 (2019-11-14)
|
||||
|
||||
* Add support for tick size (#1090) (thanks @RareData)
|
||||
* Update email hash default to allow proper clearing (#1089) (thanks @RareData)
|
||||
* Fix Unhandled Promise Rejection Warning on message `_send`
|
||||
* Add an immediate catch to the `_send` promise passed to `_whenReady` in case there is rejection before async handlers are added (#1092) (thanks @nickewansmith)
|
||||
* Docs improvements
|
||||
* Add XRP Toolkit reference (#1088)
|
||||
* Internal improvements
|
||||
* Add a prettier config
|
||||
* Update Node.js Testing Versions (#1085)
|
||||
* Testing matrix based on: https://nodejs.org/en/about/releases/
|
||||
- Node 11 is no longer supported (not LTS)
|
||||
- Node 12 added (active LTS)
|
||||
- Node 13 added ("current" release)
|
||||
|
||||
## 1.4.1 (2019-11-06)
|
||||
|
||||
* Compatibility: Change TypeScript compile target back to `es6` (#1071)
|
||||
* WARNING: This allows for the use of Node v6, which is no longer supported by Node.js, as it was end-of-life'd in April 2019
|
||||
* We recommend updating to Node v8/v10 ASAP in order to get security updates and fixes from the Node.js team
|
||||
* We are not actively running tests against Node v6 (ref #1076)
|
||||
* Docs: `getAccountObjects` doc fix
|
||||
* Dependencies:
|
||||
* Update `bignumber.js`
|
||||
* Update `ripple-keypairs`
|
||||
* Update `ws`
|
||||
* Build process: Update `webpack` flow
|
||||
|
||||
## 1.4.0 (2019-10-28)
|
||||
|
||||
* Unref timer so it does not hang the Node.js process
|
||||
* Add a 2-second timeout for connect()
|
||||
* Improve getTransaction() error when tx has not been validated yet
|
||||
* Add support for the new X-address format
|
||||
* Fix error in Safari, Chrome 78, Firefox 70
|
||||
* Some error messages have changed slightly. For example:
|
||||
* `-instance.Account is not of a type(s) string,instance.Account does not conform to the "address" format`
|
||||
* `+instance.Account is not of a type(s) string,instance.Account is not exactly one from <xAddress>,<classicAddress>`
|
||||
|
||||
### Internal improvements
|
||||
|
||||
* Reduce dependency size
|
||||
* Move tests to TypeScript
|
||||
* Replace tslint with eslint
|
||||
* Update https-proxy-agent
|
||||
* Add tests
|
||||
|
||||
## 1.3.4 (2019-10-18)
|
||||
|
||||
* Update ripple-lib-transactionparser
|
||||
* Improve error message when signing fails (e.g. due to trailing zeros)
|
||||
* Integrate ripple-hashes (in TypeScript with improved naming and docs)
|
||||
* Add multi-signing example to sign() method docs
|
||||
* Update TypeScript
|
||||
|
||||
## 1.3.3 (2019-09-10)
|
||||
|
||||
* Expand node version compatibility to support Node.js 12 ([ripple-binary-codec#32](https://github.com/ripple/ripple-binary-codec/issues/32))
|
||||
|
||||
## 1.3.2 (2019-09-03)
|
||||
|
||||
* Export and document `rippleTimeToISO8601()` method
|
||||
* Add type for isValidAddress (fixes error TS7016, #1032)
|
||||
* Docs: update recommended Node.js version (#1031)
|
||||
|
||||
When using this release with [rippled](https://github.com/ripple/rippled), we recommend using [rippled version 1.3.1](https://github.com/ripple/rippled/releases/tag/1.3.1) or later.
|
||||
|
||||
## 1.3.1 (2019-08-26)
|
||||
|
||||
* Upgrade to gulp 4 (#1030)
|
||||
* Remove http server (unused)
|
||||
* Update dependencies
|
||||
|
||||
There are no changes in the browser version with this release. The npm package for Node.js should be slightly smaller.
|
||||
|
||||
When using this release with [rippled](https://github.com/ripple/rippled), we recommend using [rippled version 1.3.1](https://github.com/ripple/rippled/releases/tag/1.3.1).
|
||||
|
||||
## 1.3.0 (2019-08-16)
|
||||
|
||||
### Bug fixes:
|
||||
@@ -334,7 +670,7 @@ f28921f57a133678dcb3cb54c497626bd76b1f953d22d61f3ddca31c8947d552 ripple-1.1.0-m
|
||||
The SHA-256 checksums for the browser version of this release can be found
|
||||
below.
|
||||
```
|
||||
% shasum -a 256 *
|
||||
% shasum -a 256 *
|
||||
2556fe17296e127ed44e7066e90a6175e2b164f00ca3c1aa7b1c554f31c688dd ripple-1.0.2-debug.js
|
||||
e0342ea21eac32a1024c62034fba09c6f26dd3e7371b23ea1e153e03135cd590 ripple-1.0.2-min.js
|
||||
c7286c517497d018d02d09257e81172b61d36c8b9885a077af68e8133c3b3b9b ripple-1.0.2.js
|
||||
|
||||
66
README.md
66
README.md
@@ -1,9 +1,19 @@
|
||||
# ripple-lib
|
||||
# ripple-lib (RippleAPI)
|
||||
|
||||
A JavaScript API for interacting with the XRP Ledger
|
||||
A JavaScript/TypeScript API for interacting with the XRP Ledger
|
||||
|
||||
[](https://www.npmjs.org/package/ripple-lib)
|
||||
|
||||
This is the recommended library for integrating a JavaScript/TypeScript app with the XRP Ledger, especially if you intend to use advanced functionality such as IOUs, payment paths, the decentralized exchange, account settings, payment channels, escrows, multi-signing, and more.
|
||||
|
||||
## [➡️ Reference Documentation](https://xrpl.org/rippleapi-reference.html)
|
||||
|
||||
See the full reference documentation on the XRP Ledger Dev Portal.
|
||||
|
||||
## [➡️ Applications and Projects](APPLICATIONS.md)
|
||||
|
||||
What is ripple-lib used for? The applications on the list linked above use `ripple-lib`. Open a PR to add your app or project to the list!
|
||||
|
||||
### Features
|
||||
|
||||
+ Connect to a `rippled` server from Node.js or a web browser
|
||||
@@ -12,25 +22,27 @@ A JavaScript API for interacting with the XRP Ledger
|
||||
+ Sign and submit transactions to the XRP Ledger
|
||||
+ Type definitions for TypeScript
|
||||
|
||||
### Requirements
|
||||
|
||||
+ **[Node.js v14](https://nodejs.org/)** is recommended. Other versions may work but are not frequently tested.
|
||||
+ **[Yarn](https://yarnpkg.com/)** is recommended. `npm` may work but we use `yarn.lock`.
|
||||
|
||||
## Getting Started
|
||||
|
||||
See also: [RippleAPI Beginners Guide](https://xrpl.org/get-started-with-rippleapi-for-javascript.html)
|
||||
|
||||
### Requirements
|
||||
|
||||
+ **[Node v10](https://nodejs.org/)** is recommended. Other versions may work but are not frequently tested.
|
||||
+ **[Yarn](https://yarnpkg.com/)** is recommended. `npm` may work but we use `yarn.lock`.
|
||||
|
||||
### Install
|
||||
|
||||
In an existing project (with `package.json`), install `ripple-lib`:
|
||||
```
|
||||
$ yarn add ripple-lib
|
||||
```
|
||||
|
||||
Then see the [documentation](https://github.com/ripple/ripple-lib/blob/develop/docs/index.md) and [code samples](https://github.com/ripple/ripple-lib/tree/develop/docs/samples).
|
||||
Then see the documentation:
|
||||
|
||||
**What is ripple-lib used for?** Here's a [list of applications](APPLICATIONS.md) that use `ripple-lib`. Open a PR to add your app or project to the list!
|
||||
## Documentation
|
||||
|
||||
+ [RippleAPI Beginners Guide](https://xrpl.org/get-started-with-rippleapi-for-javascript.html)
|
||||
+ [RippleAPI Full Reference Documentation](https://xrpl.org/rippleapi-reference.html) ([in this repo](https://github.com/ripple/ripple-lib/blob/develop/docs/index.md))
|
||||
+ [Code Samples](https://github.com/ripple/ripple-lib/tree/develop/docs/samples)
|
||||
|
||||
### Mailing Lists
|
||||
|
||||
@@ -44,35 +56,41 @@ If you're using the XRP Ledger in production, you should run a [rippled server](
|
||||
|
||||
## Development
|
||||
|
||||
To build the library for Node.js:
|
||||
```
|
||||
$ yarn compile
|
||||
```
|
||||
|
||||
The TypeScript compiler will [output](./tsconfig.json#L7) the resulting JS files in `./dist/npm/`.
|
||||
|
||||
To build the library for the browser:
|
||||
To build the library for Node.js and the browser:
|
||||
```
|
||||
$ yarn build
|
||||
```
|
||||
|
||||
Gulp will [output](./Gulpfile.js) the resulting JS files in `./build/`.
|
||||
The TypeScript compiler will [output](./tsconfig.json#L7) the resulting JS files in `./dist/npm/`.
|
||||
|
||||
webpack will output the resulting JS files in `./build/`.
|
||||
|
||||
For details, see the `scripts` in `package.json`.
|
||||
|
||||
## Running Tests
|
||||
|
||||
### Unit Tests
|
||||
|
||||
1. Clone the repository
|
||||
2. `cd` into the repository and install dependencies with `yarn install`
|
||||
3. `yarn test`
|
||||
|
||||
Also, run `yarn lint` to lint the code with `tslint`.
|
||||
### Linting
|
||||
|
||||
Run `yarn lint` to lint the code with `eslint`.
|
||||
|
||||
## Generating Documentation
|
||||
|
||||
The continuous integration tests require that the documentation stays up-to-date. If you make changes to the JSON schemas, fixtures, or documentation sources, you must update the documentation by running `yarn run docgen`.
|
||||
Do not edit `./docs/index.md` directly because it is a generated file.
|
||||
|
||||
Instead, edit the appropriate `.md.ejs` files in `./docs/src/`.
|
||||
|
||||
If you make changes to the JSON schemas, fixtures, or documentation sources, update the documentation by running `yarn run docgen`.
|
||||
|
||||
## More Information
|
||||
|
||||
+ [RippleAPI Reference](https://developers.ripple.com/rippleapi-reference.html) - XRP Ledger Dev Portal
|
||||
+ [XRP Ledger Dev Portal](https://developers.ripple.com/)
|
||||
+ [ripple-lib-announce mailing list](https://groups.google.com/forum/#!forum/ripple-lib-announce) - subscribe for release announcements
|
||||
+ [RippleAPI Reference](https://xrpl.org/rippleapi-reference.html) - XRP Ledger Dev Portal
|
||||
+ [XRP Ledger Dev Portal](https://xrpl.org/)
|
||||
|
||||
[](https://travis-ci.org/ripple/ripple-lib)
|
||||
|
||||
29
SECURITY.md
Normal file
29
SECURITY.md
Normal file
@@ -0,0 +1,29 @@
|
||||
# Security Policy
|
||||
|
||||
## Supported Versions
|
||||
|
||||
This table shows which versions of ripple-lib are currently supported with security updates:
|
||||
|
||||
| Version | Supported |
|
||||
| ------- | ---------------------- |
|
||||
| 1.x | :white_check_mark: Yes |
|
||||
| 0.x | :x: No |
|
||||
|
||||
## Responsible disclosure security policy
|
||||
|
||||
The responsible disclosure of vulnerabilities helps to protect users of the project. Vulnerabilities are first triaged in a private manner, and only publicly disclosed after a reasonable time period that allows patching the vulnerability and provides an upgrade path for users.
|
||||
|
||||
When contacting us directly via email, we will do our best to respond in a reasonable time to resolve the issue. Do not disclose the vulnerability until it has been patched and users have been given time to upgrade.
|
||||
|
||||
We kindly ask you to refrain from malicious acts that put our users, the project, or any of the project’s team members at risk.
|
||||
|
||||
## Reporting a security issue
|
||||
|
||||
Security is a top priority. But no matter how much effort we put into security, there can still be vulnerabilities present.
|
||||
|
||||
If you discover a security vulnerability, please use the following means of communications to report it to us:
|
||||
|
||||
- Report the security issue to bugs@ripple.com
|
||||
- [Ripple Bug Bounty](https://ripple.com/bug-bounty/)
|
||||
|
||||
Your efforts to responsibly disclose your findings are sincerely appreciated and will be taken into account to acknowledge your contributions.
|
||||
1302
docs/index.md
1302
docs/index.md
File diff suppressed because it is too large
Load Diff
@@ -1,3 +1,5 @@
|
||||
Usage:
|
||||
babel-node balances.js
|
||||
babel-node cancelall.js (requires setting address and secret in source file first)
|
||||
babel-node payment.js (requires setting address and secret in source file first)
|
||||
babel-node ticket.js (requires setting address and secret in source file first)
|
||||
|
||||
31
docs/samples/ticket.js
Normal file
31
docs/samples/ticket.js
Normal file
@@ -0,0 +1,31 @@
|
||||
'use strict';
|
||||
const RippleAPI = require('../../src').RippleAPI; // require('ripple-lib')
|
||||
|
||||
const address = 'INSERT ADDRESS HERE';
|
||||
const secret = 'INSERT SECRET HERE';
|
||||
|
||||
const api = new RippleAPI({server: 'wss://s1.ripple.com:443'});
|
||||
const instructions = {
|
||||
maxLedgerVersionOffset: 5
|
||||
};
|
||||
const numberOfTickets = 1;
|
||||
|
||||
function quit(message) {
|
||||
console.log(message);
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
function fail(message) {
|
||||
console.error(message);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
api.connect().then(() => {
|
||||
console.log('Connected...');
|
||||
return api.prepareTicketCreate(address, numberOfTickets, instructions).then(prepared => {
|
||||
console.log('Ticket transaction prepared...');
|
||||
const {signedTransaction} = api.sign(prepared.txJSON, secret);
|
||||
console.log('Ticket transaction signed...');
|
||||
api.submit(signedTransaction).then(quit, fail);
|
||||
});
|
||||
}).catch(fail);
|
||||
@@ -6,11 +6,23 @@
|
||||
"r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59"
|
||||
```
|
||||
|
||||
Every XRP Ledger account has an *address*, which is a base58-encoding of a hash of the account's public key. XRP Ledger addresses always start with the lowercase letter `r`.
|
||||
```json
|
||||
"X7AcgcsBL6XDcUb289X4mJ8djcdyKaB5hJDWMArnXr61cqZ"
|
||||
```
|
||||
|
||||
An *address* refers to a specific XRP Ledger account. It is a base-58 encoding of a hash of the account's public key. There are two kinds of addresses in common use:
|
||||
|
||||
### Classic Address
|
||||
|
||||
A *classic address* encodes a hash of the account's public key and a checksum. It has no other data. This kind of address always starts with the lowercase letter `r`.
|
||||
|
||||
### X-address
|
||||
|
||||
An *X-address* encodes a hash of the account's public key, a tag, and a checksum. This kind of address starts with the uppercase letter `X` if it is intended for use on the production XRP Ledger (mainnet). It starts with the uppercase letter `T` if it is intended for use on a test network such as Testnet or Devnet.
|
||||
|
||||
## Account Sequence Number
|
||||
|
||||
Every XRP Ledger account has a *sequence number* that is used to keep transactions in order. Every transaction must have a sequence number. A transaction can only be executed if it has the next sequence number in order, of the account sending it. This prevents one transaction from executing twice and transactions executing out of order. The sequence number starts at `1` and increments for each transaction that the account makes.
|
||||
Every XRP Ledger account has a *sequence number* that is used to keep transactions in order. Every transaction must have a sequence or a ticketSequence number. A transaction can only be executed if it has the next sequence number in order, of the account sending it, or uses a previously generated ticketSequence number. This prevents one transaction from executing twice and transactions executing out of order. The sequence number starts at `1` and increments for each transaction that the account makes.
|
||||
|
||||
## Currency
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@ api.connect().then(() => {
|
||||
}).catch(console.error);
|
||||
```
|
||||
|
||||
RippleAPI is designed to work in [Node.js](https://nodejs.org) version **6.11.3**. RippleAPI may work on older Node.js versions if you use [Babel](https://babeljs.io/) for [ECMAScript 6](https://babeljs.io/docs/learn-es2015/) support.
|
||||
RippleAPI is designed to work in [Node.js](https://nodejs.org) version 6 or higher. Ripple recommends Node.js v10 LTS.
|
||||
|
||||
The code samples in this documentation are written with ECMAScript 6 (ES6) features, but `RippleAPI` also works with ECMAScript 5 (ES5). Regardless of whether you use ES5 or ES6, the methods that return Promises return [ES6-style promises](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise).
|
||||
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
## generateAddress
|
||||
|
||||
`generateAddress(): {address: string, secret: string}`
|
||||
`generateAddress(options?: object): {address: string, secret: string}`
|
||||
|
||||
Deprecated: This method returns a classic address. If you do not need the classic address, use `generateXAddress` instead.
|
||||
|
||||
Generate a new XRP Ledger address and corresponding secret.
|
||||
|
||||
|
||||
23
docs/src/generateXAddress.md.ejs
Normal file
23
docs/src/generateXAddress.md.ejs
Normal file
@@ -0,0 +1,23 @@
|
||||
## generateXAddress
|
||||
|
||||
`generateXAddress(options?: object): {address: string, secret: string}`
|
||||
|
||||
Generate a new XRP Ledger address and corresponding secret.
|
||||
|
||||
### Parameters
|
||||
|
||||
<%- renderSchema('input/generate-x-address.json') %>
|
||||
|
||||
### Return Value
|
||||
|
||||
This method returns an object with the following structure:
|
||||
|
||||
<%- renderSchema('output/generate-x-address.json') %>
|
||||
|
||||
### Example
|
||||
|
||||
```javascript
|
||||
return api.generateXAddress();
|
||||
```
|
||||
|
||||
<%- renderFixture('responses/generate-x-address.json') %>
|
||||
@@ -15,12 +15,13 @@ This method returns a promise that resolves with an object with the following st
|
||||
<%- renderSchema('output/get-account-objects.json') %>
|
||||
|
||||
The types of objects that may be returned include:
|
||||
* Offer objects for orders that are currently live, unfunded, or expired but not yet removed.
|
||||
* RippleState objects for trust lines where this account's side is not in the default state.
|
||||
* A SignerList object if the account has multi-signing enabled.
|
||||
* Escrow objects for held payments that have not yet been executed or canceled.
|
||||
* PayChannel objects for open payment channels.
|
||||
* Check objects for pending checks.
|
||||
|
||||
* `Offer` objects for orders that are currently live, unfunded, or expired but not yet removed.
|
||||
* `RippleState` objects for trust lines where this account's side is not in the default state.
|
||||
* A `SignerList` object if the account has multi-signing enabled.
|
||||
* `Escrow` objects for held payments that have not yet been executed or canceled.
|
||||
* `PayChannel` objects for open payment channels.
|
||||
* `Check` objects for pending checks.
|
||||
|
||||
### Example
|
||||
|
||||
|
||||
@@ -1,67 +1,70 @@
|
||||
<% include introduction.md.ejs %>
|
||||
<% include boilerplate.md.ejs %>
|
||||
<% include offline.md.ejs %>
|
||||
<% include basictypes.md.ejs %>
|
||||
<% include transactions.md.ejs %>
|
||||
<% include specifications.md.ejs %>
|
||||
<% include rippledAPIs.md.ejs %>
|
||||
<% include request.md.ejs %>
|
||||
<% include hasNextPage.md.ejs %>
|
||||
<% include requestNextPage.md.ejs %>
|
||||
<%- include('introduction.md.ejs') %>
|
||||
<%- include('boilerplate.md.ejs') %>
|
||||
<%- include('offline.md.ejs') %>
|
||||
<%- include('basictypes.md.ejs') %>
|
||||
<%- include('transactions.md.ejs') %>
|
||||
<%- include('specifications.md.ejs') %>
|
||||
<%- include('rippledAPIs.md.ejs') %>
|
||||
<%- include('request.md.ejs') %>
|
||||
<%- include('hasNextPage.md.ejs') %>
|
||||
<%- include('requestNextPage.md.ejs') %>
|
||||
|
||||
<% include staticMethods.md.ejs %>
|
||||
<% include renameCounterpartyToIssuer.md.ejs %>
|
||||
<% include formatBidsAndAsks.md.ejs %>
|
||||
<%- include('staticMethods.md.ejs') %>
|
||||
<%- include('renameCounterpartyToIssuer.md.ejs') %>
|
||||
<%- include('formatBidsAndAsks.md.ejs') %>
|
||||
|
||||
<% include methods.md.ejs %>
|
||||
<% include connect.md.ejs %>
|
||||
<% include disconnect.md.ejs %>
|
||||
<% include isConnected.md.ejs %>
|
||||
<% include getServerInfo.md.ejs %>
|
||||
<% include getFee.md.ejs %>
|
||||
<% include getLedgerVersion.md.ejs %>
|
||||
<% include getTransaction.md.ejs %>
|
||||
<% include getTransactions.md.ejs %>
|
||||
<% include getTrustlines.md.ejs %>
|
||||
<% include getBalances.md.ejs %>
|
||||
<% include getBalanceSheet.md.ejs %>
|
||||
<% include getPaths.md.ejs %>
|
||||
<% include getOrders.md.ejs %>
|
||||
<% include getOrderbook.md.ejs %>
|
||||
<% include getSettings.md.ejs %>
|
||||
<% include getAccountInfo.md.ejs %>
|
||||
<% include getAccountObjects.md.ejs %>
|
||||
<% include getPaymentChannel.md.ejs %>
|
||||
<% include getLedger.md.ejs %>
|
||||
<% include parseAccountFlags.md.ejs %>
|
||||
<% include prepareTransaction.md.ejs %>
|
||||
<% include preparePayment.md.ejs %>
|
||||
<% include prepareTrustline.md.ejs %>
|
||||
<% include prepareOrder.md.ejs %>
|
||||
<% include prepareOrderCancellation.md.ejs %>
|
||||
<% include prepareSettings.md.ejs %>
|
||||
<% include prepareEscrowCreation.md.ejs %>
|
||||
<% include prepareEscrowCancellation.md.ejs %>
|
||||
<% include prepareEscrowExecution.md.ejs %>
|
||||
<% include preparePaymentChannelCreate.md.ejs %>
|
||||
<% include preparePaymentChannelClaim.md.ejs %>
|
||||
<% include preparePaymentChannelFund.md.ejs %>
|
||||
<% include prepareCheckCreate.md.ejs %>
|
||||
<% include prepareCheckCancel.md.ejs %>
|
||||
<% include prepareCheckCash.md.ejs %>
|
||||
<% include sign.md.ejs %>
|
||||
<% include combine.md.ejs %>
|
||||
<% include submit.md.ejs %>
|
||||
<% include generateAddress.md.ejs %>
|
||||
<% include isValidAddress.md.ejs %>
|
||||
<% include isValidSecret.md.ejs %>
|
||||
<% include deriveKeypair.md.ejs %>
|
||||
<% include deriveAddress.md.ejs %>
|
||||
<% include signPaymentChannelClaim.md.ejs %>
|
||||
<% include verifyPaymentChannelClaim.md.ejs %>
|
||||
<% include computeLedgerHash.md.ejs %>
|
||||
<% include xrpToDropsAndDropsToXrp.md.ejs %>
|
||||
<% include iso8601ToRippleTime.md.ejs %>
|
||||
<% include txFlags.md.ejs %>
|
||||
<% include schemaValidator.md.ejs %>
|
||||
<% include events.md.ejs %>
|
||||
<%- include('methods.md.ejs') %>
|
||||
<%- include('connect.md.ejs') %>
|
||||
<%- include('disconnect.md.ejs') %>
|
||||
<%- include('isConnected.md.ejs') %>
|
||||
<%- include('getServerInfo.md.ejs') %>
|
||||
<%- include('getFee.md.ejs') %>
|
||||
<%- include('getLedgerVersion.md.ejs') %>
|
||||
<%- include('getTransaction.md.ejs') %>
|
||||
<%- include('getTransactions.md.ejs') %>
|
||||
<%- include('getTrustlines.md.ejs') %>
|
||||
<%- include('getBalances.md.ejs') %>
|
||||
<%- include('getBalanceSheet.md.ejs') %>
|
||||
<%- include('getPaths.md.ejs') %>
|
||||
<%- include('getOrders.md.ejs') %>
|
||||
<%- include('getOrderbook.md.ejs') %>
|
||||
<%- include('getSettings.md.ejs') %>
|
||||
<%- include('getAccountInfo.md.ejs') %>
|
||||
<%- include('getAccountObjects.md.ejs') %>
|
||||
<%- include('getPaymentChannel.md.ejs') %>
|
||||
<%- include('getLedger.md.ejs') %>
|
||||
<%- include('parseAccountFlags.md.ejs') %>
|
||||
<%- include('prepareTransaction.md.ejs') %>
|
||||
<%- include('preparePayment.md.ejs') %>
|
||||
<%- include('prepareTrustline.md.ejs') %>
|
||||
<%- include('prepareOrder.md.ejs') %>
|
||||
<%- include('prepareOrderCancellation.md.ejs') %>
|
||||
<%- include('prepareSettings.md.ejs') %>
|
||||
<%- include('prepareEscrowCreation.md.ejs') %>
|
||||
<%- include('prepareEscrowCancellation.md.ejs') %>
|
||||
<%- include('prepareEscrowExecution.md.ejs') %>
|
||||
<%- include('preparePaymentChannelCreate.md.ejs') %>
|
||||
<%- include('preparePaymentChannelClaim.md.ejs') %>
|
||||
<%- include('preparePaymentChannelFund.md.ejs') %>
|
||||
<%- include('prepareCheckCreate.md.ejs') %>
|
||||
<%- include('prepareCheckCancel.md.ejs') %>
|
||||
<%- include('prepareCheckCash.md.ejs') %>
|
||||
<%- include('prepareTicketCreate.md.ejs') %>
|
||||
<%- include('sign.md.ejs') %>
|
||||
<%- include('combine.md.ejs') %>
|
||||
<%- include('submit.md.ejs') %>
|
||||
<%- include('generateXAddress.md.ejs') %>
|
||||
<%- include('generateAddress.md.ejs') %>
|
||||
<%- include('isValidAddress.md.ejs') %>
|
||||
<%- include('isValidSecret.md.ejs') %>
|
||||
<%- include('deriveKeypair.md.ejs') %>
|
||||
<%- include('deriveAddress.md.ejs') %>
|
||||
<%- include('signPaymentChannelClaim.md.ejs') %>
|
||||
<%- include('verifyPaymentChannelClaim.md.ejs') %>
|
||||
<%- include('computeLedgerHash.md.ejs') %>
|
||||
<%- include('xrpToDropsAndDropsToXrp.md.ejs') %>
|
||||
<%- include('iso8601ToRippleTime.md.ejs') %>
|
||||
<%- include('rippleTimeToISO8601.md.ejs') %>
|
||||
<%- include('txFlags.md.ejs') %>
|
||||
<%- include('schemaValidator.md.ejs') %>
|
||||
<%- include('events.md.ejs') %>
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
# Introduction
|
||||
|
||||
RippleAPI (ripple-lib) is the official client library to the XRP Ledger. Currently, RippleAPI is only available in JavaScript.
|
||||
RippleAPI (ripple-lib) is the official client library to the XRP Ledger. Currently, RippleAPI is only available in JavaScript/TypeScript.
|
||||
|
||||
Using RippleAPI, you can:
|
||||
|
||||
* [Query transactions from the XRP Ledger history](#gettransaction)
|
||||
@@ -8,3 +9,7 @@ Using RippleAPI, you can:
|
||||
* [Submit](#submit) transactions to the XRP Ledger, including [Payments](#payment), [Orders](#order), [Settings changes](#settings), and [other types](#transaction-types)
|
||||
* [Generate a new XRP Ledger Address](#generateaddress)
|
||||
* ... and [much more](#api-methods).
|
||||
|
||||
This page contains documentation for ripple-lib. To use ripple-lib with npm/yarn, begin with the [Getting Started](https://github.com/ripple/ripple-lib#getting-started) steps.
|
||||
|
||||
**What is ripple-lib used for?** Here's a [list of applications that use `ripple-lib`](https://github.com/ripple/ripple-lib/blob/develop/APPLICATIONS.md). Open a PR to add your app or project to the list!
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
`isValidAddress(address: string): boolean`
|
||||
|
||||
Checks if the specified string contains a valid address.
|
||||
Checks if the specified string contains a valid address. X-addresses are considered valid with ripple-lib v1.4.0 and higher.
|
||||
|
||||
### Parameters
|
||||
|
||||
|
||||
@@ -23,4 +23,5 @@ Methods that depend on the state of the XRP Ledger are unavailable in offline mo
|
||||
* [prepareEscrowExecution](#prepareescrowexecution)
|
||||
* [sign](#sign)
|
||||
* [generateAddress](#generateaddress)
|
||||
* [generateXAddress](#generatexaddress)
|
||||
* [computeLedgerHash](#computeledgerhash)
|
||||
|
||||
34
docs/src/prepareTicketCreate.md.ejs
Normal file
34
docs/src/prepareTicketCreate.md.ejs
Normal file
@@ -0,0 +1,34 @@
|
||||
## prepareTicketCreate
|
||||
|
||||
`prepareTicketCreate(address: string, ticketCount: number, instructions: object): Promise<object>`
|
||||
|
||||
Prepare a ticket transaction. The prepared transaction must subsequently be [signed](#sign) and [submitted](#submit).
|
||||
|
||||
Ticket functionality requires the [TicketBatch amendment](https://github.com/ripple/xrpl-dev-portal/issues/898). As of 2020-11-24, this amendment is not activated on the Mainnet, Testnet, or Devnet.
|
||||
|
||||
### Parameters
|
||||
|
||||
<%- renderSchema("input/prepare-ticket-create.json") %>
|
||||
|
||||
### Return Value
|
||||
|
||||
This method returns a promise that resolves with an object with the following structure:
|
||||
|
||||
<aside class="notice">
|
||||
All "prepare*" methods have the same return type.
|
||||
</aside>
|
||||
|
||||
<%- renderSchema("output/prepare.json") %>
|
||||
|
||||
### Example
|
||||
|
||||
```javascript
|
||||
const address = 'r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59';
|
||||
return api.prepareTicketCreate(address, 2).then(prepared => {
|
||||
/* ... */
|
||||
}).catch(error => {
|
||||
/* ... as with all prepare* methods, use a Promise catch block to handle errors ... */
|
||||
})
|
||||
```
|
||||
|
||||
<%- renderFixture("responses/prepare-ticket-create.json") %>
|
||||
@@ -6,7 +6,7 @@ Prepare a transaction. The prepared transaction must subsequently be [signed](#s
|
||||
|
||||
This method works with any of [the transaction types supported by rippled](https://developers.ripple.com/transaction-types.html).
|
||||
|
||||
Notably, this is the preferred method for preparing a `DepositPreauth` transaction (added in rippled 1.1.0).
|
||||
Notably, this is the preferred method for preparing `DepositPreauth` or `AccountDelete` transactions.
|
||||
|
||||
### Parameters
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ Returns the response from invoking the specified command, with the specified opt
|
||||
|
||||
Refer to [rippled APIs](https://ripple.com/build/rippled-apis/) for commands and options. All XRP amounts must be specified in drops. One drop is equal to 0.000001 XRP. See [Specifying Currency Amounts](https://ripple.com/build/rippled-apis/#specifying-currency-amounts).
|
||||
|
||||
Most commands return data for the `current` (in-progress, open) ledger by default. Do not rely on this. Always specify a ledger version in your request. In the example below, the 'validated' ledger is requested, which is the most recent ledger that has been validated by the whole network. See [Specifying Ledgers](https://ripple.com/build/rippled-apis/#specifying-ledgers).
|
||||
Most commands return data for the `current` (in-progress, open) ledger by default. Do not rely on this. Always specify a ledger version in your request. In the example below, the 'validated' ledger is requested, which is the most recent ledger that has been validated by the whole network. See [Specifying Ledgers](https://xrpl.org/basic-data-types.html#specifying-ledgers).
|
||||
|
||||
### Return Value
|
||||
|
||||
|
||||
27
docs/src/rippleTimeToISO8601.md.ejs
Normal file
27
docs/src/rippleTimeToISO8601.md.ejs
Normal file
@@ -0,0 +1,27 @@
|
||||
## rippleTimeToISO8601
|
||||
|
||||
`rippleTimeToISO8601(rippleTime: number): string`
|
||||
|
||||
This method takes the number of seconds since the "Ripple Epoch" of January 1, 2000 (00:00 UTC) and returns a string representation of a date.
|
||||
|
||||
The Ripple Epoch is 946684800 seconds after the Unix Epoch.
|
||||
|
||||
This method is useful for interpreting timestamps returned by the rippled APIs. The rippled APIs represent time as an unsigned integer of the number of seconds since the Ripple Epoch.
|
||||
|
||||
### Parameters
|
||||
|
||||
`rippleTime`: A number of seconds since the Ripple Epoch.
|
||||
|
||||
### Return Value
|
||||
|
||||
A string representing a date and time, created by calling a `Date` object's `toISOString()` method.
|
||||
|
||||
### Example
|
||||
|
||||
```javascript
|
||||
api.rippleTimeToISO8601(540659097);
|
||||
```
|
||||
|
||||
```json
|
||||
'2017-02-17T15:04:57.000Z'
|
||||
```
|
||||
@@ -1,18 +1,21 @@
|
||||
# rippled APIs
|
||||
|
||||
ripple-lib relies on [rippled APIs](https://ripple.com/build/rippled-apis/) for all online functionality. With ripple-lib version 1.0.0 and higher, you can easily access rippled APIs through ripple-lib. Use the `request()`, `hasNextPage()`, and `requestNextPage()` methods:
|
||||
* Use `request()` to issue any `rippled` command, including `account_currencies`, `subscribe`, and `unsubscribe`. [Full list of API Methods](https://ripple.com/build/rippled-apis/#api-methods).
|
||||
ripple-lib relies on [rippled APIs](https://ripple.com/build/rippled-apis/) for online functionality. In addition to ripple-lib's own methods, you can also access rippled APIs through ripple-lib. Use the `request()`, `hasNextPage()`, and `requestNextPage()` methods:
|
||||
|
||||
* Use `request()` to issue any `rippled` command, including `account_currencies`, `subscribe`, and `unsubscribe`. [Full list of API Methods](https://ripple.com/build/rippled-apis/#api-methods).
|
||||
* Use `hasNextPage()` to determine whether a response has more pages. This is true when the response includes a [`marker` field](https://ripple.com/build/rippled-apis/#markers-and-pagination).
|
||||
* Use `requestNextPage()` to request the next page of data.
|
||||
|
||||
When using rippled APIs:
|
||||
|
||||
* [Specify XRP amounts in drops](https://developers.ripple.com/basic-data-types.html#specifying-currency-amounts).
|
||||
* [Specify timestamps as the number of seconds since the "Ripple Epoch"](https://developers.ripple.com/basic-data-types.html#specifying-time).
|
||||
* Instead of `counterparty`, use `issuer`.
|
||||
|
||||
## Listening to streams
|
||||
|
||||
The `rippled` server can push updates to your client when various events happen. Refer to [Subscriptions in the `rippled` API docs](https://developers.ripple.com/subscription-methods.html) for details.
|
||||
The `rippled` server can push updates to your client when various events happen.
|
||||
Refer to [Subscriptions in the `rippled` API docs](https://xrpl.org/subscribe.html) for details.
|
||||
|
||||
Note that the `streams` parameter for generic streams takes an array. For example, to subscribe to the `validations` stream, use `{ streams: [ 'validations' ] }`.
|
||||
|
||||
@@ -35,15 +38,16 @@ Type | Description
|
||||
`ledgerClosed` | Sent by the `ledger` stream when the consensus process declares a new fully validated ledger. The message identifies the ledger and provides some information about its contents.
|
||||
`validationReceived` | Sent by the `validations` stream when the server receives a validation message, also called a validation vote, regardless of whether the server trusts the validator.
|
||||
`manifestReceived` | Sent by the `manifests` stream when the server receives a manifest.
|
||||
`transaction` | Sent by many subscriptions including `transactions`, `transactions_proposed`, `accounts`, `accounts_proposed`, and `book` (Order Book). See [Transaction Streams](https://ripple.com/build/rippled-apis/#transaction-streams) for details.
|
||||
`transaction` | Sent by many subscriptions including `transactions`, `transactions_proposed`, `accounts`, `accounts_proposed`, and `book` (Order Book). See [Transaction Streams](https://xrpl.org/subscribe.html#transaction-streams) for details.
|
||||
`peerStatusChange` | (Admin-only) Reports a large amount of information on the activities of other `rippled` servers to which the server is connected.
|
||||
`path_find` | Asynchronous follow-up response to the currently open path\_find request. See [rippled path\_find method](https://xrpl.org/path_find.html) for details.
|
||||
|
||||
To register your listener function, use `connection.on(type, handler)`.
|
||||
|
||||
Here is an example of listening for transactions on given account(s):
|
||||
```
|
||||
const account = 'rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn' // Replace with the account you want notifications for
|
||||
api.connect().then(() => { // Omit this if you are already connected
|
||||
api.connect().then(() => {
|
||||
|
||||
// 'transaction' can be replaced with the relevant `type` from the table above
|
||||
api.connection.on('transaction', (event) => {
|
||||
@@ -55,9 +59,7 @@ api.connect().then(() => { // Omit this if you are already connected
|
||||
api.request('subscribe', {
|
||||
accounts: [ account ]
|
||||
}).then(response => {
|
||||
if (response.status === 'success') {
|
||||
console.log('Successfully subscribed')
|
||||
}
|
||||
console.log('Successfully subscribed')
|
||||
}).catch(error => {
|
||||
// Handle `error`
|
||||
})
|
||||
|
||||
@@ -15,6 +15,8 @@ This method can sign any of [the transaction types supported by ripple-binary-co
|
||||
|
||||
<%- renderSchema("input/sign.json") %>
|
||||
|
||||
When this method is used for multisigning, the `options` parameter is required. See the multisigning example in this section for more details.
|
||||
|
||||
### Return Value
|
||||
|
||||
This method returns an object with the following structure:
|
||||
@@ -31,3 +33,91 @@ return api.sign(txJSON, secret); // or: api.sign(txJSON, keypair);
|
||||
```
|
||||
|
||||
<%- renderFixture("responses/sign.json") %>
|
||||
|
||||
### Example (multisigning)
|
||||
|
||||
```javascript
|
||||
const RippleAPI = require('ripple-lib').RippleAPI;
|
||||
|
||||
// jon's address will have a multi-signing setup with a quorum of 2
|
||||
const jon = {
|
||||
account: 'rJKpme4m2zBQceBuU89d7vLMzgoUw2Ptj',
|
||||
secret: 'sh4Va7b1wQof8knHFV2sxwX12fSgK'
|
||||
};
|
||||
const aya = {
|
||||
account: 'rnrPdBjs98fFFfmRpL6hM7exT788SWQPFN',
|
||||
secret: 'snaMuMrXeVc2Vd4NYvHofeGNjgYoe'
|
||||
};
|
||||
const bran = {
|
||||
account: 'rJ93RLnT1t5A8fCr7HTScw7WtfKJMRXodH',
|
||||
secret: 'shQtQ8Um5MS218yvEU3Ehy1eZQKqH'
|
||||
};
|
||||
|
||||
// Setup the signers list with a quorum of 2
|
||||
const multiSignSetupTransaction = {
|
||||
"Flags": 0,
|
||||
"TransactionType": "SignerListSet",
|
||||
"Account": "rJKpme4m2zBQceBuU89d7vLMzgoUw2Ptj",
|
||||
"Fee": "120",
|
||||
"SignerQuorum": 2,
|
||||
"SignerEntries": [
|
||||
{
|
||||
"SignerEntry": {
|
||||
"Account": "rnrPdBjs98fFFfmRpL6hM7exT788SWQPFN",
|
||||
"SignerWeight": 2
|
||||
}
|
||||
},
|
||||
{
|
||||
"SignerEntry": {
|
||||
"Account": "rJ93RLnT1t5A8fCr7HTScw7WtfKJMRXodH",
|
||||
"SignerWeight": 1
|
||||
}
|
||||
},
|
||||
]
|
||||
};
|
||||
|
||||
// a transaction which requires multi signing
|
||||
const multiSignPaymentTransaction = {
|
||||
TransactionType: 'Payment',
|
||||
Account: 'rJKpme4m2zBQceBuU89d7vLMzgoUw2Ptj',
|
||||
Destination: 'rJ93RLnT1t5A8fCr7HTScw7WtfKJMRXodH',
|
||||
Amount: '88000000'
|
||||
};
|
||||
|
||||
const api = new RippleAPI({
|
||||
server: 'wss://s.altnet.rippletest.net:51233'
|
||||
});
|
||||
|
||||
api.connect().then(() => {
|
||||
// adding the multi signing feature to jon's account
|
||||
api.prepareTransaction(multiSignSetupTransaction).then((prepared) => {
|
||||
console.log(prepared);
|
||||
jonSign = api.sign(prepared.txJSON, jon.secret).signedTransaction;
|
||||
api.submit(jonSign).then( response => {
|
||||
console.log(response.resultCode, response.resultMessage);
|
||||
|
||||
// multi sign a transaction
|
||||
api.prepareTransaction(multiSignPaymentTransaction).then(prepared => {
|
||||
console.log(prepared);
|
||||
|
||||
// Aya and Bran sign it too but with 'signAs' set to their own account
|
||||
let ayaSign = api.sign(prepared.txJSON, aya.secret, {'signAs': aya.account}).signedTransaction;
|
||||
let branSign = api.sign(prepared.txJSON, bran.secret, {'signAs': bran.account}).signedTransaction;
|
||||
|
||||
// signatures are combined and submitted
|
||||
let combinedTx = api.combine([ayaSign, branSign]);
|
||||
api.submit(combinedTx.signedTransaction).then(response => {
|
||||
console.log(response.tx_json.hash);
|
||||
return api.disconnect();
|
||||
}).catch(console.error);
|
||||
}).catch(console.error);
|
||||
}).catch(console.error)
|
||||
}).catch(console.error);
|
||||
}).catch(console.error);
|
||||
```
|
||||
|
||||
Assuming the multisigning account was setup properly, the above example will respond with `resultCode: 'tesSUCCESS'` and the hash for the transaction.
|
||||
If any of `{signAs: some_address}` options were missing the code will return a validation error as follow:
|
||||
```
|
||||
[ValidationError(txJSON is not the same for all signedTransactions)]
|
||||
```
|
||||
|
||||
@@ -1,145 +1,185 @@
|
||||
# Transaction Specifications
|
||||
|
||||
A *transaction specification* specifies what a transaction should do. Each [Transaction Type](#transaction-types) has its own type of specification.
|
||||
A *transaction specification* specifies what a transaction should do. Each [Transaction Type](#transaction-types) has its own type of specification, which corresponds to the [native XRP Ledger transaction types](https://xrpl.org/transaction-types.html).
|
||||
|
||||
## Payment
|
||||
## Account Delete
|
||||
|
||||
See [Transaction Types](#transaction-types) for a description.
|
||||
Delete your account and send the remaining XRP elsewhere. (Native transaction type: [AccountDelete](https://xrpl.org/accountdelete.html))
|
||||
|
||||
<%- renderSchema('specifications/payment.json') %>
|
||||
<%- renderSchema('specifications/account-delete.json') %>
|
||||
|
||||
### Example
|
||||
> **Note:** To prepare an Account Delete transaction, use [`prepareTransaction()`](#preparetransaction) with the [native transaction format](https://xrpl.org/accountdelete.html).
|
||||
|
||||
<%- renderFixture('requests/prepare-payment.json') %>
|
||||
## Check Cancel
|
||||
|
||||
## Trustline
|
||||
Cancel a Check that has not been redeemed. (Native transaction type: [CheckCancel](https://xrpl.org/checkcancel.html))
|
||||
|
||||
See [Transaction Types](#transaction-types) for a description.
|
||||
<%- renderSchema('specifications/check-cancel.json') %>
|
||||
|
||||
<%- renderSchema('specifications/trustline.json') %>
|
||||
#### Example
|
||||
|
||||
### Example
|
||||
<%- renderFixture('requests/prepare-check-cancel.json') %>
|
||||
|
||||
|
||||
## Check Cash
|
||||
|
||||
Redeem a Check for up to its stated value. (Native transaction type: [CheckCash](https://xrpl.org/checkcash.html))
|
||||
|
||||
<%- renderSchema('specifications/check-cash.json') %>
|
||||
|
||||
#### Example
|
||||
|
||||
<%- renderFixture('requests/prepare-check-cash-amount.json') %>
|
||||
|
||||
|
||||
## Check Create
|
||||
|
||||
Create a Check, a deferred payment that can be redeemed by the destination. (Native transaction type: [CheckCreate](https://xrpl.org/checkcreate.html))
|
||||
|
||||
<%- renderSchema('specifications/check-create.json') %>
|
||||
|
||||
#### Example
|
||||
|
||||
<%- renderFixture('requests/prepare-check-create.json') %>
|
||||
|
||||
|
||||
## Deposit Preauth
|
||||
|
||||
Preauthorize an sender to deposit money at an account using [Deposit Authorization](https://xrpl.org/depositauth.html). (Native transaction type: [DepositPreauth](https://xrpl.org/depositpreauth.html))
|
||||
|
||||
<%- renderSchema('specifications/deposit-preauth.json') %>
|
||||
|
||||
> **Note:** To prepare a Deposit Preauth transaction, use [`prepareTransaction()`](#preparetransaction) with the [native transaction format](https://xrpl.org/depositpreauth.html).
|
||||
|
||||
|
||||
## Escrow Cancellation
|
||||
|
||||
Cancel an Escrow that has passed its expiration. (Native transaction type: [EscrowCancel](https://xrpl.org/escrowcancel.html))
|
||||
|
||||
<%- renderSchema('specifications/escrow-cancellation.json') %>
|
||||
|
||||
#### Example
|
||||
|
||||
<%- renderFixture('requests/prepare-escrow-cancellation.json') %>
|
||||
|
||||
|
||||
## Escrow Creation
|
||||
|
||||
Create an Escrow that locks up XRP until a given time or condition is met. (Native transaction type: [EscrowCreate](https://xrpl.org/escrowcreate.html))
|
||||
|
||||
<%- renderSchema('specifications/escrow-creation.json') %>
|
||||
|
||||
#### Example
|
||||
|
||||
<%- renderFixture('requests/prepare-escrow-creation.json') %>
|
||||
|
||||
|
||||
## Escrow Execution
|
||||
|
||||
Deliver XRP from an Escrow after its conditions have been met. (Native transaction type: [EscrowFinish](https://xrpl.org/escrowfinish.html))
|
||||
|
||||
<%- renderSchema('specifications/escrow-execution.json') %>
|
||||
|
||||
#### Example
|
||||
|
||||
<%- renderFixture('requests/prepare-escrow-execution.json') %>
|
||||
|
||||
<%- renderFixture('requests/prepare-trustline.json') %>
|
||||
|
||||
## Order
|
||||
|
||||
See [Transaction Types](#transaction-types) for a description.
|
||||
Create and execute a limit order in the decentralized exchange. (Native transaction type: [OfferCreate](https://xrpl.org/offercreate.html))
|
||||
|
||||
<%- renderSchema('specifications/order.json') %>
|
||||
|
||||
The following invalid flag combination causes a `ValidationError`: `immediateOrCancel` and `fillOrKill`. These fields are mutually exclusive, and cannot both be set at the same time.
|
||||
|
||||
### Example
|
||||
#### Example
|
||||
|
||||
<%- renderFixture('requests/prepare-order.json') %>
|
||||
|
||||
|
||||
## Order Cancellation
|
||||
|
||||
See [Transaction Types](#transaction-types) for a description.
|
||||
Cancel an order in the decentralized exchange. (Native transaction type: [OfferCancel](https://xrpl.org/offercancel.html))
|
||||
|
||||
<%- renderSchema('specifications/order-cancellation.json') %>
|
||||
|
||||
### Example
|
||||
#### Example
|
||||
|
||||
<%- renderFixture('requests/prepare-order-cancellation.json') %>
|
||||
|
||||
## Settings
|
||||
|
||||
See [Transaction Types](#transaction-types) for a description.
|
||||
## Payment
|
||||
|
||||
<%- renderSchema('output/get-settings.json') %>
|
||||
Send value from one account to another. (Native transaction type: [Payment](https://xrpl.org/payment.html))
|
||||
|
||||
### Example
|
||||
<%- renderSchema('specifications/payment.json') %>
|
||||
|
||||
<%- renderFixture('requests/prepare-settings.json') %>
|
||||
#### Example
|
||||
|
||||
## Escrow Creation
|
||||
<%- renderFixture('requests/prepare-payment.json') %>
|
||||
|
||||
See [Transaction Types](#transaction-types) for a description.
|
||||
|
||||
<%- renderSchema('specifications/escrow-creation.json') %>
|
||||
|
||||
### Example
|
||||
|
||||
<%- renderFixture('requests/prepare-escrow-creation.json') %>
|
||||
|
||||
## Escrow Cancellation
|
||||
|
||||
See [Transaction Types](#transaction-types) for a description.
|
||||
|
||||
<%- renderSchema('specifications/escrow-cancellation.json') %>
|
||||
|
||||
### Example
|
||||
|
||||
<%- renderFixture('requests/prepare-escrow-cancellation.json') %>
|
||||
|
||||
## Escrow Execution
|
||||
|
||||
See [Transaction Types](#transaction-types) for a description.
|
||||
|
||||
<%- renderSchema('specifications/escrow-execution.json') %>
|
||||
|
||||
### Example
|
||||
|
||||
<%- renderFixture('requests/prepare-escrow-execution.json') %>
|
||||
|
||||
## Check Create
|
||||
|
||||
See [Transaction Types](#transaction-types) for a description.
|
||||
|
||||
<%- renderSchema('specifications/check-create.json') %>
|
||||
|
||||
### Example
|
||||
|
||||
<%- renderFixture('requests/prepare-check-create.json') %>
|
||||
|
||||
## Check Cancel
|
||||
|
||||
See [Transaction Types](#transaction-types) for a description.
|
||||
|
||||
<%- renderSchema('specifications/check-cancel.json') %>
|
||||
|
||||
### Example
|
||||
|
||||
<%- renderFixture('requests/prepare-check-cancel.json') %>
|
||||
|
||||
## Check Cash
|
||||
|
||||
See [Transaction Types](#transaction-types) for a description.
|
||||
|
||||
<%- renderSchema('specifications/check-cash.json') %>
|
||||
|
||||
### Example
|
||||
|
||||
<%- renderFixture('requests/prepare-check-cash-amount.json') %>
|
||||
|
||||
## Payment Channel Create
|
||||
|
||||
See [Transaction Types](#transaction-types) for a description.
|
||||
|
||||
<%- renderSchema('specifications/payment-channel-create.json') %>
|
||||
|
||||
### Example
|
||||
|
||||
<%- renderFixture('requests/prepare-payment-channel-create.json') %>
|
||||
|
||||
## Payment Channel Fund
|
||||
|
||||
See [Transaction Types](#transaction-types) for a description.
|
||||
|
||||
<%- renderSchema('specifications/payment-channel-fund.json') %>
|
||||
|
||||
### Example
|
||||
|
||||
<%- renderFixture('requests/prepare-payment-channel-fund.json') %>
|
||||
|
||||
## Payment Channel Claim
|
||||
|
||||
See [Transaction Types](#transaction-types) for a description.
|
||||
Redeem XRP from a Payment Channel. (Native transaction type: [PaymentChannelClaim](https://xrpl.org/paymentchannelclaim.html))
|
||||
|
||||
<%- renderSchema('specifications/payment-channel-claim.json') %>
|
||||
|
||||
### Example
|
||||
#### Example
|
||||
|
||||
<%- renderFixture('requests/prepare-payment-channel-claim.json') %>
|
||||
|
||||
|
||||
## Payment Channel Create
|
||||
|
||||
Create a Payment Channel with XRP set aside for asynchronous payments. (Native transaction type: [PaymentChannelCreate](https://xrpl.org/paymentchannelcreate.html))
|
||||
|
||||
<%- renderSchema('specifications/payment-channel-create.json') %>
|
||||
|
||||
#### Example
|
||||
|
||||
<%- renderFixture('requests/prepare-payment-channel-create.json') %>
|
||||
|
||||
|
||||
## Payment Channel Fund
|
||||
|
||||
Add XRP to a Payment Channel. (Native transaction type: [PaymentChannelFund](https://xrpl.org/paymentchannelfund.html))
|
||||
|
||||
<%- renderSchema('specifications/payment-channel-fund.json') %>
|
||||
|
||||
#### Example
|
||||
|
||||
<%- renderFixture('requests/prepare-payment-channel-fund.json') %>
|
||||
|
||||
|
||||
|
||||
## Settings
|
||||
|
||||
Change account settings. (Native transaction types: [AccountSet](https://xrpl.org/accountset.html), [SetRegularKey](https://xrpl.org/setregularkey.html), [SignerListSet](https://xrpl.org/signerlistset.html))
|
||||
|
||||
<%- renderSchema('output/get-settings.json') %>
|
||||
|
||||
#### Example
|
||||
|
||||
<%- renderFixture('requests/prepare-settings.json') %>
|
||||
|
||||
|
||||
## Ticket Create
|
||||
|
||||
Set aside account Sequence numbers as Tickets to be used by later transactions.
|
||||
|
||||
> **Caution:** As of 2021-01-22, Tickets are not yet available on the XRP Ledger.
|
||||
|
||||
> **Note:** To prepare a Ticket Create transaction, use [`prepareTransaction()`](#preparetransaction) with the native transaction format. <!-- Future link: https://xrpl.org/ticketcreate.html -->
|
||||
|
||||
|
||||
## Trustline
|
||||
|
||||
Create or modify a trust line between two accounts, for an issued currency. (Native transaction type: [TrustSet](https://xrpl.org/trustset.html))
|
||||
|
||||
<%- renderSchema('specifications/trustline.json') %>
|
||||
|
||||
#### Example
|
||||
|
||||
<%- renderFixture('requests/prepare-trustline.json') %>
|
||||
|
||||
@@ -1 +1,100 @@
|
||||
# Static Methods
|
||||
|
||||
You can access static methods directly on the `RippleAPI` class. For example, `RippleAPI.computeBinaryTransactionHash(...)`.
|
||||
|
||||
A few of the most commonly-used methods are documented below.
|
||||
|
||||
For a full list, refer to these docs:
|
||||
|
||||
- [XRP Ledger Hashes](https://github.com/ripple/ripple-lib/blob/develop/src/common/hashes/README.md)
|
||||
- [ripple-address-codec API](https://github.com/ripple/ripple-address-codec/blob/master/README.md#api)
|
||||
|
||||
## computeBinaryTransactionHash
|
||||
|
||||
`computeBinaryTransactionHash(txBlobHex: string): string`
|
||||
|
||||
Returns the hash (id) of a binary transaction blob.
|
||||
|
||||
This is a static method on the `RippleAPI` class.
|
||||
|
||||
### Parameters
|
||||
|
||||
This method takes one parameter, a string containing a binary transaction in hex.
|
||||
|
||||
### Return Value
|
||||
|
||||
This method returns a string representing the transaction's id (hash).
|
||||
|
||||
### Example
|
||||
|
||||
```javascript
|
||||
const signed_blob = '120000228000000024000B2E5A201B0066374B61400000003B9ACA0068400000000000000C732102356E89059A75438887F9FEE2056A2890DB82A68353BE9C0C0C8F89C0018B37FC74473045022100B3721EEB1ED6DFF29FB8B209E2DE6B54A0A6E44D52D926342F3D334BE98F08640220367A74107AD5DEAEFA3AB2984C161FC23F30B2704BB5CC984358BA262177A4568114F667B0CA50CC7709A220B0561B85E53A48461FA883142B71D8B09B4EE8DAA68FB936C23E3A974713BDAC'
|
||||
if (typeof signed_blob === 'string' && signed_blob.match(/^[A-F0-9]+$/)) {
|
||||
const id = RippleAPI.computeBinaryTransactionHash(signed_blob)
|
||||
console.log('Transaction hash:', id')
|
||||
}
|
||||
```
|
||||
|
||||
```
|
||||
Transaction hash: 80C5E11E1A21A626759D6CB944B33DBAAC66BD704A289C86E330B847904F5C13
|
||||
```
|
||||
|
||||
[RunKit Example: computeBinaryTransactionHash](https://runkit.com/intelliot/computebinarytransactionhash-example)
|
||||
|
||||
## classicAddressToXAddress
|
||||
|
||||
`classicAddressToXAddress(classicAddress: string, tag: number | false[, test: boolean]): string`
|
||||
|
||||
Convert a classic address and tag to an X-address.
|
||||
|
||||
If `test` is `true`, the address with start with `T` and readers of the address will know that the address is intended for use on a test network.
|
||||
|
||||
### Example: Encode an X-address with tag 4294967295
|
||||
|
||||
```javascript
|
||||
const RippleAPI = require('ripple-lib').RippleAPI
|
||||
const xAddress = RippleAPI.classicAddressToXAddress('rGWrZyQqhTp9Xu7G5Pkayo7bXjH4k4QYpf', 4294967295)
|
||||
console.log(xAddress)
|
||||
```
|
||||
|
||||
```
|
||||
XVLhHMPHU98es4dbozjVtdWzVrDjtV18pX8yuPT7y4xaEHi
|
||||
```
|
||||
|
||||
### Example: Encode a test address for use with Testnet or Devnet
|
||||
|
||||
```javascript
|
||||
const RippleAPI = require('ripple-lib').RippleAPI
|
||||
const address = RippleAPI.classicAddressToXAddress('r3SVzk8ApofDJuVBPKdmbbLjWGCCXpBQ2g', 123, true)
|
||||
console.log(address)
|
||||
```
|
||||
|
||||
```
|
||||
T7oKJ3q7s94kDH6tpkBowhetT1JKfcfdSCmAXbS75iATyLD
|
||||
```
|
||||
|
||||
## xAddressToClassicAddress
|
||||
|
||||
`xAddressToClassicAddress(xAddress: string): {classicAddress: string, tag: number | false, test: boolean}`
|
||||
|
||||
Convert an X-address to a classic address and tag.
|
||||
|
||||
Since `0` is a valid tag, use `if (tag !== false)` to you want to check for a tag.
|
||||
|
||||
If the address is intended for use on a test network, `test === true`. Otherwise, `test === false`.
|
||||
|
||||
### Example
|
||||
|
||||
```javascript
|
||||
const RippleAPI = require('ripple-lib').RippleAPI
|
||||
const address = RippleAPI.xAddressToClassicAddress('XVLhHMPHU98es4dbozjVtdWzVrDjtV18pX8yuPT7y4xaEHi')
|
||||
console.log(address)
|
||||
```
|
||||
|
||||
```
|
||||
{
|
||||
classicAddress: 'rGWrZyQqhTp9Xu7G5Pkayo7bXjH4k4QYpf',
|
||||
tag: 4294967295,
|
||||
test: false
|
||||
}
|
||||
```
|
||||
|
||||
@@ -1,25 +1,83 @@
|
||||
## submit
|
||||
|
||||
`submit(signedTransaction: string): Promise<object>`
|
||||
`request('submit', {tx_blob: string, fail_hard: boolean}): Promise<object>`
|
||||
|
||||
Submits a signed transaction. The transaction is not guaranteed to succeed; it must be verified with [getTransaction](#gettransaction).
|
||||
The `submit` method applies a transaction and sends it to the network to be confirmed and included in future ledgers.
|
||||
|
||||
This method takes a signed, serialized transaction as a binary blob, and submits it to the network as-is. Since signed transaction objects are immutable, no part of the transaction can be modified or automatically filled in after submission.
|
||||
|
||||
To send a transaction as robustly as possible, you should construct and sign it in advance, persist it somewhere that you can access even after a power outage, then `submit` it as a `tx_blob`. After submission, monitor the network with the `tx` method to see if the transaction was successfully applied; if a restart or other problem occurs, you can safely re-submit the `tx_blob` transaction: it won't be applied twice since it has the same sequence number as the old transaction.
|
||||
|
||||
### Parameters
|
||||
|
||||
<%- renderSchema('input/submit.json') %>
|
||||
| `Field` | Type | Description |
|
||||
|:------------|:--------|:-----------------------------------------------------|
|
||||
| `tx_blob` | String | Hex representation of the signed transaction to submit. This can be a multi-signed transaction. |
|
||||
| `fail_hard` | Boolean | (Optional, defaults to false) If true, and the transaction fails locally, do not retry or relay the transaction to other servers |
|
||||
|
||||
### Return Value
|
||||
|
||||
This method returns an object with the following structure:
|
||||
When successful, this method returns an object containing the following fields:
|
||||
|
||||
<%- renderSchema('output/submit.json') %>
|
||||
| `Field` | Type | Description |
|
||||
|:------------------------|:--------|:-----------------------------------------|
|
||||
| `engine_result` | String | Text [result code](https://xrpl.org/transaction-results.html) indicating the preliminary result of the transaction, for example `tesSUCCESS` |
|
||||
| `engine_result_code` | Integer | Numeric version of the [result code](https://xrpl.org/transaction-results.html). **Not recommended.** |
|
||||
| `engine_result_message` | String | Human-readable explanation of the transaction's preliminary result |
|
||||
| `tx_blob` | String | The complete transaction in hex string format |
|
||||
| `tx_json` | Object | The complete transaction in JSON format |
|
||||
| `accepted` | Boolean | The value `true` indicates that the transaction was applied, queued, broadcast, or kept for later. The value `false` indicates that none of those happened, so the transaction cannot possibly succeed as long as you do not submit it again and have not already submitted it another time. [New in: rippled 1.5.0] |
|
||||
| `account_sequence_available` | Number | The next [Sequence Number](https://xrpl.org/basic-data-types.html#account-sequence) available for the sending account after all pending and [queued](https://xrpl.org/transaction-queue.html) transactions. [New in: rippled 1.5.0] |
|
||||
| `account_sequence_next` | number | The next [Sequence Number](https://xrpl.org/basic-data-types.html#account-sequence) for the sending account after all transactions that have been provisionally applied, but not transactions in the [queue](https://xrpl.org/transaction-queue.html). [New in: rippled 1.5.0] |
|
||||
| `applied` | Boolean | The value `true` indicates that this transaction was applied to the open ledger. In this case, the transaction is likely, but not guaranteed, to be validated in the next ledger version. [New in: rippled 1.5.0] |
|
||||
| `broadcast` | Boolean | The value `true` indicates this transaction was broadcast to peer servers in the peer-to-peer XRP Ledger network. (Note: if the server has no peers, such as in [stand-alone mode](https://xrpl.org/rippled-server-modes.html#reasons-to-run-a-rippled-server-in-stand-alone-mode), the server uses the value `true` for cases where it _would_ have broadcast the transaction.) The value `false` indicates the transaction was not broadcast to any other servers. [New in: rippled 1.5.0] |
|
||||
| `kept` | Boolean | The value `true` indicates that the transaction was kept to be retried later. [New in: rippled 1.5.0] |
|
||||
| `queued` | Boolean | The value `true` indicates the transaction was put in the [Transaction Queue](https://xrpl.org/transaction-queue.html), which means it is likely to be included in a future ledger version. [New in: rippled 1.5.0] |
|
||||
| `open_ledger_cost` | String | The current [open ledger cost](https://xrpl.org/transaction-cost.html#open-ledger-cost) before processing this transaction. Transactions with a lower cost are likely to be [queued](https://xrpl.org/transaction-queue.html). [New in: rippled 1.5.0] |
|
||||
| `validated_ledger_index` | Integer | The [ledger index](https://xrpl.org/basic-data-types.html#ledger-index) of the newest validated ledger at the time of submission. This provides a lower bound on the ledger versions that the transaction can appear in as a result of this request. (The transaction could only have been validated in this ledger version or earlier if it had already been submitted before.) |
|
||||
|
||||
Note: Many situations can prevent a transaction from processing successfully, such as a lack of trust lines connecting the two accounts in a payment, or changes in the state of the ledger since the time the transaction was constructed. Even if nothing is wrong, it may take several seconds to close and validate the ledger version that includes the transaction. Do not consider the transaction's results final until they appear in a validated ledger version.
|
||||
|
||||
### Example
|
||||
|
||||
```javascript
|
||||
const signedTransaction = '12000322800000002400000017201B0086955368400000000000000C732102F89EAEC7667B30F33D0687BBA86C3FE2A08CCA40A9186C5BDE2DAA6FA97A37D874473045022100BDE09A1F6670403F341C21A77CF35BA47E45CDE974096E1AA5FC39811D8269E702203D60291B9A27F1DCABA9CF5DED307B4F23223E0B6F156991DB601DFB9C41CE1C770A726970706C652E636F6D81145E7B112523F68D2F5E879DB4EAC51C6698A69304';
|
||||
return api.submit(signedTransaction)
|
||||
.then(result => {/* ... */});
|
||||
const signedTransaction = '12000022800000002400000007201B007008BC61400000000754D4C068400000000000000C732103E8110048477E60F292DEDA67CF518511E70A15E1E3771B3C024026E1F824832874473045022100D659C836C24FF346A87054E463078D805B19EFE9F10348FD4C6ED6C3F3C4D750022060BE0BFD5E2C4963A1B0E0F21D5BA800969863BA486F71E75C08D76D77C45B22811492F80A3F3849DBB5714A4F2C691CE7D47BEED58083141266204CFBC657E65D9B4D30301FF98644693935';
|
||||
const failHard = false;
|
||||
const result = await api.request('submit', {
|
||||
tx_blob: signedTransaction,
|
||||
fail_hard: failHard // optional
|
||||
});
|
||||
```
|
||||
|
||||
<%- renderFixture('responses/submit.json') %>
|
||||
```json
|
||||
{
|
||||
"accepted": true,
|
||||
"account_sequence_available": 8,
|
||||
"account_sequence_next": 8,
|
||||
"applied": true,
|
||||
"broadcast": true,
|
||||
"engine_result": "tesSUCCESS",
|
||||
"engine_result_code": 0,
|
||||
"engine_result_message": "The transaction was applied. Only final in a validated ledger.",
|
||||
"kept": true,
|
||||
"open_ledger_cost": "10",
|
||||
"queued": false,
|
||||
"tx_blob": "12000022800000002400000007201B007008BC61400000000754D4C068400000000000000C732103E8110048477E60F292DEDA67CF518511E70A15E1E3771B3C024026E1F824832874473045022100D659C836C24FF346A87054E463078D805B19EFE9F10348FD4C6ED6C3F3C4D750022060BE0BFD5E2C4963A1B0E0F21D5BA800969863BA486F71E75C08D76D77C45B22811492F80A3F3849DBB5714A4F2C691CE7D47BEED58083141266204CFBC657E65D9B4D30301FF98644693935",
|
||||
"tx_json": {
|
||||
"Account": "rNQao3Z1irwRjKWSs8heL4a8WKLPKfLrXs",
|
||||
"Amount": "123000000",
|
||||
"Destination": "rpgHWJdXkSvvzikdJCpuMzU7zWnuqsJRCZ",
|
||||
"Fee": "12",
|
||||
"Flags": 2147483648,
|
||||
"LastLedgerSequence": 7342268,
|
||||
"Sequence": 7,
|
||||
"SigningPubKey": "03E8110048477E60F292DEDA67CF518511E70A15E1E3771B3C024026E1F8248328",
|
||||
"TransactionType": "Payment",
|
||||
"TxnSignature": "3045022100D659C836C24FF346A87054E463078D805B19EFE9F10348FD4C6ED6C3F3C4D750022060BE0BFD5E2C4963A1B0E0F21D5BA800969863BA486F71E75C08D76D77C45B22",
|
||||
"hash": "FE8D68D7FF5805EB07AF15A1ADF07FB5463CCD2C6C0A15981EB3D26A02E1551C"
|
||||
},
|
||||
"validated_ledger_index": 7341775
|
||||
}
|
||||
```
|
||||
|
||||
(In ripple-lib 1.8.0, [the old `submit` method](https://github.com/ripple/ripple-lib/blob/1.7.0/docs/index.md#submit) was deprecated.)
|
||||
|
||||
@@ -9,7 +9,7 @@ Type | Description
|
||||
[payment](#payment) | A `payment` transaction represents a transfer of value from one account to another. Depending on the [path](https://ripple.com/build/paths/) taken, additional exchanges of value may occur atomically to facilitate the payment.
|
||||
[order](#order) | An `order` transaction creates a limit order. It defines an intent to exchange currencies, and creates an order in the XRP Ledger's order book if not completely fulfilled when placed. Orders can be partially fulfilled.
|
||||
[orderCancellation](#order-cancellation) | An `orderCancellation` transaction cancels an order in the XRP Ledger's order book.
|
||||
[trustline](#trustline) | A `trustline` transactions creates or modifies a trust line between two accounts.
|
||||
[trustline](#trustline) | A `trustline` transaction creates or modifies a trust line between two accounts.
|
||||
[settings](#settings) | A `settings` transaction modifies the settings of an account in the XRP Ledger.
|
||||
[escrowCreation](#escrow-creation) | An `escrowCreation` transaction creates an escrow on the ledger, which locks XRP until a cryptographic condition is met or it expires. It is like an escrow service where the XRP Ledger acts as the escrow agent.
|
||||
[escrowCancellation](#escrow-cancellation) | An `escrowCancellation` transaction unlocks the funds in an escrow and sends them back to the creator of the escrow, but it will only work after the escrow expires.
|
||||
@@ -20,6 +20,7 @@ Type | Description
|
||||
[paymentChannelCreate](#payment-channel-create) | A `paymentChannelCreate` transaction opens a payment channel between two addresses with XRP set aside for asynchronous payments.
|
||||
[paymentChannelFund](#payment-channel-fund) | A `paymentChannelFund` transaction adds XRP to a payment channel and optionally sets a new expiration for the channel.
|
||||
[paymentChannelClaim](#payment-channel-claim) | A `paymentChannelClaim` transaction withdraws XRP from a channel and optionally requests to close it.
|
||||
[ticketCreate](#ticket-create) | A successful `ticketCreate` transaction adds a Ticket in the directory of the owning account.
|
||||
|
||||
## Transaction Flow
|
||||
|
||||
@@ -37,6 +38,7 @@ Executing a transaction with `RippleAPI` requires the following four steps:
|
||||
* [prepareCheckCreate](#preparecheckcreate)
|
||||
* [prepareCheckCancel](#preparecheckcancel)
|
||||
* [prepareCheckCash](#preparecheckcash)
|
||||
* [prepareTicketCreate](#prepareticketcreate)
|
||||
2. [Sign](#sign) - Cryptographically sign the transaction locally and save the [transaction ID](#transaction-id). Signing is how the owner of an account authorizes a transaction to take place. For multisignature transactions, the `signedTransaction` fields returned by `sign` must be collected and passed to the [combine](#combine) method.
|
||||
3. [Submit](#submit) - Submit the transaction to the connected server.
|
||||
4. Verify - Verify that the transaction got validated by querying with [getTransaction](#gettransaction). This is necessary because transactions may fail even if they were successfully submitted.
|
||||
|
||||
96
package.json
96
package.json
@@ -1,13 +1,16 @@
|
||||
{
|
||||
"name": "ripple-lib",
|
||||
"version": "1.3.0",
|
||||
"version": "1.9.3",
|
||||
"license": "ISC",
|
||||
"description": "A JavaScript API for interacting with Ripple in Node.js and the browser",
|
||||
"description": "A TypeScript/JavaScript API for interacting with the XRP Ledger in Node.js and the browser",
|
||||
"files": [
|
||||
"dist/npm/*",
|
||||
"build/*"
|
||||
"build/ripple-latest-min.js",
|
||||
"build/ripple-latest.js"
|
||||
],
|
||||
"main": "dist/npm/",
|
||||
"unpkg": "build/ripple-latest-min.js",
|
||||
"jsdelivr": "build/ripple-latest-min.js",
|
||||
"types": "dist/npm/index.d.ts",
|
||||
"browser": {
|
||||
"ws": "./dist/npm/common/wswrapper.js",
|
||||
@@ -18,52 +21,66 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@types/lodash": "^4.14.136",
|
||||
"@types/ws": "^3.2.0",
|
||||
"bignumber.js": "^4.1.0",
|
||||
"https-proxy-agent": "2.2.1",
|
||||
"@types/ws": "^7.2.0",
|
||||
"bignumber.js": "^9.0.0",
|
||||
"https-proxy-agent": "^5.0.0",
|
||||
"jsonschema": "1.2.2",
|
||||
"lodash": "^4.17.4",
|
||||
"ripple-address-codec": "^2.0.1",
|
||||
"ripple-binary-codec": "0.2.2",
|
||||
"ripple-hashes": "0.3.2",
|
||||
"ripple-keypairs": "^0.10.1",
|
||||
"ripple-lib-transactionparser": "0.7.1",
|
||||
"ws": "^3.3.1"
|
||||
"lodash.isequal": "^4.5.0",
|
||||
"ripple-address-codec": "^4.1.1",
|
||||
"ripple-binary-codec": "^1.1.2",
|
||||
"ripple-keypairs": "^1.0.3",
|
||||
"ripple-lib-transactionparser": "0.8.2",
|
||||
"ws": "^7.2.0"
|
||||
},
|
||||
"resolutions": {
|
||||
"elliptic": "^6.5.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "11.13.0",
|
||||
"assert-diff": "^1.0.1",
|
||||
"doctoc": "^0.15.0",
|
||||
"ejs": "^2.3.4",
|
||||
"eventemitter2": "^0.4.14",
|
||||
"gulp": "^4.0.2",
|
||||
"json-loader": "^0.5.2",
|
||||
"@types/mocha": "^8.2.1",
|
||||
"@types/node": "^14.0.1",
|
||||
"@typescript-eslint/eslint-plugin": "^2.3.3",
|
||||
"@typescript-eslint/parser": "^2.27.0",
|
||||
"assert": "^2.0.0",
|
||||
"assert-diff": "^3.0.0",
|
||||
"buffer": "^6.0.2",
|
||||
"crypto-browserify": "^3.12.0",
|
||||
"doctoc": "^2.0.0",
|
||||
"ejs": "^3.0.1",
|
||||
"eslint": "^6.5.1",
|
||||
"eventemitter2": "^6.0.0",
|
||||
"json-schema-to-markdown-table": "^0.4.0",
|
||||
"mocha": "6.1.3",
|
||||
"mocha-junit-reporter": "^1.9.1",
|
||||
"null-loader": "^0.1.1",
|
||||
"nyc": "^14.1.1",
|
||||
"source-map-support": "0.5.12",
|
||||
"ts-loader": "^3.2.0",
|
||||
"ts-node": "8.0.3",
|
||||
"tslint": "^5.8.0",
|
||||
"tslint-eslint-rules": "^4.1.1",
|
||||
"typescript": "3.4.2",
|
||||
"uglifyjs-webpack-plugin": "^1.1.4",
|
||||
"webpack": "3.12.0"
|
||||
"mocha": "^7",
|
||||
"nyc": "^15",
|
||||
"prettier": "^2.0.5",
|
||||
"process": "^0.11.10",
|
||||
"stream-browserify": "^3.0.0",
|
||||
"ts-node": "^9.1.1",
|
||||
"typescript": "^3.7.5",
|
||||
"url": "^0.11.0",
|
||||
"webpack": "^5.6.0",
|
||||
"webpack-bundle-analyzer": "^4.1.0",
|
||||
"webpack-cli": "^4.2.0"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "gulp",
|
||||
"build:schemas": "mkdir -p dist/npm/common && cp -r src/common/schemas dist/npm/common/",
|
||||
"build:lib": "tsc --build",
|
||||
"build:web": "webpack",
|
||||
"build": "yarn build:schemas && yarn build:lib && yarn build:web",
|
||||
"analyze": "yarn build:web --analyze",
|
||||
"watch": "yarn build:lib --watch",
|
||||
"clean": "rm -rf dist/npm",
|
||||
"doctoc": "doctoc docs/index.md --title '# RippleAPI Reference' --github --maxlevel 2",
|
||||
"docgen": "node --harmony scripts/build_docs.js",
|
||||
"clean": "rm -rf dist/npm",
|
||||
"compile": "mkdir -p dist/npm/common/js && cp -r src/common/js/ dist/npm/common/js/ && mkdir -p dist/npm/common && cp -r src/common/schemas dist/npm/common/ && tsc --build",
|
||||
"watch": "tsc -w",
|
||||
"prepublish": "npm run clean && npm run compile && npm run build",
|
||||
"prepublish": "yarn clean && yarn build",
|
||||
"test": "TS_NODE_PROJECT=src/tsconfig.json nyc mocha --exit",
|
||||
"lint": "tslint -p ./",
|
||||
"test:watch": "TS_NODE_PROJECT=src/tsconfig.json mocha --watch --reporter dot",
|
||||
"format": "prettier --write '{src,test}/**/*.ts'",
|
||||
"lint": "eslint 'src/**/*.ts' 'test/*-test.{ts,js}'",
|
||||
"perf": "./scripts/perf_test.sh",
|
||||
"start": "node scripts/http.js"
|
||||
"compile:snippets": "tsc -p snippets/tsconfig.json",
|
||||
"start:snippet": "npm run compile:snippets && node ./snippets/dist/start.js",
|
||||
"inspect:snippet": "npm run compile:snippets && node inspect ./snippets/dist/start.js"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
@@ -71,6 +88,7 @@
|
||||
},
|
||||
"readmeFilename": "README.md",
|
||||
"engines": {
|
||||
"node": ">=6.12.3"
|
||||
"node": ">=10.13.0",
|
||||
"yarn": "^1.15.2"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,7 +14,10 @@ lint() {
|
||||
|
||||
unittest() {
|
||||
# test "src"
|
||||
mocha test --reporter mocha-junit-reporter --reporter-options mochaFile=$CIRCLE_TEST_REPORTS/test-results.xml
|
||||
|
||||
# TODO: replace/upgrade mocha-junit-reporter
|
||||
#mocha test --reporter mocha-junit-reporter --reporter-options mochaFile=$CIRCLE_TEST_REPORTS/test-results.xml
|
||||
|
||||
yarn test --coverage
|
||||
#yarn run coveralls
|
||||
|
||||
|
||||
9
snippets/src/decoder.ts
Normal file
9
snippets/src/decoder.ts
Normal file
@@ -0,0 +1,9 @@
|
||||
import * as codec from 'ripple-binary-codec'
|
||||
|
||||
const original = codec.decode('12000022800200002400000001201B00EF81E661EC6386F26FC0FFFF0000000000000000000000005553440000000000054F6F784A58F9EFB0A9EB90B83464F9D166461968400000000000000C6940000000000000646AD3504529A0465E2E0000000000000000000000005553440000000000054F6F784A58F9EFB0A9EB90B83464F9D1664619732102F89EAEC7667B30F33D0687BBA86C3FE2A08CCA40A9186C5BDE2DAA6FA97A37D87446304402200A693FB5CA6B21250EBDFD8CFF526EE0DF7C9E4E31EB0660692E75E6A93BF5F802203CC39463DDA21386898CA31E18AD1A6828647D65741DD637BAD71BC83E29DB9481145E7B112523F68D2F5E879DB4EAC51C6698A693048314CA6EDC7A28252DAEA6F2045B24F4D7C333E146170112300000000000000000000000005553440000000000054F6F784A58F9EFB0A9EB90B83464F9D166461900')
|
||||
|
||||
const test = codec.decode('12000022800200002400000017201B008694F261EC6386F26FC0FFFF0000000000000000000000005553440000000000054F6F784A58F9EFB0A9EB90B83464F9D166461968400000000000000C6940000000000000646AD3504529A0465E2E0000000000000000000000005553440000000000054F6F784A58F9EFB0A9EB90B83464F9D1664619732102F89EAEC7667B30F33D0687BBA86C3FE2A08CCA40A9186C5BDE2DAA6FA97A37D874473045022100D8B57E8E06EAE27B1343AF8CAD3F501E18260CCF8BCED08066074106F0F191A3022058FEA6CE9E7FA69D1244C3A70F18983CC2DAF0B10CBB86A6677CF2A5D2B8A68081145E7B112523F68D2F5E879DB4EAC51C6698A693048314CA6EDC7A28252DAEA6F2045B24F4D7C333E146170112300000000000000000000000005553440000000000054F6F784A58F9EFB0A9EB90B83464F9D166461900')
|
||||
|
||||
console.log('original:', JSON.stringify(original))
|
||||
|
||||
console.log('test:', JSON.stringify(test))
|
||||
47
snippets/src/paths.ts
Normal file
47
snippets/src/paths.ts
Normal file
@@ -0,0 +1,47 @@
|
||||
import {RippleAPI} from '../../dist/npm'
|
||||
|
||||
const api = new RippleAPI({
|
||||
// server: 'wss://s.altnet.rippletest.net:51233'
|
||||
// server: 'ws://35.158.96.209:51233'
|
||||
server: 'ws://34.210.87.206:51233'
|
||||
})
|
||||
|
||||
sign()
|
||||
|
||||
async function sign() {
|
||||
await api.connect()
|
||||
const pathfind: any = {
|
||||
source: {
|
||||
address: 'r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59',
|
||||
amount: {
|
||||
currency: 'drops',
|
||||
value: '100'
|
||||
}
|
||||
},
|
||||
destination: {
|
||||
address: 'rKT4JX4cCof6LcDYRz8o3rGRu7qxzZ2Zwj',
|
||||
amount: {
|
||||
currency: 'USD',
|
||||
counterparty: 'rVnYNK9yuxBz4uP8zC8LEFokM2nqH3poc'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
await api.getPaths(pathfind).then(async (data) => {
|
||||
console.log('paths:', JSON.stringify(data))
|
||||
const fakeSecret = 'shsWGZcmZz6YsWWmcnpfr6fLTdtFV'
|
||||
|
||||
pathfind.paths = data[0].paths
|
||||
pathfind.destination = data[0].destination
|
||||
await api.preparePayment('r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59', pathfind).then(ret => {
|
||||
const signed = api.sign(ret.txJSON, fakeSecret)
|
||||
console.log('signed:', signed)
|
||||
}).catch(err => {
|
||||
console.log('ERR 1:', JSON.stringify(err))
|
||||
})
|
||||
}).catch(err => {
|
||||
console.log('ERR 2:', err)
|
||||
})
|
||||
|
||||
api.disconnect()
|
||||
}
|
||||
200
snippets/src/reliableTransactionSubmission.ts
Normal file
200
snippets/src/reliableTransactionSubmission.ts
Normal file
@@ -0,0 +1,200 @@
|
||||
import {
|
||||
RippleAPI,
|
||||
AccountInfoResponse,
|
||||
LedgerClosedEvent
|
||||
} from '../../dist/npm'
|
||||
import https = require('https')
|
||||
|
||||
/**
|
||||
* When implementing Reliable Transaction Submission, there are many potential solutions, each with different trade-offs. The main decision points are:
|
||||
* 1) Transaction preparation:
|
||||
* - How do we decide which account sequence and LastLedgerSequence numbers to use?
|
||||
* (To prevent unintentional duplicate transactions, an {account, account_sequence} pair can be used as a transaction's idempotency key)
|
||||
* - How do we decide how much to pay for the transaction fee? (If our transactions have been failing due to low fee, we should consider increasing this value)
|
||||
* 2) Transaction status retrieval. Options include:
|
||||
* - Poll for transaction status:
|
||||
* - On a regular interval (e.g. every 3-5 seconds), or
|
||||
* - When a new validated ledger is detected
|
||||
* + (To accommodate an edge case in transaction retrieval, check the sending account's Sequence number to confirm that it has the expected value;
|
||||
* alternatively, wait until a few additional ledgers have been validated before deciding that a transaction has definitively not been included in a validated ledger)
|
||||
* - Listen for transaction status: scan all validated transactions to see if our transactions are among them
|
||||
* 3) What do we do when a transaction fails? It is possible to implement retry logic, but caution is advised. Note that there are a few ways for a transaction to fail:
|
||||
* A) `tec`: The transaction was included in a ledger but only claimed the transaction fee
|
||||
* B) `tesSUCCESS` but unexpected result: The transaction was successful but did not have the expected result. This generally does not occur for XRP-to-XRP payments
|
||||
* C) The transaction was not, and never will be, included in a validated ledger [3C]
|
||||
*
|
||||
* References:
|
||||
* - https://xrpl.org/reliable-transaction-submission.html
|
||||
* - https://xrpl.org/send-xrp.html
|
||||
* - https://xrpl.org/look-up-transaction-results.html
|
||||
* - https://xrpl.org/get-started-with-rippleapi-for-javascript.html
|
||||
* - https://xrpl.org/monitor-incoming-payments-with-websocket.html
|
||||
*
|
||||
* For the implementation in this example, we have made the following decisions:
|
||||
* 1) The script will choose the account sequence and LastLedgerSequence numbers automatically. We allow ripple-lib to choose the fee.
|
||||
* Payments are defined upfront, and idempotency is not needed. If the script is run a second time, duplicate payments will result.
|
||||
* 2) We will listen for notification that a new validated ledger has been found, and poll for transaction status at that time.
|
||||
* Futhermore, as a precaution, we will wait until the server is 3 ledgers past the transaction's LastLedgerSequence
|
||||
* (with the transaction nowhere to be seen) before deciding that it has definitively failed per [3C]
|
||||
* 3) Transactions will not be automatically retried. Transactions are limited to XRP-to-XRP payments and cannot "succeed" in an unexpected way.
|
||||
*/
|
||||
reliableTransactionSubmissionExample()
|
||||
|
||||
async function reliableTransactionSubmissionExample() {
|
||||
/**
|
||||
* Array of payments to execute.
|
||||
*
|
||||
* For brevity, these are XRP-to-XRP payments, taking a source, destination, and an amount in drops.
|
||||
*
|
||||
* The script will attempt to make all of these payments as quickly as possible, and report the final status of each. Transactions that fail are NOT retried.
|
||||
*/
|
||||
const payments = []
|
||||
|
||||
const sourceAccount = (await generateTestnetAccount()).account
|
||||
console.log(`Generated new Testnet account: ${sourceAccount.classicAddress}/${sourceAccount.secret}`)
|
||||
// Send amounts from 1 drop to 10 drops
|
||||
for (let i = 1; i <= 10; i++) {
|
||||
payments.push({
|
||||
source: sourceAccount,
|
||||
destination: 'rhsoCozhUxwcyQgzFi1FVRoMVQgk7cZd4L', // Random Testnet destination
|
||||
amount_drops: i.toString(),
|
||||
})
|
||||
}
|
||||
const results = await performPayments(payments)
|
||||
console.log(JSON.stringify(results, null, 2))
|
||||
process.exit(0)
|
||||
}
|
||||
|
||||
async function performPayments(payments) {
|
||||
const finalResults = []
|
||||
const txFinalizedPromises = []
|
||||
const api = new RippleAPI({server: 'wss://s.altnet.rippletest.net:51233'})
|
||||
await api.connect()
|
||||
|
||||
for (let i = 0; i < payments.length; i++) {
|
||||
const payment = payments[i]
|
||||
const account_info: AccountInfoResponse = await api.request('account_info', {
|
||||
account: payment.source.classicAddress,
|
||||
ledger_index: 'current'})
|
||||
const sequence = account_info.account_data.Sequence
|
||||
const preparedPayment = await api.preparePayment(payment.source.classicAddress, {
|
||||
source: {
|
||||
address: payment.source.classicAddress,
|
||||
amount: {
|
||||
value: payment.amount_drops,
|
||||
currency: 'drops'
|
||||
}
|
||||
},
|
||||
destination: {
|
||||
address: payment.destination,
|
||||
minAmount: {
|
||||
value: payment.amount_drops,
|
||||
currency: 'drops'
|
||||
}
|
||||
}
|
||||
}, {
|
||||
sequence
|
||||
})
|
||||
const signed = api.sign(preparedPayment.txJSON, payment.source.secret)
|
||||
finalResults.push({
|
||||
id: signed.id
|
||||
})
|
||||
const result = await api.submit(signed.signedTransaction)
|
||||
|
||||
// Most of the time we'll get 'tesSUCCESS' or (after many submissions) 'terQUEUED'
|
||||
console.log(`tx ${i} - tentative: ${result.resultCode}`)
|
||||
|
||||
const txFinalizedPromise = new Promise((resolve) => {
|
||||
const ledgerClosedCallback = async (event: LedgerClosedEvent) => {
|
||||
let status
|
||||
try {
|
||||
status = await api.getTransaction(signed.id)
|
||||
} catch (e) {
|
||||
// Typical error when the tx hasn't been validated yet:
|
||||
if (e.name !== 'MissingLedgerHistoryError') {
|
||||
console.log(e)
|
||||
}
|
||||
|
||||
if (event.ledger_index > preparedPayment.instructions.maxLedgerVersion + 3) {
|
||||
// Assumptions:
|
||||
// - We are still connected to the same rippled server
|
||||
// - No ledger gaps occurred
|
||||
// - All ledgers between the time we submitted the tx and now have been checked for the tx
|
||||
status = {
|
||||
finalResult: 'Transaction was not, and never will be, included in a validated ledger'
|
||||
}
|
||||
} else {
|
||||
// Check again later:
|
||||
api.connection.once('ledgerClosed', ledgerClosedCallback)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
for (let j = 0; j < finalResults.length; j++) {
|
||||
if (finalResults[j].id === signed.id) {
|
||||
finalResults[j].result = status.address ? {
|
||||
source: status.address,
|
||||
destination: status.specification.destination.address,
|
||||
deliveredAmount: status.outcome.deliveredAmount,
|
||||
result: status.outcome.result,
|
||||
timestamp: status.outcome.timestamp,
|
||||
ledgerVersion: status.outcome.ledgerVersion
|
||||
} : status
|
||||
process.stdout.write('.')
|
||||
return resolve()
|
||||
}
|
||||
}
|
||||
}
|
||||
api.connection.once('ledgerClosed', ledgerClosedCallback)
|
||||
})
|
||||
txFinalizedPromises.push(txFinalizedPromise)
|
||||
}
|
||||
await Promise.all(txFinalizedPromises)
|
||||
return finalResults
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a new Testnet account by requesting one from the faucet
|
||||
*/
|
||||
async function generateTestnetAccount(): Promise<{
|
||||
account: {
|
||||
xAddress: string,
|
||||
classicAddress, string,
|
||||
secret: string
|
||||
},
|
||||
balance: number
|
||||
}> {
|
||||
const options = {
|
||||
hostname: 'faucet.altnet.rippletest.net',
|
||||
port: 443,
|
||||
path: '/accounts',
|
||||
method: 'POST'
|
||||
}
|
||||
return new Promise((resolve, reject) => {
|
||||
const request = https.request(options, response => {
|
||||
const chunks = []
|
||||
response.on('data', d => {
|
||||
chunks.push(d)
|
||||
})
|
||||
response.on('end', () => {
|
||||
const body = Buffer.concat(chunks).toString()
|
||||
|
||||
// "application/json; charset=utf-8"
|
||||
if (response.headers['content-type'].startsWith('application/json')) {
|
||||
resolve(JSON.parse(body))
|
||||
} else {
|
||||
reject({
|
||||
statusCode: response.statusCode,
|
||||
contentType: response.headers['content-type'],
|
||||
body
|
||||
})
|
||||
}
|
||||
})
|
||||
})
|
||||
request.on('error', error => {
|
||||
console.error(error)
|
||||
reject(error)
|
||||
})
|
||||
request.end()
|
||||
})
|
||||
}
|
||||
275
src/api.ts
275
src/api.ts
@@ -5,8 +5,10 @@ import {
|
||||
validate,
|
||||
xrpToDrops,
|
||||
dropsToXrp,
|
||||
rippleTimeToISO8601,
|
||||
iso8601ToRippleTime,
|
||||
txFlags
|
||||
txFlags,
|
||||
ensureClassicAddress
|
||||
} from './common'
|
||||
import {
|
||||
connect,
|
||||
@@ -22,8 +24,7 @@ import getBalances from './ledger/balances'
|
||||
import getBalanceSheet from './ledger/balance-sheet'
|
||||
import getPaths from './ledger/pathfind'
|
||||
import getOrders from './ledger/orders'
|
||||
import {getOrderbook,
|
||||
formatBidsAndAsks} from './ledger/orderbook'
|
||||
import {getOrderbook, formatBidsAndAsks} from './ledger/orderbook'
|
||||
import {getSettings, parseAccountFlags} from './ledger/settings'
|
||||
import getAccountInfo from './ledger/accountinfo'
|
||||
import getAccountObjects from './ledger/accountobjects'
|
||||
@@ -42,29 +43,44 @@ import prepareCheckCreate from './transaction/check-create'
|
||||
import prepareCheckCancel from './transaction/check-cancel'
|
||||
import prepareCheckCash from './transaction/check-cash'
|
||||
import prepareSettings from './transaction/settings'
|
||||
import prepareTicketCreate from './transaction/ticket'
|
||||
import sign from './transaction/sign'
|
||||
import combine from './transaction/combine'
|
||||
import submit from './transaction/submit'
|
||||
import {generateAddressAPI} from './offline/generate-address'
|
||||
import {deriveKeypair, deriveAddress} from './offline/derive'
|
||||
import {
|
||||
generateAddressAPI,
|
||||
GenerateAddressOptions,
|
||||
GeneratedAddress
|
||||
} from './offline/generate-address'
|
||||
import {deriveKeypair, deriveAddress, deriveXAddress} from './offline/derive'
|
||||
import computeLedgerHash from './offline/ledgerhash'
|
||||
import signPaymentChannelClaim from './offline/sign-payment-channel-claim'
|
||||
import verifyPaymentChannelClaim from './offline/verify-payment-channel-claim'
|
||||
import getLedger from './ledger/ledger'
|
||||
|
||||
import {
|
||||
AccountObjectsRequest, AccountObjectsResponse,
|
||||
AccountOffersRequest, AccountOffersResponse,
|
||||
AccountInfoRequest, AccountInfoResponse,
|
||||
AccountLinesRequest, AccountLinesResponse,
|
||||
BookOffersRequest, BookOffersResponse,
|
||||
GatewayBalancesRequest, GatewayBalancesResponse,
|
||||
LedgerRequest, LedgerResponse,
|
||||
LedgerEntryRequest, LedgerEntryResponse,
|
||||
ServerInfoRequest, ServerInfoResponse
|
||||
AccountObjectsRequest,
|
||||
AccountObjectsResponse,
|
||||
AccountOffersRequest,
|
||||
AccountOffersResponse,
|
||||
AccountInfoRequest,
|
||||
AccountInfoResponse,
|
||||
AccountLinesRequest,
|
||||
AccountLinesResponse,
|
||||
BookOffersRequest,
|
||||
BookOffersResponse,
|
||||
GatewayBalancesRequest,
|
||||
GatewayBalancesResponse,
|
||||
LedgerRequest,
|
||||
LedgerResponse,
|
||||
LedgerDataRequest,
|
||||
LedgerDataResponse,
|
||||
LedgerEntryRequest,
|
||||
LedgerEntryResponse,
|
||||
ServerInfoRequest,
|
||||
ServerInfoResponse
|
||||
} from './common/types/commands'
|
||||
|
||||
|
||||
import RangeSet from './common/rangeset'
|
||||
import * as ledgerUtils from './ledger/utils'
|
||||
import * as transactionUtils from './transaction/utils'
|
||||
@@ -72,14 +88,27 @@ import * as schemaValidator from './common/schema-validator'
|
||||
import {getServerInfo, getFee} from './common/serverinfo'
|
||||
import {clamp, renameCounterpartyToIssuer} from './ledger/utils'
|
||||
import {TransactionJSON, Instructions, Prepare} from './transaction/types'
|
||||
import {ConnectionOptions} from './common/connection'
|
||||
import {ConnectionUserOptions} from './common/connection'
|
||||
import {classicAddressToXAddress, xAddressToClassicAddress, isValidXAddress, isValidClassicAddress, encodeSeed, decodeSeed, encodeAccountID, decodeAccountID, encodeNodePublic, decodeNodePublic, encodeAccountPublic, decodeAccountPublic, encodeXAddress, decodeXAddress} from 'ripple-address-codec'
|
||||
import {
|
||||
computeBinaryTransactionHash,
|
||||
computeTransactionHash,
|
||||
computeBinaryTransactionSigningHash,
|
||||
computeAccountLedgerObjectID,
|
||||
computeSignerListLedgerObjectID,
|
||||
computeOrderID,
|
||||
computeTrustlineHash,
|
||||
computeTransactionTreeHash,
|
||||
computeStateTreeHash,
|
||||
computeEscrowHash,
|
||||
computePaymentChannelHash
|
||||
} from './common/hashes'
|
||||
|
||||
export interface APIOptions extends ConnectionOptions {
|
||||
server?: string,
|
||||
feeCushion?: number,
|
||||
maxFeeXRP?: string,
|
||||
trace?: boolean,
|
||||
proxy?: string,
|
||||
export interface APIOptions extends ConnectionUserOptions {
|
||||
server?: string
|
||||
feeCushion?: number
|
||||
maxFeeXRP?: string
|
||||
proxy?: string
|
||||
timeout?: number
|
||||
}
|
||||
|
||||
@@ -88,7 +117,7 @@ export interface APIOptions extends ConnectionOptions {
|
||||
* command. This varies from command to command, but we need to know it to
|
||||
* properly count across many requests.
|
||||
*/
|
||||
function getCollectKeyFromCommand(command: string): string|undefined {
|
||||
function getCollectKeyFromCommand(command: string): string | undefined {
|
||||
switch (command) {
|
||||
case 'account_offers':
|
||||
case 'book_offers':
|
||||
@@ -127,7 +156,7 @@ class RippleAPI extends EventEmitter {
|
||||
const serverURL = options.server
|
||||
if (serverURL !== undefined) {
|
||||
this.connection = new Connection(serverURL, options)
|
||||
this.connection.on('ledgerClosed', message => {
|
||||
this.connection.on('ledgerClosed', (message) => {
|
||||
this.emit('ledger', formatLedgerClose(message))
|
||||
})
|
||||
this.connection.on('error', (errorCode, errorMessage, data) => {
|
||||
@@ -136,8 +165,15 @@ class RippleAPI extends EventEmitter {
|
||||
this.connection.on('connected', () => {
|
||||
this.emit('connected')
|
||||
})
|
||||
this.connection.on('disconnected', code => {
|
||||
this.emit('disconnected', code)
|
||||
this.connection.on('disconnected', (code) => {
|
||||
let finalCode = code
|
||||
// 1005: This is a backwards-compatible fix for this change in the ws library: https://github.com/websockets/ws/issues/1257
|
||||
// 4000: Connection uses a 4000 code internally to indicate a manual disconnect/close
|
||||
// TODO: Remove in next major, breaking version
|
||||
if (finalCode === 1005 || finalCode === 4000) {
|
||||
finalCode = 1000
|
||||
}
|
||||
this.emit('disconnected', finalCode)
|
||||
})
|
||||
} else {
|
||||
// use null object pattern to provide better error message if user
|
||||
@@ -146,35 +182,56 @@ class RippleAPI extends EventEmitter {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Makes a request to the API with the given command and
|
||||
* additional request body parameters.
|
||||
*/
|
||||
async request(command: 'account_info', params: AccountInfoRequest):
|
||||
Promise<AccountInfoResponse>
|
||||
async request(command: 'account_lines', params: AccountLinesRequest):
|
||||
Promise<AccountLinesResponse>
|
||||
async request(command: 'account_objects', params: AccountObjectsRequest):
|
||||
Promise<AccountObjectsResponse>
|
||||
async request(command: 'account_offers', params: AccountOffersRequest):
|
||||
Promise<AccountOffersResponse>
|
||||
async request(command: 'book_offers', params: BookOffersRequest):
|
||||
Promise<BookOffersResponse>
|
||||
async request(command: 'gateway_balances', params: GatewayBalancesRequest):
|
||||
Promise<GatewayBalancesResponse>
|
||||
async request(command: 'ledger', params: LedgerRequest):
|
||||
Promise<LedgerResponse>
|
||||
async request(command: 'ledger_entry', params: LedgerEntryRequest):
|
||||
Promise<LedgerEntryResponse>
|
||||
async request(command: 'server_info', params?: ServerInfoRequest):
|
||||
Promise<ServerInfoResponse>
|
||||
async request(command: string, params: any):
|
||||
Promise<any>
|
||||
async request(
|
||||
command: 'account_info',
|
||||
params: AccountInfoRequest
|
||||
): Promise<AccountInfoResponse>
|
||||
async request(
|
||||
command: 'account_lines',
|
||||
params: AccountLinesRequest
|
||||
): Promise<AccountLinesResponse>
|
||||
async request(
|
||||
command: 'account_objects',
|
||||
params: AccountObjectsRequest
|
||||
): Promise<AccountObjectsResponse>
|
||||
async request(
|
||||
command: 'account_offers',
|
||||
params: AccountOffersRequest
|
||||
): Promise<AccountOffersResponse>
|
||||
async request(
|
||||
command: 'book_offers',
|
||||
params: BookOffersRequest
|
||||
): Promise<BookOffersResponse>
|
||||
async request(
|
||||
command: 'gateway_balances',
|
||||
params: GatewayBalancesRequest
|
||||
): Promise<GatewayBalancesResponse>
|
||||
async request(
|
||||
command: 'ledger',
|
||||
params: LedgerRequest
|
||||
): Promise<LedgerResponse>
|
||||
async request(
|
||||
command: 'ledger_data',
|
||||
params?: LedgerDataRequest
|
||||
): Promise<LedgerDataResponse>
|
||||
async request(
|
||||
command: 'ledger_entry',
|
||||
params: LedgerEntryRequest
|
||||
): Promise<LedgerEntryResponse>
|
||||
async request(
|
||||
command: 'server_info',
|
||||
params?: ServerInfoRequest
|
||||
): Promise<ServerInfoResponse>
|
||||
async request(command: string, params: any): Promise<any>
|
||||
async request(command: string, params: any = {}): Promise<any> {
|
||||
return this.connection.request({
|
||||
...params,
|
||||
command
|
||||
command,
|
||||
account: params.account ? ensureClassicAddress(params.account) : undefined
|
||||
})
|
||||
}
|
||||
|
||||
@@ -194,7 +251,7 @@ class RippleAPI extends EventEmitter {
|
||||
command: string,
|
||||
params: object = {},
|
||||
currentResponse: T
|
||||
): Promise<object> {
|
||||
): Promise<T> {
|
||||
if (!currentResponse.marker) {
|
||||
return Promise.reject(
|
||||
new errors.NotFoundError('response does not have a next page')
|
||||
@@ -209,10 +266,12 @@ class RippleAPI extends EventEmitter {
|
||||
/**
|
||||
* Prepare a transaction.
|
||||
*
|
||||
* You can later submit the transaction with `submit()`.
|
||||
* You can later submit the transaction with a `submit` request.
|
||||
*/
|
||||
async prepareTransaction(txJSON: TransactionJSON, instructions: Instructions = {}):
|
||||
Promise<Prepare> {
|
||||
async prepareTransaction(
|
||||
txJSON: TransactionJSON,
|
||||
instructions: Instructions = {}
|
||||
): Promise<Prepare> {
|
||||
return transactionUtils.prepareTransaction(txJSON, this, instructions)
|
||||
}
|
||||
|
||||
@@ -240,16 +299,23 @@ class RippleAPI extends EventEmitter {
|
||||
* general use. Instead, use rippled's built-in pagination and make multiple
|
||||
* requests as needed.
|
||||
*/
|
||||
async _requestAll(command: 'account_offers', params: AccountOffersRequest):
|
||||
Promise<AccountOffersResponse[]>
|
||||
async _requestAll(command: 'book_offers', params: BookOffersRequest):
|
||||
Promise<BookOffersResponse[]>
|
||||
async _requestAll(command: 'account_lines', params: AccountLinesRequest):
|
||||
Promise<AccountLinesResponse[]>
|
||||
async _requestAll(
|
||||
command: 'account_offers',
|
||||
params: AccountOffersRequest
|
||||
): Promise<AccountOffersResponse[]>
|
||||
async _requestAll(
|
||||
command: 'book_offers',
|
||||
params: BookOffersRequest
|
||||
): Promise<BookOffersResponse[]>
|
||||
async _requestAll(
|
||||
command: 'account_lines',
|
||||
params: AccountLinesRequest
|
||||
): Promise<AccountLinesResponse[]>
|
||||
async _requestAll(
|
||||
command: string,
|
||||
params: any = {},
|
||||
options: {collect?: string} = {}): Promise<any[]> {
|
||||
options: {collect?: string} = {}
|
||||
): Promise<any[]> {
|
||||
// The data under collection is keyed based on the command. Fail if command
|
||||
// not recognized and collection key not provided.
|
||||
const collectKey = options.collect || getCollectKeyFromCommand(command)
|
||||
@@ -258,8 +324,7 @@ class RippleAPI extends EventEmitter {
|
||||
}
|
||||
// If limit is not provided, fetches all data over multiple requests.
|
||||
// NOTE: This may return much more than needed. Set limit when possible.
|
||||
const countTo: number =
|
||||
(params.limit !== undefined) ? params.limit : Infinity
|
||||
const countTo: number = params.limit !== undefined ? params.limit : Infinity
|
||||
let count: number = 0
|
||||
let marker: string = params.marker
|
||||
let lastBatchLength: number
|
||||
@@ -283,10 +348,19 @@ class RippleAPI extends EventEmitter {
|
||||
} else {
|
||||
lastBatchLength = 0
|
||||
}
|
||||
} while(!!marker && count < countTo && lastBatchLength !== 0)
|
||||
} while (!!marker && count < countTo && lastBatchLength !== 0)
|
||||
return results
|
||||
}
|
||||
|
||||
// @deprecated Use X-addresses instead
|
||||
generateAddress(options: GenerateAddressOptions = {}): GeneratedAddress {
|
||||
return generateAddressAPI({...options, includeClassicAddress: true})
|
||||
}
|
||||
|
||||
generateXAddress(options: GenerateAddressOptions = {}): GeneratedAddress {
|
||||
return generateAddressAPI(options)
|
||||
}
|
||||
|
||||
connect = connect
|
||||
disconnect = disconnect
|
||||
isConnected = isConnected
|
||||
@@ -322,12 +396,13 @@ class RippleAPI extends EventEmitter {
|
||||
prepareCheckCreate = prepareCheckCreate
|
||||
prepareCheckCash = prepareCheckCash
|
||||
prepareCheckCancel = prepareCheckCancel
|
||||
prepareTicketCreate = prepareTicketCreate
|
||||
prepareSettings = prepareSettings
|
||||
sign = sign
|
||||
combine = combine
|
||||
submit = submit
|
||||
|
||||
generateAddress = generateAddressAPI
|
||||
submit = submit // @deprecated Use api.request('submit', { tx_blob: signedTransaction }) instead
|
||||
|
||||
deriveKeypair = deriveKeypair
|
||||
deriveAddress = deriveAddress
|
||||
computeLedgerHash = computeLedgerHash
|
||||
@@ -335,8 +410,57 @@ class RippleAPI extends EventEmitter {
|
||||
verifyPaymentChannelClaim = verifyPaymentChannelClaim
|
||||
errors = errors
|
||||
|
||||
static deriveXAddress = deriveXAddress
|
||||
|
||||
// RippleAPI.deriveClassicAddress (static) is a new name for api.deriveAddress
|
||||
static deriveClassicAddress = deriveAddress
|
||||
|
||||
/**
|
||||
* Static methods to expose ripple-address-codec methods
|
||||
*/
|
||||
static classicAddressToXAddress = classicAddressToXAddress
|
||||
static xAddressToClassicAddress = xAddressToClassicAddress
|
||||
static isValidXAddress = isValidXAddress
|
||||
static isValidClassicAddress = isValidClassicAddress
|
||||
static encodeSeed = encodeSeed
|
||||
static decodeSeed = decodeSeed
|
||||
static encodeAccountID = encodeAccountID
|
||||
static decodeAccountID = decodeAccountID
|
||||
static encodeNodePublic = encodeNodePublic
|
||||
static decodeNodePublic = decodeNodePublic
|
||||
static encodeAccountPublic = encodeAccountPublic
|
||||
static decodeAccountPublic = decodeAccountPublic
|
||||
static encodeXAddress = encodeXAddress
|
||||
static decodeXAddress = decodeXAddress
|
||||
|
||||
/**
|
||||
* Static methods that replace functionality from the now-deprecated ripple-hashes library
|
||||
*/
|
||||
// Compute the hash of a binary transaction blob.
|
||||
static computeBinaryTransactionHash = computeBinaryTransactionHash // (txBlobHex: string): string
|
||||
// Compute the hash of a transaction in txJSON format.
|
||||
static computeTransactionHash = computeTransactionHash // (txJSON: any): string
|
||||
static computeBinaryTransactionSigningHash = computeBinaryTransactionSigningHash // (txBlobHex: string): string
|
||||
// Compute the hash of an account, given the account's classic address (starting with `r`).
|
||||
static computeAccountLedgerObjectID = computeAccountLedgerObjectID // (address: string): string
|
||||
// Compute the hash (ID) of an account's SignerList.
|
||||
static computeSignerListLedgerObjectID = computeSignerListLedgerObjectID // (address: string): string
|
||||
// Compute the hash of an order, given the owner's classic address (starting with `r`) and the account sequence number of the `OfferCreate` order transaction.
|
||||
static computeOrderID = computeOrderID // (address: string, sequence: number): string
|
||||
// Compute the hash of a trustline, given the two parties' classic addresses (starting with `r`) and the currency code.
|
||||
static computeTrustlineHash = computeTrustlineHash // (address1: string, address2: string, currency: string): string
|
||||
static computeTransactionTreeHash = computeTransactionTreeHash // (transactions: any[]): string
|
||||
static computeStateTreeHash = computeStateTreeHash // (entries: any[]): string
|
||||
// Compute the hash of a ledger.
|
||||
static computeLedgerHash = computeLedgerHash // (ledgerHeader): string
|
||||
// Compute the hash of an escrow, given the owner's classic address (starting with `r`) and the account sequence number of the `EscrowCreate` escrow transaction.
|
||||
static computeEscrowHash = computeEscrowHash // (address, sequence): string
|
||||
// Compute the hash of a payment channel, given the owner's classic address (starting with `r`), the classic address of the destination, and the account sequence number of the `PaymentChannelCreate` payment channel transaction.
|
||||
static computePaymentChannelHash = computePaymentChannelHash // (address, dstAddress, sequence): string
|
||||
|
||||
xrpToDrops = xrpToDrops
|
||||
dropsToXrp = dropsToXrp
|
||||
rippleTimeToISO8601 = rippleTimeToISO8601
|
||||
iso8601ToRippleTime = iso8601ToRippleTime
|
||||
txFlags = txFlags
|
||||
|
||||
@@ -347,3 +471,26 @@ class RippleAPI extends EventEmitter {
|
||||
export {
|
||||
RippleAPI
|
||||
}
|
||||
|
||||
export type {
|
||||
AccountObjectsRequest,
|
||||
AccountObjectsResponse,
|
||||
AccountOffersRequest,
|
||||
AccountOffersResponse,
|
||||
AccountInfoRequest,
|
||||
AccountInfoResponse,
|
||||
AccountLinesRequest,
|
||||
AccountLinesResponse,
|
||||
BookOffersRequest,
|
||||
BookOffersResponse,
|
||||
GatewayBalancesRequest,
|
||||
GatewayBalancesResponse,
|
||||
LedgerRequest,
|
||||
LedgerResponse,
|
||||
LedgerDataRequest,
|
||||
LedgerDataResponse,
|
||||
LedgerEntryRequest,
|
||||
LedgerEntryResponse,
|
||||
ServerInfoRequest,
|
||||
ServerInfoResponse
|
||||
}
|
||||
|
||||
@@ -1,56 +1,58 @@
|
||||
|
||||
import * as _ from 'lodash'
|
||||
import {RippleAPI} from './api'
|
||||
import {RippleAPI, APIOptions} from './api'
|
||||
|
||||
class RippleAPIBroadcast extends RippleAPI {
|
||||
|
||||
ledgerVersion: number | undefined = undefined
|
||||
private _apis: RippleAPI[]
|
||||
|
||||
constructor(servers, options) {
|
||||
constructor(servers, options: APIOptions = {}) {
|
||||
super(options)
|
||||
|
||||
const apis: RippleAPI[] = servers.map(server => new RippleAPI(
|
||||
_.assign({}, options, {server})
|
||||
))
|
||||
const apis: RippleAPI[] = servers.map(
|
||||
(server) => new RippleAPI(_.assign({}, options, {server}))
|
||||
)
|
||||
|
||||
// exposed for testing
|
||||
this._apis = apis
|
||||
|
||||
this.getMethodNames().forEach(name => {
|
||||
this[name] = function() { // eslint-disable-line no-loop-func
|
||||
return Promise.race(apis.map(api => api[name](...arguments)))
|
||||
this.getMethodNames().forEach((name) => {
|
||||
this[name] = function () {
|
||||
// eslint-disable-line no-loop-func
|
||||
return Promise.race(apis.map((api) => api[name](...arguments)))
|
||||
}
|
||||
})
|
||||
|
||||
// connection methods must be overridden to apply to all api instances
|
||||
this.connect = async function() {
|
||||
await Promise.all(apis.map(api => api.connect()))
|
||||
this.connect = async function () {
|
||||
await Promise.all(apis.map((api) => api.connect()))
|
||||
}
|
||||
this.disconnect = async function() {
|
||||
await Promise.all(apis.map(api => api.disconnect()))
|
||||
this.disconnect = async function () {
|
||||
await Promise.all(apis.map((api) => api.disconnect()))
|
||||
}
|
||||
this.isConnected = function() {
|
||||
return apis.map(api => api.isConnected()).every(Boolean)
|
||||
this.isConnected = function () {
|
||||
return apis.map((api) => api.isConnected()).every(Boolean)
|
||||
}
|
||||
|
||||
// synchronous methods are all passed directly to the first api instance
|
||||
const defaultAPI = apis[0]
|
||||
const syncMethods = ['sign', 'generateAddress', 'computeLedgerHash']
|
||||
syncMethods.forEach(name => {
|
||||
syncMethods.forEach((name) => {
|
||||
this[name] = defaultAPI[name].bind(defaultAPI)
|
||||
})
|
||||
|
||||
apis.forEach(api => {
|
||||
apis.forEach((api) => {
|
||||
api.on('ledger', this.onLedgerEvent.bind(this))
|
||||
api.on('error', (errorCode, errorMessage, data) =>
|
||||
this.emit('error', errorCode, errorMessage, data))
|
||||
this.emit('error', errorCode, errorMessage, data)
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
onLedgerEvent(ledger) {
|
||||
if (ledger.ledgerVersion > this.ledgerVersion ||
|
||||
this.ledgerVersion === undefined) {
|
||||
if (
|
||||
ledger.ledgerVersion > this.ledgerVersion ||
|
||||
this.ledgerVersion === undefined
|
||||
) {
|
||||
this.ledgerVersion = ledger.ledgerVersion
|
||||
this.emit('ledger', ledger)
|
||||
}
|
||||
@@ -68,6 +70,4 @@ class RippleAPIBroadcast extends RippleAPI {
|
||||
}
|
||||
}
|
||||
|
||||
export {
|
||||
RippleAPIBroadcast
|
||||
}
|
||||
export {RippleAPIBroadcast}
|
||||
|
||||
44
src/common/backoff.ts
Normal file
44
src/common/backoff.ts
Normal file
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Original code based on "backo" - https://github.com/segmentio/backo
|
||||
* MIT License - Copyright 2014 Segment.io
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* A Back off strategy that increases exponentially. Useful with repeated
|
||||
* setTimeout calls over a network (where the destination may be down).
|
||||
*/
|
||||
export class ExponentialBackoff {
|
||||
private readonly ms: number
|
||||
private readonly max: number
|
||||
private readonly factor: number = 2
|
||||
private readonly jitter: number = 0
|
||||
attempts: number = 0
|
||||
|
||||
constructor(opts: {min?: number; max?: number} = {}) {
|
||||
this.ms = opts.min || 100
|
||||
this.max = opts.max || 10000
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the backoff duration.
|
||||
*/
|
||||
duration() {
|
||||
var ms = this.ms * Math.pow(this.factor, this.attempts++)
|
||||
if (this.jitter) {
|
||||
var rand = Math.random()
|
||||
var deviation = Math.floor(rand * this.jitter * ms)
|
||||
ms = (Math.floor(rand * 10) & 1) == 0 ? ms - deviation : ms + deviation
|
||||
}
|
||||
return Math.min(ms, this.max) | 0
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset the number of attempts.
|
||||
*/
|
||||
reset() {
|
||||
this.attempts = 0
|
||||
}
|
||||
}
|
||||
@@ -1,20 +1,20 @@
|
||||
|
||||
function setPrototypeOf(object, prototype) {
|
||||
// Object.setPrototypeOf not supported on Internet Explorer 9
|
||||
Object.setPrototypeOf ? Object.setPrototypeOf(object, prototype) :
|
||||
// @ts-ignore: Specifically a fallback for IE9
|
||||
object.__proto__ = prototype
|
||||
Object.setPrototypeOf
|
||||
? Object.setPrototypeOf(object, prototype)
|
||||
: // @ts-ignore: Specifically a fallback for IE9
|
||||
(object.__proto__ = prototype)
|
||||
}
|
||||
|
||||
function getConstructorName(object: object): string {
|
||||
// hack for internet explorer
|
||||
if (!object.constructor.name) {
|
||||
return object.constructor.toString().match(/^function\s+([^(]*)/)![1]
|
||||
if (object.constructor.name) {
|
||||
return object.constructor.name
|
||||
}
|
||||
return object.constructor.name
|
||||
// try to guess it on legacy browsers (ie)
|
||||
const constructorString = object.constructor.toString()
|
||||
const functionConstructor = constructorString.match(/^function\s+([^(]*)/)
|
||||
const classConstructor = constructorString.match(/^class\s([^\s]*)/)
|
||||
return functionConstructor ? functionConstructor[1] : classConstructor[1]
|
||||
}
|
||||
|
||||
export {
|
||||
getConstructorName,
|
||||
setPrototypeOf
|
||||
}
|
||||
export {getConstructorName, setPrototypeOf}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,9 +1,7 @@
|
||||
|
||||
import {txFlagIndices} from './txflags'
|
||||
|
||||
// Ordering from https://developers.ripple.com/accountroot.html
|
||||
const accountRootFlags = {
|
||||
|
||||
// lsfDefaultRipple:
|
||||
// Enable rippling on trust lines by default.
|
||||
// Required for issuing addresses; discouraged for others.
|
||||
@@ -60,6 +58,18 @@ const AccountFlags = {
|
||||
defaultRipple: accountRootFlags.DefaultRipple
|
||||
}
|
||||
|
||||
export interface Settings {
|
||||
passwordSpent?: boolean
|
||||
requireDestinationTag?: boolean
|
||||
requireAuthorization?: boolean
|
||||
depositAuth?: boolean
|
||||
disallowIncomingXRP?: boolean
|
||||
disableMasterKey?: boolean
|
||||
noFreeze?: boolean
|
||||
globalFreeze?: boolean
|
||||
defaultRipple?: boolean
|
||||
}
|
||||
|
||||
const AccountFlagIndices = {
|
||||
requireDestinationTag: txFlagIndices.AccountSet.asfRequireDest,
|
||||
requireAuthorization: txFlagIndices.AccountSet.asfRequireAuth,
|
||||
@@ -73,15 +83,17 @@ const AccountFlagIndices = {
|
||||
}
|
||||
|
||||
const AccountFields = {
|
||||
EmailHash: {name: 'emailHash', encoding: 'hex',
|
||||
length: 32, defaults: '0'},
|
||||
EmailHash: {
|
||||
name: 'emailHash',
|
||||
encoding: 'hex',
|
||||
length: 32,
|
||||
defaults: '00000000000000000000000000000000'
|
||||
},
|
||||
WalletLocator: {name: 'walletLocator'},
|
||||
MessageKey: {name: 'messageKey'},
|
||||
Domain: {name: 'domain', encoding: 'hex'},
|
||||
TransferRate: {name: 'transferRate', defaults: 0, shift: 9}
|
||||
TransferRate: {name: 'transferRate', defaults: 0, shift: 9},
|
||||
TickSize: {name: 'tickSize', defaults: 0}
|
||||
}
|
||||
|
||||
export {
|
||||
AccountFields,
|
||||
AccountFlagIndices,
|
||||
AccountFlags
|
||||
}
|
||||
export {AccountFields, AccountFlagIndices, AccountFlags}
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
|
||||
import {inspect} from 'util'
|
||||
import * as browserHacks from './browser-hacks'
|
||||
|
||||
class RippleError extends Error {
|
||||
|
||||
name: string
|
||||
message: string
|
||||
data?: any
|
||||
@@ -70,8 +68,11 @@ class MissingLedgerHistoryError extends RippleError {
|
||||
|
||||
class PendingLedgerVersionError extends RippleError {
|
||||
constructor(message?: string) {
|
||||
super(message || 'maxLedgerVersion is greater than server\'s most recent' +
|
||||
' validated ledger')
|
||||
super(
|
||||
message ||
|
||||
"maxLedgerVersion is greater than server's most recent" +
|
||||
' validated ledger'
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
65
src/common/hashes/README.md
Normal file
65
src/common/hashes/README.md
Normal file
@@ -0,0 +1,65 @@
|
||||
# XRP Ledger Hashes
|
||||
|
||||
Methods to hash XRP Ledger objects
|
||||
|
||||
## Computing a transaction hash (ID)
|
||||
|
||||
### computeBinaryTransactionHash = (txBlobHex: string): string
|
||||
|
||||
Compute the hash of a binary transaction blob.
|
||||
|
||||
### computeTransactionHash = (txJSON: any): string
|
||||
|
||||
Compute the hash of a transaction in txJSON format.
|
||||
|
||||
## [Hash Prefixes](https://xrpl.org/basic-data-types.html#hash-prefixes)
|
||||
|
||||
In many cases, the XRP Ledger prefixes an object's binary data with a 4-byte code before calculating its hash, so that objects of different types have different hashes even if the binary data is the same. The existing 4-byte codes are structured as 3 alphabetic characters, encoded as ASCII, followed by a zero byte.
|
||||
|
||||
Some types of hashes appear in API requests and responses. Others are only calculated as the first step of signing a certain type of data, or calculating a higher-level hash. Some of following methods internally use some of the 4-byte hash prefixes in order to calculate the appropriate hash.
|
||||
|
||||
### computeBinaryTransactionSigningHash = (txBlobHex: string): string
|
||||
|
||||
In order to single-sign a transaction, you must perform these steps:
|
||||
|
||||
1. Assuming the transaction is in JSON format (txJSON), `encode` the transaction in the XRP Ledger's binary format.
|
||||
2. Hash the data with the appropriate prefix (`0x53545800` if single-signing, or `0x534D5400` if multi-signing).
|
||||
3. After signing, you must re-serialize the transaction with the `TxnSignature` field included.
|
||||
|
||||
The `computeBinaryTransactionSigningHash` helps with step 2, automatically using the `0x53545800` prefix needed for single-signing a transaction.
|
||||
|
||||
For details, see [Serialization Format](https://xrpl.org/serialization.html).
|
||||
|
||||
_Removed:_ `computeTransactionSigningHash`, which took txJSON as a parameter. It was part of the deprecated ripple-hashes library. If you have txJSON, `encode` it with [ripple-binary-codec](https://github.com/ripple/ripple-binary-codec) first. Example: `return computeBinaryTransactionSigningHash(encode(txJSON))`
|
||||
|
||||
### computeAccountLedgerObjectID = (address: string): string
|
||||
|
||||
Compute the hash of an account, given the account's classic address (starting with `r`).
|
||||
|
||||
### computeSignerListLedgerObjectID = (address: string): string
|
||||
|
||||
Compute the hash of an account's SignerList.
|
||||
|
||||
### computeOrderID = (address: string, sequence: number): string
|
||||
|
||||
Compute the hash of an order, given the owner's classic address (starting with `r`) and the account sequence number of the `OfferCreate` order transaction.
|
||||
|
||||
### computeTrustlineHash = (address1: string, address2: string, currency: string): string
|
||||
|
||||
Compute the hash of a trustline, given the two parties' classic addresses (starting with `r`) and the currency code.
|
||||
|
||||
### computeTransactionTreeHash = (transactions: any[]): string
|
||||
|
||||
### computeStateTreeHash = (entries: any[]): string
|
||||
|
||||
### computeLedgerHash = (ledgerHeader): string
|
||||
|
||||
Compute the hash of a ledger.
|
||||
|
||||
### computeEscrowHash = (address, sequence): string
|
||||
|
||||
Compute the hash of an escrow, given the owner's classic address (starting with `r`) and the account sequence number of the `EscrowCreate` escrow transaction.
|
||||
|
||||
### computePaymentChannelHash = (address, dstAddress, sequence): string
|
||||
|
||||
Compute the hash of a payment channel, given the owner's classic address (starting with `r`), the classic address of the destination, and the account sequence number of the `PaymentChannelCreate` payment channel transaction.
|
||||
40
src/common/hashes/hash-prefix.ts
Normal file
40
src/common/hashes/hash-prefix.ts
Normal file
@@ -0,0 +1,40 @@
|
||||
/**
|
||||
* Prefix for hashing functions.
|
||||
*
|
||||
* These prefixes are inserted before the source material used to
|
||||
* generate various hashes. This is done to put each hash in its own
|
||||
* "space." This way, two different types of objects with the
|
||||
* same binary data will produce different hashes.
|
||||
*
|
||||
* Each prefix is a 4-byte value with the last byte set to zero
|
||||
* and the first three bytes formed from the ASCII equivalent of
|
||||
* some arbitrary string. For example "TXN".
|
||||
*/
|
||||
|
||||
enum HashPrefix {
|
||||
// transaction plus signature to give transaction ID
|
||||
TRANSACTION_ID = 0x54584e00, // 'TXN'
|
||||
|
||||
// transaction plus metadata
|
||||
TRANSACTION_NODE = 0x534e4400, // 'TND'
|
||||
|
||||
// inner node in tree
|
||||
INNER_NODE = 0x4d494e00, // 'MIN'
|
||||
|
||||
// leaf node in tree
|
||||
LEAF_NODE = 0x4d4c4e00, // 'MLN'
|
||||
|
||||
// inner transaction to sign
|
||||
TRANSACTION_SIGN = 0x53545800, // 'STX'
|
||||
|
||||
// inner transaction to sign (TESTNET)
|
||||
TRANSACTION_SIGN_TESTNET = 0x73747800, // 'stx'
|
||||
|
||||
// inner transaction to multisign
|
||||
TRANSACTION_MULTISIGN = 0x534d5400, // 'SMT'
|
||||
|
||||
// ledger
|
||||
LEDGER = 0x4c575200 // 'LWR'
|
||||
}
|
||||
|
||||
export default HashPrefix
|
||||
219
src/common/hashes/index.ts
Normal file
219
src/common/hashes/index.ts
Normal file
@@ -0,0 +1,219 @@
|
||||
import BigNumber from 'bignumber.js'
|
||||
import {decodeAccountID} from 'ripple-address-codec'
|
||||
import sha512Half from './sha512Half'
|
||||
import HashPrefix from './hash-prefix'
|
||||
import {SHAMap, NodeType} from './shamap'
|
||||
import {encode} from 'ripple-binary-codec'
|
||||
import ledgerspaces from './ledgerspaces'
|
||||
|
||||
const padLeftZero = (string: string, length: number): string => {
|
||||
return Array(length - string.length + 1).join('0') + string
|
||||
}
|
||||
|
||||
const intToHex = (integer: number, byteLength: number): string => {
|
||||
return padLeftZero(Number(integer).toString(16), byteLength * 2)
|
||||
}
|
||||
|
||||
const bytesToHex = (bytes: number[]): string => {
|
||||
return Buffer.from(bytes).toString('hex')
|
||||
}
|
||||
|
||||
const bigintToHex = (
|
||||
integerString: string | number | BigNumber,
|
||||
byteLength: number
|
||||
): string => {
|
||||
const hex = new BigNumber(integerString).toString(16)
|
||||
return padLeftZero(hex, byteLength * 2)
|
||||
}
|
||||
|
||||
const ledgerSpaceHex = (name: string): string => {
|
||||
return intToHex(ledgerspaces[name].charCodeAt(0), 2)
|
||||
}
|
||||
|
||||
const addressToHex = (address: string): string => {
|
||||
return Buffer.from(decodeAccountID(address)).toString('hex')
|
||||
}
|
||||
|
||||
const currencyToHex = (currency: string): string => {
|
||||
if (currency.length === 3) {
|
||||
const bytes = new Array(20 + 1).join('0').split('').map(parseFloat)
|
||||
bytes[12] = currency.charCodeAt(0) & 0xff
|
||||
bytes[13] = currency.charCodeAt(1) & 0xff
|
||||
bytes[14] = currency.charCodeAt(2) & 0xff
|
||||
return bytesToHex(bytes)
|
||||
}
|
||||
return currency
|
||||
}
|
||||
|
||||
const addLengthPrefix = (hex: string): string => {
|
||||
const length = hex.length / 2
|
||||
if (length <= 192) {
|
||||
return bytesToHex([length]) + hex
|
||||
} else if (length <= 12480) {
|
||||
const x = length - 193
|
||||
return bytesToHex([193 + (x >>> 8), x & 0xff]) + hex
|
||||
} else if (length <= 918744) {
|
||||
const x = length - 12481
|
||||
return bytesToHex([241 + (x >>> 16), (x >>> 8) & 0xff, x & 0xff]) + hex
|
||||
}
|
||||
throw new Error('Variable integer overflow.')
|
||||
}
|
||||
|
||||
export const computeBinaryTransactionHash = (txBlobHex: string): string => {
|
||||
const prefix = HashPrefix.TRANSACTION_ID.toString(16).toUpperCase()
|
||||
return sha512Half(prefix + txBlobHex)
|
||||
}
|
||||
|
||||
export const computeTransactionHash = (txJSON: any): string => {
|
||||
return computeBinaryTransactionHash(encode(txJSON))
|
||||
}
|
||||
|
||||
/**
|
||||
* Hash the given binary transaction data with the single-signing prefix.
|
||||
*
|
||||
* See [Serialization Format](https://xrpl.org/serialization.html)
|
||||
*
|
||||
* @param txBlobHex The binary transaction blob as a hexadecimal string
|
||||
* @returns {string} The hash to sign
|
||||
*/
|
||||
export const computeBinaryTransactionSigningHash = (
|
||||
txBlobHex: string
|
||||
): string => {
|
||||
const prefix = HashPrefix.TRANSACTION_SIGN.toString(16).toUpperCase()
|
||||
return sha512Half(prefix + txBlobHex)
|
||||
}
|
||||
|
||||
/**
|
||||
* Compute Account Ledger Object ID
|
||||
*
|
||||
* All objects in a ledger's state tree have a unique ID.
|
||||
* The Account Ledger Object ID is derived by hashing the
|
||||
* address with a namespace identifier. This ensures every
|
||||
* ID is unique.
|
||||
*
|
||||
* See [Ledger Object IDs](https://xrpl.org/ledger-object-ids.html)
|
||||
*
|
||||
* @param address The classic account address
|
||||
* @returns {string} The Ledger Object ID for the account
|
||||
*/
|
||||
export const computeAccountLedgerObjectID = (address: string): string => {
|
||||
return sha512Half(ledgerSpaceHex('account') + addressToHex(address))
|
||||
}
|
||||
|
||||
/**
|
||||
* [SignerList ID Format](https://xrpl.org/signerlist.html#signerlist-id-format)
|
||||
*
|
||||
* The ID of a SignerList object is the SHA-512Half of the following values, concatenated in order:
|
||||
* * The RippleState space key (0x0053)
|
||||
* * The AccountID of the owner of the SignerList
|
||||
* * The SignerListID (currently always 0)
|
||||
*
|
||||
* This method computes a SignerList Ledger Object ID.
|
||||
*
|
||||
* @param address The classic account address of the SignerList owner (starting with r)
|
||||
* @return {string} The ID of the account's SignerList object
|
||||
*/
|
||||
export const computeSignerListLedgerObjectID = (address: string): string => {
|
||||
return sha512Half(
|
||||
ledgerSpaceHex('signerList') + addressToHex(address) + '00000000'
|
||||
) // uint32(0) signer list index
|
||||
}
|
||||
|
||||
/**
|
||||
* [Offer ID Format](https://xrpl.org/offer.html#offer-id-format)
|
||||
*
|
||||
* The ID of a Offer object is the SHA-512Half of the following values, concatenated in order:
|
||||
* * The Offer space key (0x006F)
|
||||
* * The AccountID of the account placing the offer
|
||||
* * The Sequence number of the OfferCreate transaction that created the offer
|
||||
*
|
||||
* This method computes an Offer ID (aka Order ID).
|
||||
*
|
||||
* @param address The classic account address of the SignerList owner (starting with r)
|
||||
* @returns {string} The ID of the account's Offer object
|
||||
*/
|
||||
export const computeOrderID = (address: string, sequence: number): string => {
|
||||
const prefix = '00' + intToHex(ledgerspaces.offer.charCodeAt(0), 1)
|
||||
return sha512Half(prefix + addressToHex(address) + intToHex(sequence, 4))
|
||||
}
|
||||
|
||||
export const computeTrustlineHash = (
|
||||
address1: string,
|
||||
address2: string,
|
||||
currency: string
|
||||
): string => {
|
||||
const address1Hex = addressToHex(address1)
|
||||
const address2Hex = addressToHex(address2)
|
||||
|
||||
const swap = new BigNumber(address1Hex, 16).isGreaterThan(
|
||||
new BigNumber(address2Hex, 16)
|
||||
)
|
||||
const lowAddressHex = swap ? address2Hex : address1Hex
|
||||
const highAddressHex = swap ? address1Hex : address2Hex
|
||||
|
||||
const prefix = ledgerSpaceHex('rippleState')
|
||||
return sha512Half(
|
||||
prefix + lowAddressHex + highAddressHex + currencyToHex(currency)
|
||||
)
|
||||
}
|
||||
|
||||
export const computeTransactionTreeHash = (transactions: any[]): string => {
|
||||
const shamap = new SHAMap()
|
||||
|
||||
transactions.forEach((txJSON) => {
|
||||
const txBlobHex = encode(txJSON)
|
||||
const metaHex = encode(txJSON.metaData)
|
||||
const txHash = computeBinaryTransactionHash(txBlobHex)
|
||||
const data = addLengthPrefix(txBlobHex) + addLengthPrefix(metaHex)
|
||||
shamap.addItem(txHash, data, NodeType.TRANSACTION_METADATA)
|
||||
})
|
||||
|
||||
return shamap.hash
|
||||
}
|
||||
|
||||
export const computeStateTreeHash = (entries: any[]): string => {
|
||||
const shamap = new SHAMap()
|
||||
|
||||
entries.forEach((ledgerEntry) => {
|
||||
const data = encode(ledgerEntry)
|
||||
shamap.addItem(ledgerEntry.index, data, NodeType.ACCOUNT_STATE)
|
||||
})
|
||||
|
||||
return shamap.hash
|
||||
}
|
||||
|
||||
// see rippled Ledger::updateHash()
|
||||
export const computeLedgerHash = (ledgerHeader): string => {
|
||||
const prefix = HashPrefix.LEDGER.toString(16).toUpperCase()
|
||||
return sha512Half(
|
||||
prefix +
|
||||
intToHex(ledgerHeader.ledger_index, 4) +
|
||||
bigintToHex(ledgerHeader.total_coins, 8) +
|
||||
ledgerHeader.parent_hash +
|
||||
ledgerHeader.transaction_hash +
|
||||
ledgerHeader.account_hash +
|
||||
intToHex(ledgerHeader.parent_close_time, 4) +
|
||||
intToHex(ledgerHeader.close_time, 4) +
|
||||
intToHex(ledgerHeader.close_time_resolution, 1) +
|
||||
intToHex(ledgerHeader.close_flags, 1)
|
||||
)
|
||||
}
|
||||
|
||||
export const computeEscrowHash = (address, sequence): string => {
|
||||
return sha512Half(
|
||||
ledgerSpaceHex('escrow') + addressToHex(address) + intToHex(sequence, 4)
|
||||
)
|
||||
}
|
||||
|
||||
export const computePaymentChannelHash = (
|
||||
address,
|
||||
dstAddress,
|
||||
sequence
|
||||
): string => {
|
||||
return sha512Half(
|
||||
ledgerSpaceHex('paychan') +
|
||||
addressToHex(address) +
|
||||
addressToHex(dstAddress) +
|
||||
intToHex(sequence, 4)
|
||||
)
|
||||
}
|
||||
29
src/common/hashes/ledgerspaces.ts
Normal file
29
src/common/hashes/ledgerspaces.ts
Normal file
@@ -0,0 +1,29 @@
|
||||
/**
|
||||
* XRP Ledger namespace prefixes.
|
||||
*
|
||||
* The XRP Ledger is a key-value store. In order to avoid name collisions,
|
||||
* names are partitioned into namespaces.
|
||||
*
|
||||
* Each namespace is just a single character prefix.
|
||||
*
|
||||
* See [LedgerNameSpace enum](https://github.com/ripple/rippled/blob/master/src/ripple/protocol/LedgerFormats.h#L100)
|
||||
*/
|
||||
export default {
|
||||
account: 'a',
|
||||
dirNode: 'd',
|
||||
generatorMap: 'g',
|
||||
rippleState: 'r',
|
||||
offer: 'o', // Entry for an offer.
|
||||
ownerDir: 'O', // Directory of things owned by an account.
|
||||
bookDir: 'B', // Directory of order books.
|
||||
contract: 'c',
|
||||
skipList: 's',
|
||||
escrow: 'u',
|
||||
amendment: 'f',
|
||||
feeSettings: 'e',
|
||||
ticket: 'T',
|
||||
signerList: 'S',
|
||||
paychan: 'x',
|
||||
check: 'C',
|
||||
depositPreauth: 'p'
|
||||
}
|
||||
11
src/common/hashes/sha512Half.ts
Normal file
11
src/common/hashes/sha512Half.ts
Normal file
@@ -0,0 +1,11 @@
|
||||
import {createHash} from 'crypto'
|
||||
|
||||
const sha512Half = (hex: string): string => {
|
||||
return createHash('sha512')
|
||||
.update(Buffer.from(hex, 'hex'))
|
||||
.digest('hex')
|
||||
.toUpperCase()
|
||||
.slice(0, 64)
|
||||
}
|
||||
|
||||
export default sha512Half
|
||||
181
src/common/hashes/shamap.ts
Normal file
181
src/common/hashes/shamap.ts
Normal file
@@ -0,0 +1,181 @@
|
||||
import hashPrefix from './hash-prefix'
|
||||
import sha512Half from './sha512Half'
|
||||
const HEX_ZERO =
|
||||
'0000000000000000000000000000000000000000000000000000000000000000'
|
||||
|
||||
export enum NodeType {
|
||||
INNER = 1,
|
||||
TRANSACTION_NO_METADATA = 2,
|
||||
TRANSACTION_METADATA = 3,
|
||||
ACCOUNT_STATE = 4
|
||||
}
|
||||
|
||||
export abstract class Node {
|
||||
/**
|
||||
* Abstract constructor representing a node in a SHAMap tree.
|
||||
* Can be either InnerNode or Leaf.
|
||||
* @constructor
|
||||
*/
|
||||
public constructor() {}
|
||||
|
||||
public addItem(_tag: string, _node: Node): void {
|
||||
throw new Error(
|
||||
'Called unimplemented virtual method SHAMapTreeNode#addItem.'
|
||||
)
|
||||
}
|
||||
public get hash(): string | void {
|
||||
throw new Error('Called unimplemented virtual method SHAMapTreeNode#hash.')
|
||||
}
|
||||
}
|
||||
|
||||
export class InnerNode extends Node {
|
||||
public leaves: {[slot: number]: Node}
|
||||
public type: NodeType
|
||||
public depth: number
|
||||
public empty: boolean
|
||||
|
||||
/**
|
||||
* Define an Inner (non-leaf) node in a SHAMap tree.
|
||||
* @param {number} depth i.e. how many parent inner nodes
|
||||
* @constructor
|
||||
*/
|
||||
public constructor(depth: number = 0) {
|
||||
super()
|
||||
this.leaves = {}
|
||||
this.type = NodeType.INNER
|
||||
this.depth = depth
|
||||
this.empty = true
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} tag equates to a ledger entry `index`
|
||||
* @param {Node} node to add
|
||||
* @return {void}
|
||||
*/
|
||||
|
||||
public addItem(tag: string, node: Node): void {
|
||||
const existingNode = this.getNode(parseInt(tag[this.depth], 16))
|
||||
if (existingNode) {
|
||||
// A node already exists in this slot
|
||||
if (existingNode instanceof InnerNode) {
|
||||
// There is an inner node, so we need to go deeper
|
||||
existingNode.addItem(tag, node)
|
||||
} else if (existingNode instanceof Leaf) {
|
||||
if (existingNode.tag === tag) {
|
||||
// Collision
|
||||
throw new Error(
|
||||
'Tried to add a node to a SHAMap that was already in there.'
|
||||
)
|
||||
} else {
|
||||
// Turn it into an inner node
|
||||
const newInnerNode = new InnerNode(this.depth + 1)
|
||||
|
||||
// Parent new and existing node
|
||||
newInnerNode.addItem(existingNode.tag, existingNode)
|
||||
newInnerNode.addItem(tag, node)
|
||||
|
||||
// And place the newly created inner node in the slot
|
||||
this.setNode(parseInt(tag[this.depth], 16), newInnerNode)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Neat, we have a nice open spot for the new node
|
||||
this.setNode(parseInt(tag[this.depth], 16), node)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Overwrite the node that is currently in a given slot.
|
||||
* @param {number} slot a number 0-15
|
||||
* @param {Node} node to place
|
||||
* @return {void}
|
||||
*/
|
||||
public setNode(slot: number, node: Node): void {
|
||||
if (slot < 0 || slot > 15) {
|
||||
throw new Error('Invalid slot: slot must be between 0-15.')
|
||||
}
|
||||
this.leaves[slot] = node
|
||||
this.empty = false
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the node that is currently in a given slot.
|
||||
* @param {number} slot a number 0-15
|
||||
* @return {Node}
|
||||
*/
|
||||
public getNode(slot: number): Node {
|
||||
if (slot < 0 || slot > 15) {
|
||||
throw new Error('Invalid slot: slot must be between 0-15.')
|
||||
}
|
||||
return this.leaves[slot]
|
||||
}
|
||||
|
||||
public get hash(): string {
|
||||
if (this.empty) return HEX_ZERO
|
||||
let hex = ''
|
||||
for (let i = 0; i < 16; i++) {
|
||||
hex += this.leaves[i] ? this.leaves[i].hash : HEX_ZERO
|
||||
}
|
||||
const prefix = hashPrefix.INNER_NODE.toString(16)
|
||||
return sha512Half(prefix + hex)
|
||||
}
|
||||
}
|
||||
|
||||
export class Leaf extends Node {
|
||||
public tag: string
|
||||
public type: NodeType
|
||||
public data: string
|
||||
|
||||
/**
|
||||
* Leaf node in a SHAMap tree.
|
||||
* @param {string} tag equates to a ledger entry `index`
|
||||
* @param {string} data hex of account state, transaction etc
|
||||
* @param {number} type one of TYPE_ACCOUNT_STATE, TYPE_TRANSACTION_MD etc
|
||||
* @constructor
|
||||
*/
|
||||
public constructor(tag: string, data: string, type: NodeType) {
|
||||
super()
|
||||
this.tag = tag
|
||||
this.type = type
|
||||
this.data = data
|
||||
}
|
||||
|
||||
public get hash(): string | void {
|
||||
switch (this.type) {
|
||||
case NodeType.ACCOUNT_STATE: {
|
||||
const leafPrefix = hashPrefix.LEAF_NODE.toString(16)
|
||||
return sha512Half(leafPrefix + this.data + this.tag)
|
||||
}
|
||||
case NodeType.TRANSACTION_NO_METADATA: {
|
||||
const txIDPrefix = hashPrefix.TRANSACTION_ID.toString(16)
|
||||
return sha512Half(txIDPrefix + this.data)
|
||||
}
|
||||
case NodeType.TRANSACTION_METADATA: {
|
||||
const txNodePrefix = hashPrefix.TRANSACTION_NODE.toString(16)
|
||||
return sha512Half(txNodePrefix + this.data + this.tag)
|
||||
}
|
||||
default:
|
||||
throw new Error('Tried to hash a SHAMap node of unknown type.')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export class SHAMap {
|
||||
public root: InnerNode
|
||||
|
||||
/**
|
||||
* SHAMap tree.
|
||||
* @constructor
|
||||
*/
|
||||
public constructor() {
|
||||
this.root = new InnerNode(0)
|
||||
}
|
||||
|
||||
public addItem(tag: string, data: string, type: NodeType): void {
|
||||
this.root.addItem(tag, new Leaf(tag, data, type))
|
||||
}
|
||||
|
||||
public get hash(): string {
|
||||
return this.root.hash
|
||||
}
|
||||
}
|
||||
@@ -2,13 +2,29 @@ import * as constants from './constants'
|
||||
import * as errors from './errors'
|
||||
import * as validate from './validate'
|
||||
import * as serverInfo from './serverinfo'
|
||||
export {
|
||||
constants,
|
||||
errors,
|
||||
validate,
|
||||
serverInfo
|
||||
import {xAddressToClassicAddress, isValidXAddress} from 'ripple-address-codec'
|
||||
|
||||
export function ensureClassicAddress(account: string): string {
|
||||
if (isValidXAddress(account)) {
|
||||
const {classicAddress, tag} = xAddressToClassicAddress(account)
|
||||
|
||||
// Except for special cases, X-addresses used for requests
|
||||
// must not have an embedded tag. In other words,
|
||||
// `tag` should be `false`.
|
||||
if (tag !== false) {
|
||||
throw new Error(
|
||||
'This command does not support the use of a tag. Use an address without a tag.'
|
||||
)
|
||||
}
|
||||
|
||||
// For rippled requests that use an account, always use a classic address.
|
||||
return classicAddress
|
||||
} else {
|
||||
return account
|
||||
}
|
||||
}
|
||||
|
||||
export {constants, errors, validate, serverInfo}
|
||||
export {
|
||||
dropsToXrp,
|
||||
xrpToDrops,
|
||||
@@ -18,6 +34,5 @@ export {
|
||||
iso8601ToRippleTime,
|
||||
rippleTimeToISO8601
|
||||
} from './utils'
|
||||
export {default as Connection} from './connection'
|
||||
export {Connection} from './connection'
|
||||
export {txFlags} from './txflags'
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -5,7 +5,7 @@ type Interval = [number, number]
|
||||
|
||||
function mergeIntervals(intervals: Interval[]): Interval[] {
|
||||
const stack: Interval[] = [[-Infinity, -Infinity]]
|
||||
_.sortBy(intervals, x => x[0]).forEach(interval => {
|
||||
_.sortBy(intervals, (x) => x[0]).forEach((interval) => {
|
||||
const lastInterval: Interval = stack.pop()!
|
||||
if (interval[0] <= lastInterval[1] + 1) {
|
||||
stack.push([lastInterval[0], Math.max(interval[1], lastInterval[1])])
|
||||
@@ -18,7 +18,6 @@ function mergeIntervals(intervals: Interval[]): Interval[] {
|
||||
}
|
||||
|
||||
class RangeSet {
|
||||
|
||||
ranges: Array<[number, number]>
|
||||
|
||||
constructor() {
|
||||
@@ -30,12 +29,13 @@ class RangeSet {
|
||||
}
|
||||
|
||||
serialize() {
|
||||
return this.ranges.map(range =>
|
||||
range[0].toString() + '-' + range[1].toString()).join(',')
|
||||
return this.ranges
|
||||
.map((range) => range[0].toString() + '-' + range[1].toString())
|
||||
.join(',')
|
||||
}
|
||||
|
||||
addRange(start: number, end: number) {
|
||||
assert(start <= end, `invalid range ${start} <= ${end}`)
|
||||
assert.ok(start <= end, `invalid range ${start} <= ${end}`)
|
||||
this.ranges = mergeIntervals(this.ranges.concat([[start, end]]))
|
||||
}
|
||||
|
||||
@@ -45,14 +45,14 @@ class RangeSet {
|
||||
|
||||
parseAndAddRanges(rangesString: string) {
|
||||
const rangeStrings = rangesString.split(',')
|
||||
_.forEach(rangeStrings, rangeString => {
|
||||
_.forEach(rangeStrings, (rangeString) => {
|
||||
const range = rangeString.split('-').map(Number)
|
||||
this.addRange(range[0], range.length === 1 ? range[0] : range[1])
|
||||
})
|
||||
}
|
||||
|
||||
containsRange(start: number, end: number) {
|
||||
return _.some(this.ranges, range => range[0] <= start && range[1] >= end)
|
||||
return _.some(this.ranges, (range) => range[0] <= start && range[1] >= end)
|
||||
}
|
||||
|
||||
containsValue(value: number) {
|
||||
|
||||
@@ -2,7 +2,7 @@ import * as _ from 'lodash'
|
||||
import * as assert from 'assert'
|
||||
const {Validator} = require('jsonschema')
|
||||
import {ValidationError} from './errors'
|
||||
import {isValidAddress} from 'ripple-address-codec'
|
||||
import {isValidClassicAddress, isValidXAddress} from 'ripple-address-codec'
|
||||
import {isValidSecret} from './utils'
|
||||
|
||||
function loadSchemas() {
|
||||
@@ -13,6 +13,7 @@ function loadSchemas() {
|
||||
require('./schemas/objects/hash128.json'),
|
||||
require('./schemas/objects/hash256.json'),
|
||||
require('./schemas/objects/sequence.json'),
|
||||
require('./schemas/objects/ticket-sequence.json'),
|
||||
require('./schemas/objects/signature.json'),
|
||||
require('./schemas/objects/issue.json'),
|
||||
require('./schemas/objects/ledger-version.json'),
|
||||
@@ -34,6 +35,8 @@ function loadSchemas() {
|
||||
require('./schemas/objects/destination-address-tag.json'),
|
||||
require('./schemas/objects/transaction-hash.json'),
|
||||
require('./schemas/objects/address.json'),
|
||||
require('./schemas/objects/x-address.json'),
|
||||
require('./schemas/objects/classic-address.json'),
|
||||
require('./schemas/objects/adjustment.json'),
|
||||
require('./schemas/objects/quality.json'),
|
||||
require('./schemas/objects/amount.json'),
|
||||
@@ -60,6 +63,8 @@ function loadSchemas() {
|
||||
require('./schemas/specifications/check-cash.json'),
|
||||
require('./schemas/specifications/check-cancel.json'),
|
||||
require('./schemas/specifications/trustline.json'),
|
||||
require('./schemas/specifications/deposit-preauth.json'),
|
||||
require('./schemas/specifications/account-delete.json'),
|
||||
require('./schemas/output/sign.json'),
|
||||
require('./schemas/output/submit.json'),
|
||||
require('./schemas/output/get-account-info.json'),
|
||||
@@ -111,6 +116,7 @@ function loadSchemas() {
|
||||
require('./schemas/input/prepare-check-create.json'),
|
||||
require('./schemas/input/prepare-check-cash.json'),
|
||||
require('./schemas/input/prepare-check-cancel.json'),
|
||||
require('./schemas/input/prepare-ticket-create.json'),
|
||||
require('./schemas/input/compute-ledger-hash.json'),
|
||||
require('./schemas/input/sign.json'),
|
||||
require('./schemas/input/submit.json'),
|
||||
@@ -119,20 +125,31 @@ function loadSchemas() {
|
||||
require('./schemas/input/verify-payment-channel-claim.json'),
|
||||
require('./schemas/input/combine.json')
|
||||
]
|
||||
const titles = schemas.map(schema => schema.title)
|
||||
const duplicates = _.keys(_.pickBy(_.countBy(titles), count => count > 1))
|
||||
assert(duplicates.length === 0, 'Duplicate schemas for: ' + duplicates)
|
||||
const titles = schemas.map((schema) => schema.title)
|
||||
const duplicates = _.keys(_.pickBy(_.countBy(titles), (count) => count > 1))
|
||||
assert.ok(duplicates.length === 0, 'Duplicate schemas for: ' + duplicates)
|
||||
const validator = new Validator()
|
||||
// Register custom format validators that ignore undefined instances
|
||||
// since jsonschema will still call the format validator on a missing
|
||||
// (optional) property
|
||||
validator.customFormats.address = function(instance) {
|
||||
|
||||
// This relies on "format": "xAddress" in `x-address.json`!
|
||||
validator.customFormats.xAddress = function (instance) {
|
||||
if (instance === undefined) {
|
||||
return true
|
||||
}
|
||||
return isValidXAddress(instance)
|
||||
}
|
||||
|
||||
// This relies on "format": "classicAddress" in `classic-address.json`!
|
||||
validator.customFormats.classicAddress = function (instance) {
|
||||
if (instance === undefined) {
|
||||
return true
|
||||
}
|
||||
return isValidAddress(instance)
|
||||
}
|
||||
validator.customFormats.secret = function(instance) {
|
||||
|
||||
validator.customFormats.secret = function (instance) {
|
||||
if (instance === undefined) {
|
||||
return true
|
||||
}
|
||||
@@ -140,7 +157,9 @@ function loadSchemas() {
|
||||
}
|
||||
|
||||
// Register under the root URI '/'
|
||||
_.forEach(schemas, schema => validator.addSchema(schema, '/' + schema.title))
|
||||
_.forEach(schemas, (schema) =>
|
||||
validator.addSchema(schema, '/' + schema.title)
|
||||
)
|
||||
return validator
|
||||
}
|
||||
|
||||
@@ -158,8 +177,8 @@ function schemaValidate(schemaName: string, object: any): void {
|
||||
}
|
||||
}
|
||||
|
||||
export {
|
||||
schemaValidate,
|
||||
isValidSecret,
|
||||
isValidAddress
|
||||
function isValidAddress(address: string): boolean {
|
||||
return isValidXAddress(address) || isValidClassicAddress(address)
|
||||
}
|
||||
|
||||
export {schemaValidate, isValidSecret, isValidAddress}
|
||||
|
||||
@@ -28,7 +28,12 @@
|
||||
},
|
||||
"timeout": {
|
||||
"type": "integer",
|
||||
"description": "Timeout in milliseconds before considering a request to have failed.",
|
||||
"description": "Request timeout in milliseconds before considering a request to have failed. See also: connectionTimeout.",
|
||||
"minimum": 1
|
||||
},
|
||||
"connectionTimeout": {
|
||||
"type": "integer",
|
||||
"description": "Connection timeout, in milliseconds, before considering connect() to have failed.",
|
||||
"minimum": 1
|
||||
},
|
||||
"proxyAuthorization": {
|
||||
|
||||
@@ -14,12 +14,20 @@
|
||||
"minimum": 0,
|
||||
"maximum": 255
|
||||
},
|
||||
"description": "The entropy to use to generate the seed."
|
||||
"description": "The entropy to use to generate the seed. Must be an array of length 16 with values from 0-255 (16 bytes of entropy)"
|
||||
},
|
||||
"algorithm": {
|
||||
"type": "string",
|
||||
"enum": ["ecdsa-secp256k1", "ed25519"],
|
||||
"description": "The digital signature algorithm to generate an address for. Can be `ecdsa-secp256k1` (default) or `ed25519`."
|
||||
},
|
||||
"test": {
|
||||
"type": "boolean",
|
||||
"description": "Specifies whether the address is intended for use on a test network such as Testnet or Devnet. If `true`, the address should only be used for testing, and will start with `T`. If `false`, the address should only be used on mainnet, and will start with `X`."
|
||||
},
|
||||
"includeClassicAddress": {
|
||||
"type": "boolean",
|
||||
"description": "If `true`, return the classic address, in addition to the X-address."
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
|
||||
37
src/common/schemas/input/generate-x-address.json
Normal file
37
src/common/schemas/input/generate-x-address.json
Normal file
@@ -0,0 +1,37 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-04/schema#",
|
||||
"title": "generateXAddressParameters",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"options": {
|
||||
"type": "object",
|
||||
"description": "Options to control how the address and secret are generated.",
|
||||
"properties": {
|
||||
"entropy": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "integer",
|
||||
"minimum": 0,
|
||||
"maximum": 255
|
||||
},
|
||||
"description": "The entropy to use to generate the seed. Must be an array of length 16 with values from 0-255 (16 bytes of entropy)"
|
||||
},
|
||||
"algorithm": {
|
||||
"type": "string",
|
||||
"enum": ["ecdsa-secp256k1", "ed25519"],
|
||||
"description": "The digital signature algorithm to generate an address for. Can be `ecdsa-secp256k1` (default) or `ed25519`."
|
||||
},
|
||||
"test": {
|
||||
"type": "boolean",
|
||||
"description": "Specifies whether the address is intended for use on a test network such as Testnet or Devnet. If `true`, the address should only be used for testing, and will start with `T`. If `false`, the address should only be used on mainnet, and will start with `X`."
|
||||
},
|
||||
"includeClassicAddress": {
|
||||
"type": "boolean",
|
||||
"description": "Specifies whether the classic address should also be included in the returned payload."
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
18
src/common/schemas/input/prepare-ticket-create.json
Normal file
18
src/common/schemas/input/prepare-ticket-create.json
Normal file
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-04/schema#",
|
||||
"title": "prepareTicketParameters",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"address": {
|
||||
"$ref": "address",
|
||||
"description": "The address of the account that is creating the transaction."
|
||||
},
|
||||
"ticketCount": {
|
||||
"type": "number",
|
||||
"description": "The number of tickets to be created."
|
||||
},
|
||||
"instructions": {"$ref": "instructions"}
|
||||
},
|
||||
"additionalProperties": false,
|
||||
"required": ["address", "ticketCount"]
|
||||
}
|
||||
@@ -6,6 +6,10 @@
|
||||
"signedTransaction": {
|
||||
"$ref": "blob",
|
||||
"description": "A signed transaction as returned by [sign](#sign)."
|
||||
},
|
||||
"failHard": {
|
||||
"type": "boolean",
|
||||
"description": "If `true`, and the transaction fails locally, do not retry or relay the transaction to other servers. Defaults to `false`."
|
||||
}
|
||||
},
|
||||
"additionalProperties": false,
|
||||
|
||||
@@ -1,9 +1,12 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-04/schema#",
|
||||
"title": "address",
|
||||
"description": "A Ripple account address",
|
||||
"description": "An account address on the XRP Ledger",
|
||||
"type": "string",
|
||||
"format": "address",
|
||||
"link": "address",
|
||||
"pattern": "^r[1-9A-HJ-NP-Za-km-z]{25,34}$"
|
||||
"oneOf": [
|
||||
{"$ref": "xAddress"},
|
||||
{"$ref": "classicAddress"}
|
||||
]
|
||||
}
|
||||
|
||||
9
src/common/schemas/objects/classic-address.json
Normal file
9
src/common/schemas/objects/classic-address.json
Normal file
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-04/schema#",
|
||||
"title": "classicAddress",
|
||||
"description": "A classic address (Account ID) for the XRP Ledger",
|
||||
"type": "string",
|
||||
"format": "classicAddress",
|
||||
"link": "classic-address",
|
||||
"pattern": "^r[1-9A-HJ-NP-Za-km-z]{24,34}$"
|
||||
}
|
||||
@@ -6,9 +6,13 @@
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"sequence": {
|
||||
"description": "The initiating account's sequence number for this transaction.",
|
||||
"description": "The initiating account's sequence number for this transaction. `sequence` and `ticketSequence` are mutually exclusive, only one of them can be set.",
|
||||
"$ref": "sequence"
|
||||
},
|
||||
"ticketSequence": {
|
||||
"description": "The ticket sequence to be used for this transaction. `sequence` and `ticketSequence` are mutually exclusive, only one of them can be set.",
|
||||
"$ref": "ticket-sequence"
|
||||
},
|
||||
"fee": {
|
||||
"description": "An exact fee to pay for the transaction, before multiplying for multi-signed transactions. See [Transaction Fees](#transaction-fees) for more information.",
|
||||
"$ref": "value"
|
||||
@@ -45,6 +49,10 @@
|
||||
{
|
||||
"description": "maxLedgerVersion and maxLedgerVersionOffset are mutually exclusive",
|
||||
"required": ["maxLedgerVersion", "maxLedgerVersionOffset"]
|
||||
},
|
||||
{
|
||||
"description": "sequence and ticketSequence are mutually exclusive",
|
||||
"required": ["sequence", "ticketSequence"]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -4,5 +4,5 @@
|
||||
"link": "account-sequence-number",
|
||||
"description": "An account transaction sequence number",
|
||||
"type": "integer",
|
||||
"minimum": 1
|
||||
"minimum": 0
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
},
|
||||
"domain": {
|
||||
"type": "string",
|
||||
"description": " The domain that owns this account, as a hexadecimal string representing the ASCII for the domain in lowercase."
|
||||
"description": "The domain that owns this account, as a hexadecimal string representing the ASCII for the domain in lowercase."
|
||||
},
|
||||
"emailHash": {
|
||||
"description": "Hash of an email address to be used for generating an avatar image. Conventionally, clients use Gravatar to display this image. Use `null` to clear.",
|
||||
@@ -30,6 +30,13 @@
|
||||
{"$ref": "hash128"}
|
||||
]
|
||||
},
|
||||
"walletLocator": {
|
||||
"description": "Transaction hash or any other 64 character hexadecimal string, that may or may not represent the result of a hash operation. Use `null` to clear.",
|
||||
"oneOf": [
|
||||
{"type": "null"},
|
||||
{"$ref": "hash256"}
|
||||
]
|
||||
},
|
||||
"enableTransactionIDTracking": {
|
||||
"type": "boolean",
|
||||
"description": "Track the ID of this account’s most recent transaction."
|
||||
@@ -98,11 +105,15 @@
|
||||
"additionalProperties": false
|
||||
},
|
||||
"transferRate": {
|
||||
"description": " The fee to charge when users transfer this account’s issuances, as the decimal amount that must be sent to deliver 1 unit. Has precision up to 9 digits beyond the decimal point. Use `null` to set no fee.",
|
||||
"description": "The fee to charge when users transfer this account’s issuances, as the decimal amount that must be sent to deliver 1 unit. Has precision up to 9 digits beyond the decimal point. Use `null` to set no fee.",
|
||||
"oneOf": [
|
||||
{"type": "null"},
|
||||
{"type": "number", "minimum": 1, "maximum": 4.294967295}
|
||||
]
|
||||
},
|
||||
"tickSize": {
|
||||
"description": "Tick size to use for offers involving a currency issued by this address. The exchange rates of those offers is rounded to this many significant digits. Valid values are 3 to 15 inclusive, or 0 to disable.",
|
||||
"enum": [0, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-04/schema#",
|
||||
"title": "tag",
|
||||
"description": "An arbitrary unsigned 32-bit integer that identifies a reason for payment or a non-Ripple account.",
|
||||
"description": "An arbitrary 32-bit unsigned integer. It typically maps to an off-ledger account; for example, a hosted wallet or exchange account.",
|
||||
"type": "integer",
|
||||
"$ref": "uint32"
|
||||
}
|
||||
|
||||
8
src/common/schemas/objects/ticket-sequence.json
Normal file
8
src/common/schemas/objects/ticket-sequence.json
Normal file
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-04/schema#",
|
||||
"title": "ticket-sequence",
|
||||
"link": "account-sequence-number",
|
||||
"description": "An account transaction tickt sequence number",
|
||||
"type": "integer",
|
||||
"minimum": 1
|
||||
}
|
||||
@@ -18,6 +18,8 @@
|
||||
"paymentChannelClaim",
|
||||
"checkCreate",
|
||||
"checkCancel",
|
||||
"checkCash"
|
||||
"checkCash",
|
||||
"depositPreauth",
|
||||
"accountDelete"
|
||||
]
|
||||
}
|
||||
|
||||
9
src/common/schemas/objects/x-address.json
Normal file
9
src/common/schemas/objects/x-address.json
Normal file
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-04/schema#",
|
||||
"title": "xAddress",
|
||||
"description": "An XRP Ledger address in X-address format",
|
||||
"type": "string",
|
||||
"format": "xAddress",
|
||||
"link": "x-address",
|
||||
"pattern": "^[XT][1-9A-HJ-NP-Za-km-z]{46}$"
|
||||
}
|
||||
@@ -3,16 +3,24 @@
|
||||
"title": "generateAddress",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"xAddress": {
|
||||
"$ref": "xAddress",
|
||||
"description": "A randomly generated XRP Ledger address in X-address format."
|
||||
},
|
||||
"classicAddress": {
|
||||
"$ref": "classicAddress",
|
||||
"description": "A randomly generated XRP Ledger Account ID (classic address)."
|
||||
},
|
||||
"address": {
|
||||
"$ref": "address",
|
||||
"description": "A randomly generated Ripple account address."
|
||||
"$ref": "classicAddress",
|
||||
"description": "Deprecated: Use `classicAddress` instead."
|
||||
},
|
||||
"secret": {
|
||||
"type": "string",
|
||||
"format": "secret",
|
||||
"description": "The secret corresponding to the `address`."
|
||||
"description": "The secret corresponding to the address."
|
||||
}
|
||||
},
|
||||
"required": ["address", "secret"],
|
||||
"required": ["xAddress", "classicAddress", "address", "secret"],
|
||||
"additionalProperties": false
|
||||
}
|
||||
|
||||
18
src/common/schemas/output/generate-x-address.json
Normal file
18
src/common/schemas/output/generate-x-address.json
Normal file
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-04/schema#",
|
||||
"title": "generateXAddress",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"xAddress": {
|
||||
"$ref": "xAddress",
|
||||
"description": "A randomly generated XRP Ledger address in X-address format."
|
||||
},
|
||||
"secret": {
|
||||
"type": "string",
|
||||
"format": "secret",
|
||||
"description": "The secret corresponding to the address."
|
||||
}
|
||||
},
|
||||
"required": ["xAddress", "secret"],
|
||||
"additionalProperties": false
|
||||
}
|
||||
@@ -10,12 +10,12 @@
|
||||
"closeTime": {
|
||||
"type": "string",
|
||||
"format": "date-time",
|
||||
"description": "The time at which this ledger was closed."
|
||||
"description": "The approximate time when this ledger was closed. This number is rounded based on the `closeTimeResolution`. If it would have been rounded to the same time as a previous ledger, the close time is recorded as 1 second later instead."
|
||||
},
|
||||
"closeTimeResolution": {
|
||||
"type": "integer",
|
||||
"minimum": 1,
|
||||
"description": "Approximate number of seconds between closing one ledger version and closing the next one."
|
||||
"description": "A number of seconds, indicating how much the `closeTime` could be rounded. Ledger close times are approximate so that small differences in servers clocks don't hinder consensus."
|
||||
},
|
||||
"closeFlags": {
|
||||
"type": "integer",
|
||||
@@ -37,7 +37,7 @@
|
||||
"parentCloseTime": {
|
||||
"type": "string",
|
||||
"format": "date-time",
|
||||
"description": "The time at which the previous ledger was closed."
|
||||
"description": "The previous ledger's recorded close time."
|
||||
},
|
||||
"totalDrops": {
|
||||
"$ref": "value",
|
||||
|
||||
@@ -208,6 +208,30 @@
|
||||
"$ref": "paymentChannelClaim"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"type": {
|
||||
"enum": [
|
||||
"depositPreauth"
|
||||
]
|
||||
},
|
||||
"specification": {
|
||||
"$ref": "depositPreauth"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"type": {
|
||||
"enum": [
|
||||
"accountDelete"
|
||||
]
|
||||
},
|
||||
"specification": {
|
||||
"$ref": "accountDelete"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -18,7 +18,11 @@
|
||||
},
|
||||
"sequence": {
|
||||
"$ref": "sequence",
|
||||
"description": "The initiating account's sequence number for this transaction."
|
||||
"description": "The initiating account's sequence number for this transaction. `sequence` and `ticketSequence` are mutually exclusive, only one of them can be set."
|
||||
},
|
||||
"ticketSequence": {
|
||||
"$ref": "ticket-sequence",
|
||||
"description": "The initiating account's ticket sequence number for this transaction. `sequence` and `ticketSequence` are mutually exclusive, only one of them can be set."
|
||||
},
|
||||
"maxLedgerVersion": {
|
||||
"oneOf": [
|
||||
@@ -29,8 +33,14 @@
|
||||
}
|
||||
},
|
||||
"additionalProperties": false,
|
||||
"required": ["fee", "sequence", "maxLedgerVersion"]
|
||||
}
|
||||
"required": ["fee", "maxLedgerVersion"],
|
||||
"anyOf": [
|
||||
{ "required":
|
||||
[ "sequence" ] },
|
||||
{ "required":
|
||||
[ "ticketSequence" ] }
|
||||
]
|
||||
}
|
||||
},
|
||||
"additionalProperties": false,
|
||||
"required": ["txJSON", "instructions"]
|
||||
|
||||
29
src/common/schemas/specifications/account-delete.json
Normal file
29
src/common/schemas/specifications/account-delete.json
Normal file
@@ -0,0 +1,29 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-04/schema#",
|
||||
"title": "accountDelete",
|
||||
"link": "account-delete",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"destination": {
|
||||
"$ref": "address",
|
||||
"description": "Address of an account to receive any leftover XRP after deleting the sending account. Must be a funded account in the ledger, and must not be the sending account."
|
||||
},
|
||||
"destinationTag": {
|
||||
"$ref": "tag",
|
||||
"description": "(Optional) Arbitrary destination tag that identifies a hosted recipient or other information for the recipient of the deleted account's leftover XRP."
|
||||
},
|
||||
"destinationXAddress": {
|
||||
"$ref": "address",
|
||||
"description": "X-address of an account to receive any leftover XRP after deleting the sending account. Must be a funded account in the ledger, and must not be the sending account."
|
||||
}
|
||||
},
|
||||
"anyOf": [
|
||||
{
|
||||
"required": ["destination"]
|
||||
},
|
||||
{
|
||||
"required": ["destinationXAddress"]
|
||||
}
|
||||
],
|
||||
"additionalProperties": false
|
||||
}
|
||||
21
src/common/schemas/specifications/deposit-preauth.json
Normal file
21
src/common/schemas/specifications/deposit-preauth.json
Normal file
@@ -0,0 +1,21 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-04/schema#",
|
||||
"title": "depositPreauth",
|
||||
"link": "deposit-preauth",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"authorize": {
|
||||
"$ref": "address",
|
||||
"description": "Address of the account that can cash the check."
|
||||
},
|
||||
"unauthorize": {
|
||||
"$ref": "address",
|
||||
"description": "Address of the account that can cash the check."
|
||||
}
|
||||
},
|
||||
"oneOf": [
|
||||
{"required": ["authorize"]},
|
||||
{"required": ["unauthorize"]}
|
||||
],
|
||||
"additionalProperties": false
|
||||
}
|
||||
@@ -4,32 +4,33 @@ import BigNumber from 'bignumber.js'
|
||||
import {RippleAPI} from '..'
|
||||
|
||||
export type GetServerInfoResponse = {
|
||||
buildVersion: string,
|
||||
completeLedgers: string,
|
||||
hostID: string,
|
||||
ioLatencyMs: number,
|
||||
buildVersion: string
|
||||
completeLedgers: string
|
||||
hostID: string
|
||||
ioLatencyMs: number
|
||||
load?: {
|
||||
jobTypes: Array<object>,
|
||||
jobTypes: Array<object>
|
||||
threads: number
|
||||
},
|
||||
}
|
||||
lastClose: {
|
||||
convergeTimeS: number,
|
||||
convergeTimeS: number
|
||||
proposers: number
|
||||
},
|
||||
loadFactor: number,
|
||||
peers: number,
|
||||
pubkeyNode: string,
|
||||
pubkeyValidator?: string,
|
||||
serverState: string,
|
||||
}
|
||||
loadFactor: number
|
||||
peers: number
|
||||
pubkeyNode: string
|
||||
pubkeyValidator?: string
|
||||
serverState: string
|
||||
validatedLedger: {
|
||||
age: number,
|
||||
baseFeeXRP: string,
|
||||
hash: string,
|
||||
reserveBaseXRP: string,
|
||||
reserveIncrementXRP: string,
|
||||
age: number
|
||||
baseFeeXRP: string
|
||||
hash: string
|
||||
reserveBaseXRP: string
|
||||
reserveIncrementXRP: string
|
||||
ledgerVersion: number
|
||||
},
|
||||
}
|
||||
validationQuorum: number
|
||||
networkLedger?: string
|
||||
}
|
||||
|
||||
function renameKeys(object, mapping) {
|
||||
@@ -40,7 +41,7 @@ function renameKeys(object, mapping) {
|
||||
}
|
||||
|
||||
function getServerInfo(this: RippleAPI): Promise<GetServerInfoResponse> {
|
||||
return this.request('server_info').then(response => {
|
||||
return this.request('server_info').then((response) => {
|
||||
const info = convertKeysFromSnakeCaseToCamelCase(response.info)
|
||||
renameKeys(info, {hostid: 'hostID'})
|
||||
if (info.validatedLedger) {
|
||||
@@ -50,12 +51,9 @@ function getServerInfo(this: RippleAPI): Promise<GetServerInfoResponse> {
|
||||
reserveIncXrp: 'reserveIncrementXRP',
|
||||
seq: 'ledgerVersion'
|
||||
})
|
||||
info.validatedLedger.baseFeeXRP =
|
||||
info.validatedLedger.baseFeeXRP.toString()
|
||||
info.validatedLedger.reserveBaseXRP =
|
||||
info.validatedLedger.reserveBaseXRP.toString()
|
||||
info.validatedLedger.reserveIncrementXRP =
|
||||
info.validatedLedger.reserveIncrementXRP.toString()
|
||||
info.validatedLedger.baseFeeXRP = info.validatedLedger.baseFeeXRP.toString()
|
||||
info.validatedLedger.reserveBaseXRP = info.validatedLedger.reserveBaseXRP.toString()
|
||||
info.validatedLedger.reserveIncrementXRP = info.validatedLedger.reserveIncrementXRP.toString()
|
||||
}
|
||||
return info
|
||||
})
|
||||
@@ -63,10 +61,7 @@ function getServerInfo(this: RippleAPI): Promise<GetServerInfoResponse> {
|
||||
|
||||
// This is a public API that can be called directly.
|
||||
// This is not used by the `prepare*` methods. See `src/transaction/utils.ts`
|
||||
async function getFee(
|
||||
this: RippleAPI,
|
||||
cushion?: number
|
||||
): Promise<string> {
|
||||
async function getFee(this: RippleAPI, cushion?: number): Promise<string> {
|
||||
if (cushion === undefined) {
|
||||
cushion = this._feeCushion
|
||||
}
|
||||
@@ -81,10 +76,7 @@ async function getFee(
|
||||
// Cap fee to `this._maxFeeXRP`
|
||||
fee = BigNumber.min(fee, this._maxFeeXRP)
|
||||
// Round fee to 6 decimal places
|
||||
return (new BigNumber(fee.toFixed(6))).toString(10)
|
||||
return new BigNumber(fee.toFixed(6)).toString(10)
|
||||
}
|
||||
|
||||
export {
|
||||
getServerInfo,
|
||||
getFee
|
||||
}
|
||||
export {getServerInfo, getFee}
|
||||
|
||||
@@ -58,7 +58,4 @@ const txFlagIndices = {
|
||||
}
|
||||
}
|
||||
|
||||
export {
|
||||
txFlags,
|
||||
txFlagIndices
|
||||
}
|
||||
export {txFlags, txFlagIndices}
|
||||
|
||||
@@ -5,19 +5,19 @@ import {
|
||||
} from '../objects'
|
||||
|
||||
export interface AccountInfoRequest {
|
||||
account: string,
|
||||
strict?: boolean,
|
||||
queue?: boolean,
|
||||
ledger_hash?: string,
|
||||
ledger_index?: number | ('validated' | 'closed' | 'current'),
|
||||
account: string
|
||||
strict?: boolean
|
||||
queue?: boolean
|
||||
ledger_hash?: string
|
||||
ledger_index?: number | ('validated' | 'closed' | 'current')
|
||||
signer_lists?: boolean
|
||||
}
|
||||
|
||||
export interface AccountInfoResponse {
|
||||
account_data: AccountRootLedgerEntry,
|
||||
signer_lists?: SignerListLedgerEntry[],
|
||||
ledger_current_index?: number,
|
||||
ledger_index?: number,
|
||||
queue_data?: QueueData,
|
||||
account_data: AccountRootLedgerEntry
|
||||
signer_lists?: SignerListLedgerEntry[]
|
||||
ledger_current_index?: number
|
||||
ledger_index?: number
|
||||
queue_data?: QueueData
|
||||
validated?: boolean
|
||||
}
|
||||
|
||||
@@ -1,19 +1,19 @@
|
||||
import {Trustline} from '../objects'
|
||||
|
||||
export interface AccountLinesRequest {
|
||||
account: string,
|
||||
ledger_hash?: string,
|
||||
ledger_index?: number | ('validated' | 'closed' | 'current'),
|
||||
peer?: string,
|
||||
limit?: number,
|
||||
marker?: any,
|
||||
account: string
|
||||
ledger_hash?: string
|
||||
ledger_index?: number | ('validated' | 'closed' | 'current')
|
||||
peer?: string
|
||||
limit?: number
|
||||
marker?: any
|
||||
}
|
||||
|
||||
export interface AccountLinesResponse {
|
||||
account: string,
|
||||
lines: Trustline[],
|
||||
ledger_current_index?: number,
|
||||
ledger_index?: number,
|
||||
ledger_hash?: string,
|
||||
marker?: any,
|
||||
account: string
|
||||
lines: Trustline[]
|
||||
ledger_current_index?: number
|
||||
ledger_index?: number
|
||||
ledger_hash?: string
|
||||
marker?: any
|
||||
}
|
||||
|
||||
@@ -1,84 +1,91 @@
|
||||
import {
|
||||
CheckLedgerEntry, RippleStateLedgerEntry,
|
||||
OfferLedgerEntry, SignerListLedgerEntry,
|
||||
EscrowLedgerEntry, PayChannelLedgerEntry,
|
||||
CheckLedgerEntry,
|
||||
RippleStateLedgerEntry,
|
||||
OfferLedgerEntry,
|
||||
SignerListLedgerEntry,
|
||||
EscrowLedgerEntry,
|
||||
PayChannelLedgerEntry,
|
||||
DepositPreauthLedgerEntry
|
||||
} from '../objects'
|
||||
|
||||
export interface GetAccountObjectsOptions {
|
||||
type?: string | (
|
||||
'check' |
|
||||
'escrow' |
|
||||
'offer' |
|
||||
'payment_channel' |
|
||||
'signer_list' |
|
||||
'state'
|
||||
),
|
||||
ledgerHash?: string,
|
||||
ledgerIndex?: number | ('validated' | 'closed' | 'current'),
|
||||
limit?: number,
|
||||
type?:
|
||||
| string
|
||||
| (
|
||||
| 'check'
|
||||
| 'escrow'
|
||||
| 'offer'
|
||||
| 'payment_channel'
|
||||
| 'signer_list'
|
||||
| 'state'
|
||||
)
|
||||
ledgerHash?: string
|
||||
ledgerIndex?: number | ('validated' | 'closed' | 'current')
|
||||
limit?: number
|
||||
marker?: string
|
||||
}
|
||||
|
||||
export interface AccountObjectsRequest {
|
||||
account: string,
|
||||
account: string
|
||||
|
||||
// (Optional) Filter results to include only this type of ledger object.
|
||||
type?: string | (
|
||||
'check' |
|
||||
'escrow' |
|
||||
'offer' |
|
||||
'payment_channel' |
|
||||
'signer_list' |
|
||||
'state'
|
||||
),
|
||||
type?:
|
||||
| string
|
||||
| (
|
||||
| 'check'
|
||||
| 'escrow'
|
||||
| 'offer'
|
||||
| 'payment_channel'
|
||||
| 'signer_list'
|
||||
| 'state'
|
||||
)
|
||||
|
||||
// (Optional) A 20-byte hex string for the ledger version to use.
|
||||
ledger_hash?: string,
|
||||
ledger_hash?: string
|
||||
|
||||
// (Optional) The sequence number of the ledger to use,
|
||||
// or a shortcut string to choose a ledger automatically.
|
||||
ledger_index?: number | ('validated' | 'closed' | 'current'),
|
||||
ledger_index?: number | ('validated' | 'closed' | 'current')
|
||||
|
||||
limit?: number,
|
||||
limit?: number
|
||||
|
||||
marker?: string
|
||||
}
|
||||
|
||||
export interface AccountObjectsResponse {
|
||||
account: string,
|
||||
account: string
|
||||
|
||||
// Array of objects owned by this account.
|
||||
// from the getAccountObjects section of the dev center
|
||||
account_objects: Array<
|
||||
CheckLedgerEntry |
|
||||
RippleStateLedgerEntry |
|
||||
OfferLedgerEntry |
|
||||
SignerListLedgerEntry |
|
||||
EscrowLedgerEntry |
|
||||
PayChannelLedgerEntry |
|
||||
DepositPreauthLedgerEntry
|
||||
>,
|
||||
| CheckLedgerEntry
|
||||
| RippleStateLedgerEntry
|
||||
| OfferLedgerEntry
|
||||
| SignerListLedgerEntry
|
||||
| EscrowLedgerEntry
|
||||
| PayChannelLedgerEntry
|
||||
| DepositPreauthLedgerEntry
|
||||
>
|
||||
|
||||
// (May be omitted) The identifying hash of the ledger
|
||||
// that was used to generate this response.
|
||||
ledger_hash?: string,
|
||||
ledger_hash?: string
|
||||
|
||||
// (May be omitted) The sequence number of the ledger version
|
||||
// that was used to generate this response.
|
||||
ledger_index?: number,
|
||||
ledger_index?: number
|
||||
|
||||
// (May be omitted) The sequence number of the current in-progress ledger
|
||||
// version that was used to generate this response.
|
||||
ledger_current_index?: number,
|
||||
ledger_current_index?: number
|
||||
|
||||
// The limit that was used in this request, if any.
|
||||
limit?: number,
|
||||
limit?: number
|
||||
|
||||
// Server-defined value indicating the response is paginated. Pass this
|
||||
// to the next call to resume where this call left off. Omitted when there
|
||||
// are no additional pages after this one.
|
||||
marker?: string,
|
||||
marker?: string
|
||||
|
||||
// If true, this information comes from a ledger version
|
||||
// that has been validated by consensus.
|
||||
|
||||
@@ -1,27 +1,27 @@
|
||||
import {RippledAmount} from '../objects'
|
||||
|
||||
export interface AccountOffersRequest {
|
||||
account: string,
|
||||
ledger_hash?: string,
|
||||
ledger_index?: number | ('validated' | 'closed' | 'current'),
|
||||
limit?: number,
|
||||
marker?: any,
|
||||
account: string
|
||||
ledger_hash?: string
|
||||
ledger_index?: number | ('validated' | 'closed' | 'current')
|
||||
limit?: number
|
||||
marker?: any
|
||||
}
|
||||
|
||||
export interface AccountOffersResponse {
|
||||
account: string,
|
||||
ledger_hash?: string,
|
||||
ledger_current_index?: number,
|
||||
ledger_index?: number,
|
||||
marker?: any,
|
||||
offers?: AccountOffer[],
|
||||
account: string
|
||||
ledger_hash?: string
|
||||
ledger_current_index?: number
|
||||
ledger_index?: number
|
||||
marker?: any
|
||||
offers?: AccountOffer[]
|
||||
}
|
||||
|
||||
export interface AccountOffer {
|
||||
seq: number,
|
||||
flags: number,
|
||||
taker_gets: RippledAmount,
|
||||
taker_pays: RippledAmount,
|
||||
quality: string,
|
||||
seq: number
|
||||
flags: number
|
||||
taker_gets: RippledAmount
|
||||
taker_pays: RippledAmount
|
||||
quality: string
|
||||
expiration?: number
|
||||
}
|
||||
|
||||
@@ -1,30 +1,26 @@
|
||||
import {
|
||||
TakerRequestAmount,
|
||||
RippledAmount,
|
||||
OfferLedgerEntry
|
||||
} from '../objects'
|
||||
import {TakerRequestAmount, RippledAmount, OfferLedgerEntry} from '../objects'
|
||||
|
||||
export interface BookOffersRequest {
|
||||
taker?: string,
|
||||
taker_gets: TakerRequestAmount,
|
||||
taker_pays: TakerRequestAmount,
|
||||
ledger_hash?: string,
|
||||
ledger_index?: number | ('validated' | 'closed' | 'current'),
|
||||
limit?: number,
|
||||
taker?: string
|
||||
taker_gets: TakerRequestAmount
|
||||
taker_pays: TakerRequestAmount
|
||||
ledger_hash?: string
|
||||
ledger_index?: number | ('validated' | 'closed' | 'current')
|
||||
limit?: number
|
||||
marker?: any
|
||||
}
|
||||
|
||||
export interface BookOffersResponse {
|
||||
offers: BookOffer[],
|
||||
ledger_hash?: string,
|
||||
ledger_current_index?: number,
|
||||
ledger_index?: number,
|
||||
offers: BookOffer[]
|
||||
ledger_hash?: string
|
||||
ledger_current_index?: number
|
||||
ledger_index?: number
|
||||
marker?: any
|
||||
}
|
||||
|
||||
export interface BookOffer extends OfferLedgerEntry {
|
||||
quality?: string
|
||||
owner_funds?: string,
|
||||
taker_gets_funded?: RippledAmount,
|
||||
owner_funds?: string
|
||||
taker_gets_funded?: RippledAmount
|
||||
taker_pays_funded?: RippledAmount
|
||||
}
|
||||
|
||||
@@ -1,19 +1,19 @@
|
||||
import {Amount} from '../objects'
|
||||
|
||||
export interface GatewayBalancesRequest {
|
||||
account: string,
|
||||
strict?: boolean,
|
||||
hotwallet: string|Array<string>,
|
||||
ledger_hash?: string,
|
||||
account: string
|
||||
strict?: boolean
|
||||
hotwallet: string | Array<string>
|
||||
ledger_hash?: string
|
||||
ledger_index?: number | ('validated' | 'closed' | 'current')
|
||||
}
|
||||
|
||||
export interface GatewayBalancesResponse {
|
||||
account: string,
|
||||
obligations?: {[currency: string]: string},
|
||||
balances?: {[address: string]: Amount[]},
|
||||
assets?: {[address: string]: Amount[]},
|
||||
ledger_hash?: string,
|
||||
ledger_current_index?: number,
|
||||
account: string
|
||||
obligations?: {[currency: string]: string}
|
||||
balances?: {[address: string]: Amount[]}
|
||||
assets?: {[address: string]: Amount[]}
|
||||
ledger_hash?: string
|
||||
ledger_current_index?: number
|
||||
ledger_index?: number
|
||||
}
|
||||
|
||||
@@ -5,5 +5,6 @@ export * from './account_offers'
|
||||
export * from './book_offers'
|
||||
export * from './gateway_balances'
|
||||
export * from './ledger'
|
||||
export * from './ledger_data'
|
||||
export * from './ledger_entry'
|
||||
export * from './server_info'
|
||||
|
||||
12
src/common/types/commands/ledger_data.ts
Normal file
12
src/common/types/commands/ledger_data.ts
Normal file
@@ -0,0 +1,12 @@
|
||||
import {LedgerData} from '../objects'
|
||||
|
||||
export interface LedgerDataRequest {
|
||||
id?: any
|
||||
ledger_hash?: string
|
||||
ledger_index?: string
|
||||
binary?: boolean
|
||||
limit?: number
|
||||
marker?: string
|
||||
}
|
||||
|
||||
export type LedgerDataResponse = LedgerData
|
||||
@@ -3,29 +3,34 @@ import {LedgerEntry} from '../objects'
|
||||
export interface LedgerEntryRequest {
|
||||
ledger_hash?: string
|
||||
ledger_index?: number | ('validated' | 'closed' | 'current')
|
||||
index?: string,
|
||||
account_root?: string,
|
||||
directory?: string | {
|
||||
sub_index?: number,
|
||||
dir_root: string
|
||||
} | {
|
||||
sub_index?: number,
|
||||
owner: string
|
||||
},
|
||||
offer?: string | {
|
||||
account: string,
|
||||
seq: number
|
||||
},
|
||||
index?: string
|
||||
account_root?: string
|
||||
directory?:
|
||||
| string
|
||||
| {
|
||||
sub_index?: number
|
||||
dir_root: string
|
||||
}
|
||||
| {
|
||||
sub_index?: number
|
||||
owner: string
|
||||
}
|
||||
offer?:
|
||||
| string
|
||||
| {
|
||||
account: string
|
||||
seq: number
|
||||
}
|
||||
ripple_state?: {
|
||||
accounts: [string, string],
|
||||
accounts: [string, string]
|
||||
currency: string
|
||||
},
|
||||
}
|
||||
binary?: boolean
|
||||
}
|
||||
|
||||
export interface LedgerEntryResponse {
|
||||
index: string,
|
||||
ledger_index: number,
|
||||
node_binary?: string,
|
||||
node?: LedgerEntry,
|
||||
index: string
|
||||
ledger_index: number
|
||||
node_binary?: string
|
||||
node?: LedgerEntry
|
||||
}
|
||||
|
||||
@@ -4,48 +4,48 @@ export interface ServerInfoRequest {
|
||||
|
||||
export interface ServerInfoResponse {
|
||||
info: {
|
||||
amendment_blocked?: boolean,
|
||||
build_version: string,
|
||||
closed_ledger?: LedgerInfo,
|
||||
complete_ledgers: string,
|
||||
hostid: string,
|
||||
io_latency_ms: number,
|
||||
amendment_blocked?: boolean
|
||||
build_version: string
|
||||
closed_ledger?: LedgerInfo
|
||||
complete_ledgers: string
|
||||
hostid: string
|
||||
io_latency_ms: number
|
||||
last_close: {
|
||||
converge_time_s: number,
|
||||
converge_time_s: number
|
||||
proposers: number
|
||||
},
|
||||
}
|
||||
load?: {
|
||||
job_types: {
|
||||
job_type: string,
|
||||
per_second: number,
|
||||
job_type: string
|
||||
per_second: number
|
||||
in_progress: number
|
||||
}[],
|
||||
}[]
|
||||
threads: number
|
||||
},
|
||||
load_factor: number,
|
||||
load_factor_local?: number,
|
||||
load_factor_net?: number,
|
||||
load_factor_cluster?: number,
|
||||
load_factor_fee_escalation?: number,
|
||||
load_factor_fee_queue?: number,
|
||||
load_factor_server?: number,
|
||||
peers: number,
|
||||
pubkey_node: string,
|
||||
pubkey_validator: string,
|
||||
server_state: string,
|
||||
state_accounting: any,
|
||||
uptime: number,
|
||||
validated_ledger?: LedgerInfo,
|
||||
validation_quorum: number,
|
||||
}
|
||||
load_factor: number
|
||||
load_factor_local?: number
|
||||
load_factor_net?: number
|
||||
load_factor_cluster?: number
|
||||
load_factor_fee_escalation?: number
|
||||
load_factor_fee_queue?: number
|
||||
load_factor_server?: number
|
||||
peers: number
|
||||
pubkey_node: string
|
||||
pubkey_validator: string
|
||||
server_state: string
|
||||
state_accounting: any
|
||||
uptime: number
|
||||
validated_ledger?: LedgerInfo
|
||||
validation_quorum: number
|
||||
validator_list_expires: string
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
export interface LedgerInfo {
|
||||
age: number,
|
||||
base_fee_xrp: number,
|
||||
hash: string,
|
||||
reserve_base_xrp: number,
|
||||
reserve_inc_xrp: number,
|
||||
seq: number,
|
||||
age: number
|
||||
base_fee_xrp: number
|
||||
hash: string
|
||||
reserve_base_xrp: number
|
||||
reserve_inc_xrp: number
|
||||
seq: number
|
||||
}
|
||||
|
||||
@@ -1,19 +1,19 @@
|
||||
import {Amount} from './amounts'
|
||||
|
||||
export type Adjustment = {
|
||||
address: string,
|
||||
amount: Amount,
|
||||
address: string
|
||||
amount: Amount
|
||||
tag?: number
|
||||
}
|
||||
|
||||
export type MaxAdjustment = {
|
||||
address: string,
|
||||
maxAmount: Amount,
|
||||
address: string
|
||||
maxAmount: Amount
|
||||
tag?: number
|
||||
}
|
||||
|
||||
export type MinAdjustment = {
|
||||
address: string,
|
||||
minAmount: Amount,
|
||||
address: string
|
||||
minAmount: Amount
|
||||
tag?: number
|
||||
}
|
||||
|
||||
@@ -2,7 +2,6 @@ export interface Amount extends Issue {
|
||||
value: string
|
||||
}
|
||||
|
||||
|
||||
export type RippledAmount = string | Amount
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
export * from './adjustments'
|
||||
export * from './amounts'
|
||||
export * from './ledger'
|
||||
export * from './ledger_data'
|
||||
export * from './ledger_entries'
|
||||
export * from './memos'
|
||||
export * from './orders'
|
||||
|
||||
@@ -1,23 +1,37 @@
|
||||
export interface Ledger {
|
||||
account_hash: string,
|
||||
close_time: number,
|
||||
close_time_human: string,
|
||||
close_time_resolution: number,
|
||||
closed: boolean,
|
||||
ledger_hash: string,
|
||||
ledger_index: string,
|
||||
parent_hash: string,
|
||||
total_coins: string,
|
||||
transaction_hash: string,
|
||||
transactions: string[] | object[],
|
||||
account_hash: string
|
||||
close_time: number
|
||||
close_time_human: string
|
||||
close_time_resolution: number
|
||||
closed: boolean
|
||||
ledger_hash: string
|
||||
ledger_index: string
|
||||
parent_hash: string
|
||||
total_coins: string
|
||||
transaction_hash: string
|
||||
transactions: string[] | object[]
|
||||
// @deprecated
|
||||
seqNum?: string,
|
||||
seqNum?: string
|
||||
// @deprecated
|
||||
totalCoins?: string,
|
||||
totalCoins?: string
|
||||
// @deprecated
|
||||
hash?: string,
|
||||
close_flags?: number,
|
||||
parent_close_time?: number,
|
||||
accountState?: any[],
|
||||
hash?: string
|
||||
close_flags?: number
|
||||
parent_close_time?: number
|
||||
accountState?: any[]
|
||||
validated?: boolean
|
||||
}
|
||||
|
||||
// https://xrpl.org/subscribe.html#ledger-stream
|
||||
export type LedgerClosedEvent = {
|
||||
type: 'ledgerClosed'
|
||||
fee_base: number
|
||||
fee_ref: number
|
||||
ledger_hash: string
|
||||
ledger_index: number
|
||||
ledger_time: number
|
||||
reserve_base: number
|
||||
reserve_inc: number
|
||||
txn_count: number
|
||||
validated_ledgers: string
|
||||
}
|
||||
|
||||
6
src/common/types/objects/ledger_data.ts
Normal file
6
src/common/types/objects/ledger_data.ts
Normal file
@@ -0,0 +1,6 @@
|
||||
export interface LedgerData {
|
||||
ledger_index: string
|
||||
ledger_hash: string
|
||||
marker: string
|
||||
state: ({data?: string; LedgerEntryType?: string; index: string} & any)[]
|
||||
}
|
||||
@@ -2,188 +2,189 @@ import {SignerEntry} from './index'
|
||||
import {Amount, RippledAmount} from './amounts'
|
||||
|
||||
export interface AccountRootLedgerEntry {
|
||||
LedgerEntryType: 'AccountRoot',
|
||||
Account: string,
|
||||
Balance: string,
|
||||
Flags: number,
|
||||
OwnerCount: number,
|
||||
PreviousTxnID: string,
|
||||
PreviousTxnLgrSeq: number,
|
||||
Sequence: number,
|
||||
AccountTxnID?: string,
|
||||
Domain?: string,
|
||||
EmailHash?: string,
|
||||
LedgerEntryType: 'AccountRoot'
|
||||
Account: string
|
||||
Balance: string
|
||||
Flags: number
|
||||
OwnerCount: number
|
||||
PreviousTxnID: string
|
||||
PreviousTxnLgrSeq: number
|
||||
Sequence: number
|
||||
AccountTxnID?: string
|
||||
Domain?: string
|
||||
EmailHash?: string
|
||||
MessageKey?: string
|
||||
RegularKey?: string,
|
||||
TickSize?: number,
|
||||
TransferRate?: number,
|
||||
WalletLocator?: string, // DEPRECATED
|
||||
RegularKey?: string
|
||||
TickSize?: number
|
||||
TransferRate?: number
|
||||
WalletLocator?: string
|
||||
WalletSize?: number // DEPRECATED
|
||||
}
|
||||
|
||||
export interface AmendmentsLedgerEntry {
|
||||
LedgerEntryType: 'Amendments',
|
||||
Amendments?: string[],
|
||||
Majorities?: any[],
|
||||
LedgerEntryType: 'Amendments'
|
||||
Amendments?: string[]
|
||||
Majorities?: any[]
|
||||
Flags: 0
|
||||
}
|
||||
|
||||
export interface CheckLedgerEntry {
|
||||
LedgerEntryType: 'Check',
|
||||
Account: string,
|
||||
Destination, string,
|
||||
Flags: 0,
|
||||
OwnerNode: string,
|
||||
PreviousTxnID: string,
|
||||
PreviousTxnLgrSeq: number,
|
||||
SendMax: string | object,
|
||||
Sequence: number,
|
||||
DestinationNode: string,
|
||||
DestinationTag: number,
|
||||
Expiration: number,
|
||||
InvoiceID: string,
|
||||
LedgerEntryType: 'Check'
|
||||
Account: string
|
||||
Destination
|
||||
string
|
||||
Flags: 0
|
||||
OwnerNode: string
|
||||
PreviousTxnID: string
|
||||
PreviousTxnLgrSeq: number
|
||||
SendMax: string | object
|
||||
Sequence: number
|
||||
DestinationNode: string
|
||||
DestinationTag: number
|
||||
Expiration: number
|
||||
InvoiceID: string
|
||||
SourceTag: number
|
||||
}
|
||||
|
||||
export interface DepositPreauthLedgerEntry {
|
||||
LedgerEntryType: 'DepositPreauth',
|
||||
Account: string,
|
||||
Authorize: string,
|
||||
OwnerNode: string,
|
||||
PreviousTxnID: string,
|
||||
LedgerEntryType: 'DepositPreauth'
|
||||
Account: string
|
||||
Authorize: string
|
||||
OwnerNode: string
|
||||
PreviousTxnID: string
|
||||
PreviousTxnLgrSeq: number
|
||||
}
|
||||
|
||||
export interface DirectoryNodeLedgerEntry {
|
||||
LedgerEntryType: 'DirectoryNode',
|
||||
Flags: number,
|
||||
RootIndex: string,
|
||||
Indexes: string[],
|
||||
IndexNext?: number,
|
||||
LedgerEntryType: 'DirectoryNode'
|
||||
Flags: number
|
||||
RootIndex: string
|
||||
Indexes: string[]
|
||||
IndexNext?: number
|
||||
IndexPrevious?: number
|
||||
}
|
||||
|
||||
export interface OfferDirectoryNodeLedgerEntry
|
||||
extends DirectoryNodeLedgerEntry {
|
||||
TakerPaysCurrency: string,
|
||||
TakerPaysIssuer: string,
|
||||
TakerGetsCurrency: string,
|
||||
TakerGetsIssuer: string,
|
||||
extends DirectoryNodeLedgerEntry {
|
||||
TakerPaysCurrency: string
|
||||
TakerPaysIssuer: string
|
||||
TakerGetsCurrency: string
|
||||
TakerGetsIssuer: string
|
||||
ExchangeRate?: number // DEPRECATED
|
||||
}
|
||||
|
||||
export interface OwnerDirectoryNodeLedgerEntry
|
||||
extends DirectoryNodeLedgerEntry {
|
||||
Owner: string,
|
||||
Owner: string
|
||||
}
|
||||
|
||||
export interface EscrowLedgerEntry {
|
||||
LedgerEntryType: 'Escrow',
|
||||
Account: string,
|
||||
Destination: string,
|
||||
Amount: string,
|
||||
Condition?: string,
|
||||
CancelAfter?: number,
|
||||
FinishAfter?: number,
|
||||
Flags: number,
|
||||
SourceTag?: number,
|
||||
DestinationTag?: number,
|
||||
OwnerNode: string,
|
||||
DestinationNode?: string,
|
||||
PreviousTxnID: string,
|
||||
LedgerEntryType: 'Escrow'
|
||||
Account: string
|
||||
Destination: string
|
||||
Amount: string
|
||||
Condition?: string
|
||||
CancelAfter?: number
|
||||
FinishAfter?: number
|
||||
Flags: number
|
||||
SourceTag?: number
|
||||
DestinationTag?: number
|
||||
OwnerNode: string
|
||||
DestinationNode?: string
|
||||
PreviousTxnID: string
|
||||
PreviousTxnLgrSeq: number
|
||||
}
|
||||
|
||||
export interface FeeSettingsLedgerEntry {
|
||||
LedgerEntryType: 'FeeSettings',
|
||||
BaseFee: string,
|
||||
ReferenceFeeUnits: number,
|
||||
ReserveBase: number,
|
||||
ReserveIncrement: number,
|
||||
LedgerEntryType: 'FeeSettings'
|
||||
BaseFee: string
|
||||
ReferenceFeeUnits: number
|
||||
ReserveBase: number
|
||||
ReserveIncrement: number
|
||||
Flags: number
|
||||
}
|
||||
|
||||
export interface LedgerHashesLedgerEntry {
|
||||
LedgerEntryType: 'LedgerHashes',
|
||||
Hashes: string[],
|
||||
Flags: number,
|
||||
FirstLedgerSequence?: number, // DEPRECATED
|
||||
LedgerEntryType: 'LedgerHashes'
|
||||
Hashes: string[]
|
||||
Flags: number
|
||||
FirstLedgerSequence?: number // DEPRECATED
|
||||
LastLedgerSequence?: number
|
||||
}
|
||||
|
||||
export interface OfferLedgerEntry {
|
||||
LedgerEntryType: 'Offer',
|
||||
Flags: number,
|
||||
Account: string,
|
||||
Sequence: number,
|
||||
TakerPays: RippledAmount,
|
||||
TakerGets: RippledAmount,
|
||||
BookDirectory: string,
|
||||
BookNode: string,
|
||||
OwnerNode: string,
|
||||
PreviousTxnID: string,
|
||||
PreviousTxnLgrSeq: number,
|
||||
LedgerEntryType: 'Offer'
|
||||
Flags: number
|
||||
Account: string
|
||||
Sequence: number
|
||||
TakerPays: RippledAmount
|
||||
TakerGets: RippledAmount
|
||||
BookDirectory: string
|
||||
BookNode: string
|
||||
OwnerNode: string
|
||||
PreviousTxnID: string
|
||||
PreviousTxnLgrSeq: number
|
||||
Expiration?: number
|
||||
}
|
||||
|
||||
export interface PayChannelLedgerEntry {
|
||||
LedgerEntryType: 'PayChannel',
|
||||
Sequence: number,
|
||||
Account: string,
|
||||
Amount: string,
|
||||
Balance: string,
|
||||
PublicKey: string,
|
||||
Destination: string,
|
||||
SettleDelay: number,
|
||||
Expiration?: number,
|
||||
CancelAfter?: number,
|
||||
SourceTag?: number,
|
||||
DestinationTag?: number,
|
||||
OwnerNode: string,
|
||||
PreviousTxnID: string,
|
||||
PreviousTxnLgrSeq: number,
|
||||
LedgerEntryType: 'PayChannel'
|
||||
Sequence: number
|
||||
Account: string
|
||||
Amount: string
|
||||
Balance: string
|
||||
PublicKey: string
|
||||
Destination: string
|
||||
SettleDelay: number
|
||||
Expiration?: number
|
||||
CancelAfter?: number
|
||||
SourceTag?: number
|
||||
DestinationTag?: number
|
||||
OwnerNode: string
|
||||
PreviousTxnID: string
|
||||
PreviousTxnLgrSeq: number
|
||||
index: string
|
||||
}
|
||||
|
||||
export interface RippleStateLedgerEntry {
|
||||
LedgerEntryType: 'RippleState',
|
||||
Flags: number,
|
||||
Balance: Amount,
|
||||
LowLimit: Amount,
|
||||
HighLimit: Amount,
|
||||
PreviousTxnID: string,
|
||||
PreviousTxnLgrSeq: number,
|
||||
LowNode?: string,
|
||||
HighNode?: string,
|
||||
LowQualityIn?: number,
|
||||
LowQualityOut?: number,
|
||||
HighQualityIn?: number,
|
||||
LedgerEntryType: 'RippleState'
|
||||
Flags: number
|
||||
Balance: Amount
|
||||
LowLimit: Amount
|
||||
HighLimit: Amount
|
||||
PreviousTxnID: string
|
||||
PreviousTxnLgrSeq: number
|
||||
LowNode?: string
|
||||
HighNode?: string
|
||||
LowQualityIn?: number
|
||||
LowQualityOut?: number
|
||||
HighQualityIn?: number
|
||||
HighQualityOut?: number
|
||||
}
|
||||
|
||||
export interface SignerListLedgerEntry {
|
||||
LedgerEntryType: 'SignerList',
|
||||
OwnerNode: string,
|
||||
SignerQuorum: number,
|
||||
SignerEntries: SignerEntry[],
|
||||
SignerListID: number,
|
||||
PreviousTxnID: string,
|
||||
LedgerEntryType: 'SignerList'
|
||||
OwnerNode: string
|
||||
SignerQuorum: number
|
||||
SignerEntries: SignerEntry[]
|
||||
SignerListID: number
|
||||
PreviousTxnID: string
|
||||
PreviousTxnLgrSeq: number
|
||||
}
|
||||
|
||||
// see https://ripple.com/build/ledger-format/#ledger-object-types
|
||||
export type LedgerEntry =
|
||||
AccountRootLedgerEntry |
|
||||
AmendmentsLedgerEntry |
|
||||
CheckLedgerEntry |
|
||||
DepositPreauthLedgerEntry |
|
||||
DirectoryNodeLedgerEntry |
|
||||
OfferDirectoryNodeLedgerEntry |
|
||||
OwnerDirectoryNodeLedgerEntry |
|
||||
EscrowLedgerEntry |
|
||||
FeeSettingsLedgerEntry |
|
||||
LedgerHashesLedgerEntry |
|
||||
OfferLedgerEntry |
|
||||
PayChannelLedgerEntry |
|
||||
RippleStateLedgerEntry |
|
||||
SignerListLedgerEntry
|
||||
| AccountRootLedgerEntry
|
||||
| AmendmentsLedgerEntry
|
||||
| CheckLedgerEntry
|
||||
| DepositPreauthLedgerEntry
|
||||
| DirectoryNodeLedgerEntry
|
||||
| OfferDirectoryNodeLedgerEntry
|
||||
| OwnerDirectoryNodeLedgerEntry
|
||||
| EscrowLedgerEntry
|
||||
| FeeSettingsLedgerEntry
|
||||
| LedgerHashesLedgerEntry
|
||||
| OfferLedgerEntry
|
||||
| PayChannelLedgerEntry
|
||||
| RippleStateLedgerEntry
|
||||
| SignerListLedgerEntry
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
|
||||
export type Memo = {
|
||||
type?: string,
|
||||
format?: string,
|
||||
type?: string
|
||||
format?: string
|
||||
data?: string
|
||||
}
|
||||
|
||||
@@ -2,14 +2,14 @@ import {Amount} from './amounts'
|
||||
import {Memo} from './memos'
|
||||
|
||||
export type FormattedOrderSpecification = {
|
||||
direction: string,
|
||||
quantity: Amount,
|
||||
totalPrice: Amount,
|
||||
immediateOrCancel?: boolean,
|
||||
fillOrKill?: boolean,
|
||||
expirationTime?: string,
|
||||
orderToReplace?: number,
|
||||
memos?: Memo[],
|
||||
direction: string
|
||||
quantity: Amount
|
||||
totalPrice: Amount
|
||||
immediateOrCancel?: boolean
|
||||
fillOrKill?: boolean
|
||||
expirationTime?: string
|
||||
orderToReplace?: number
|
||||
memos?: Memo[]
|
||||
// If enabled, the offer will not consume offers that exactly match it, and
|
||||
// instead becomes an Offer node in the ledger. It will still consume offers
|
||||
// that cross it.
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
export interface QueueTransaction {
|
||||
auth_change: boolean,
|
||||
fee: string,
|
||||
fee_level: string,
|
||||
max_spend_drops: string,
|
||||
auth_change: boolean
|
||||
fee: string
|
||||
fee_level: string
|
||||
max_spend_drops: string
|
||||
seq: number
|
||||
}
|
||||
|
||||
export interface QueueData {
|
||||
txn_count: number,
|
||||
auth_change_queued?: boolean,
|
||||
lowest_sequence?: number,
|
||||
highest_sequence?: number,
|
||||
max_spend_drops_total?: string,
|
||||
txn_count: number
|
||||
auth_change_queued?: boolean
|
||||
lowest_sequence?: number
|
||||
highest_sequence?: number
|
||||
max_spend_drops_total?: string
|
||||
transactions?: QueueTransaction[]
|
||||
}
|
||||
|
||||
@@ -1,31 +1,33 @@
|
||||
import {Memo} from './memos'
|
||||
|
||||
export type WeightedSigner = {
|
||||
address: string,
|
||||
address: string
|
||||
weight: number
|
||||
}
|
||||
|
||||
export type Signers = {
|
||||
threshold?: number,
|
||||
threshold?: number
|
||||
weights: WeightedSigner[]
|
||||
}
|
||||
|
||||
export type FormattedSettings = {
|
||||
defaultRipple?: boolean,
|
||||
depositAuth?: boolean,
|
||||
disableMasterKey?: boolean,
|
||||
disallowIncomingXRP?: boolean,
|
||||
domain?: string,
|
||||
emailHash?: string|null,
|
||||
enableTransactionIDTracking?: boolean,
|
||||
globalFreeze?: boolean,
|
||||
memos?: Memo[],
|
||||
messageKey?: string,
|
||||
noFreeze?: boolean,
|
||||
passwordSpent?: boolean,
|
||||
regularKey?: string,
|
||||
requireAuthorization?: boolean,
|
||||
requireDestinationTag?: boolean,
|
||||
signers?: Signers,
|
||||
transferRate?: number|null
|
||||
defaultRipple?: boolean
|
||||
depositAuth?: boolean
|
||||
disableMasterKey?: boolean
|
||||
disallowIncomingXRP?: boolean
|
||||
domain?: string
|
||||
emailHash?: string | null
|
||||
walletLocator?: string | null
|
||||
enableTransactionIDTracking?: boolean
|
||||
globalFreeze?: boolean
|
||||
memos?: Memo[]
|
||||
messageKey?: string
|
||||
noFreeze?: boolean
|
||||
passwordSpent?: boolean
|
||||
regularKey?: string
|
||||
requireAuthorization?: boolean
|
||||
requireDestinationTag?: boolean
|
||||
signers?: Signers
|
||||
transferRate?: number | null
|
||||
tickSize?: number
|
||||
}
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
export interface SignerEntry {
|
||||
Account: string,
|
||||
SignerWeight: number
|
||||
SignerEntry: {
|
||||
Account: string
|
||||
SignerWeight: number
|
||||
}
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user