Compare commits

...

5 Commits
1.1.0 ... 1.1.1

Author SHA1 Message Date
Elliot Lee
fcc205b85a Release 1.1.1 2018-11-27 15:17:42 -08:00
Elliot Lee
0f5056221f Fix getOrderbook (#970)
* Fix `getOrderbook` (Fix #766)
* Add `formatBidsAndAsks` as a recommended alternative to `getOrderbook`
* Add `renameCounterpartyToIssuer`
2018-11-26 15:25:15 -08:00
Elliot Lee
8384ace746 Add return type for generateAddress (#968)
For TypeScript apps
2018-11-20 15:35:34 -08:00
Elliot Lee
040cabece0 Add comments for accountRootFlags (#962) 2018-11-16 22:34:41 -08:00
Elliot Lee
319a8d6ab2 Fix book-offers test fixture by swapping bids/asks (#966) 2018-10-31 22:48:27 -07:00
23 changed files with 18748 additions and 495 deletions

View File

@@ -1,5 +1,29 @@
# ripple-lib Release History
## 1.1.1 (2018-11-27)
+ Fix `getOrderbook` offer sorting (#970)
+ **BREAKING CHANGE:** The ordering of offers returned by `getOrderbook` has
been changed so that offers with the best quality are sorted first
+ Add new helper methods for working with the `rippled` APIs:
+ `formatBidsAndAsks`: Takes offers and returns a formatted order book object
with bids and asks
+ `renameCounterpartyToIssuer`: Takes an object and renames the `counterparty`
field to `issuer`
+ TypeScript: Add return type for `generateAddress` (#968)
When using `ripple-lib` with `rippled`, we recommend using `rippled` version 1.1.1 or
later.
The SHA-256 checksums for the browser version of this release can be found
below.
```
% shasum -a 256 *
e151900e49bb5482b02bef5b0b1542ea586076363b072ae616f6d4d2f7f5b8a1 ripple-1.1.1-debug.js
6aee3757b29de285f361e20862261090033c07a13fd09f4a3cc4c097b6e84b55 ripple-1.1.1-min.js
bea4a889fb9ee4092324c6667490ea66469bdde869ddc1aaddf5e9d12b0cf091 ripple-1.1.1.js
```
## 1.1.0 (2018-10-31)
+ Add support for Node.js v10 LTS (#964)

View File

@@ -38,6 +38,9 @@
- [request](#request)
- [hasNextPage](#hasnextpage)
- [requestNextPage](#requestnextpage)
- [Static Methods](#static-methods)
- [renameCounterpartyToIssuer](#renamecounterpartytoissuer)
- [formatBidsAndAsks](#formatbidsandasks)
- [API Methods](#api-methods)
- [connect](#connect)
- [disconnect](#disconnect)
@@ -950,6 +953,326 @@ return api.request(command, params).then(response => {
}).catch(console.error);
```
# Static Methods
## renameCounterpartyToIssuer
`renameCounterpartyToIssuer(issue: {currency: string, counterparty: address}): {currency: string, issuer: address}`
Returns an object with the `counterparty` field renamed to `issuer`. This is useful because RippleAPI generally uses the name `counterparty` while the rippled API generally uses the name `issuer`.
This is a static method on the `RippleAPI` class.
### Parameters
This method takes one parameter, an object with a `counterparty` field.
### Return Value
This method returns a new object similar to the source object, but with `issuer` instead of `counterparty`.
### Example
```javascript
const orderbookInfo = {
"base": {
"currency": "USD",
"counterparty": "rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B"
},
"counter": {
"currency": "BTC",
"counterparty": "rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B"
}
};
console.log(RippleAPI.renameCounterpartyToIssuer(orderbookInfo.base))
console.log(RippleAPI.renameCounterpartyToIssuer(orderbookInfo.counter))
```
```
{ currency: 'USD', issuer: 'rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B' }
{ currency: 'BTC', issuer: 'rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B' }
```
## formatBidsAndAsks
`formatBidsAndAsks(orderbookInfo: {base: Issue, counter: Issue}, offers: BookOffer[]): orderbook`
Returns formatted bids and asks, which make up an orderbook.
This is a static method on the `RippleAPI` class.
### Parameters
This method takes two parameters.
1. An `OrderbookInfo` object: `{ base: Issue, counter: Issue }`.
2. An array of `BookOffer` objects.
### Return Value
This method returns an object with two properties: `bids` and `asks`, each of which is an array of bids (buy orders) or asks (sell orders), respectively. (Note: the structures of `bids` and `asks` are identical.)
Object structure:
Name | Type | Description
---- | ---- | -----------
bids | array | The buy orders in the order book.
bids[] | object | An order in the order book.
*bids[].* specification | [order](#order) | An order specification that would create an order equivalent to the current state of this order.
*bids[].* properties | object | Properties of the order not in the specification.
*bids[].properties.* maker | [address](#address) | The address of the account that submitted the order.
*bids[].properties.* sequence | [sequence](#account-sequence-number) | The account sequence number of the transaction that created this order.
*bids[].properties.* makerExchangeRate | [value](#value) | The exchange rate from the point of view of the account that submitted the order (also known as "quality").
*bids[].data.* \* | object |
*bids[].* state | object | *Optional* The state of the order.
*bids[].state.* fundedAmount | [amount](#amount) | How much of the amount the maker would have to pay that the maker currently holds.
*bids[].state.* priceOfFundedAmount | [amount](#amount) | How much the `fundedAmount` would convert to through the exchange rate of this order.
asks | array | The sell orders in the order book.
asks[] | object | An order in the order book.
*asks[].* specification | [order](#order) | An order specification that would create an order equivalent to the current state of this order.
*asks[].* properties | object | Properties of the order not in the specification.
*asks[].properties.* maker | [address](#address) | The address of the account that submitted the order.
*asks[].properties.* sequence | [sequence](#account-sequence-number) | The account sequence number of the transaction that created this order.
*asks[].properties.* makerExchangeRate | [value](#value) | The exchange rate from the point of view of the account that submitted the order (also known as "quality").
*asks[].data.* \* | object |
*asks[].* state | object | *Optional* The state of the order.
*asks[].state.* fundedAmount | [amount](#amount) | How much of the amount the maker would have to pay that the maker currently holds.
*asks[].state.* priceOfFundedAmount | [amount](#amount) | How much the `fundedAmount` would convert to through the exchange rate of this order.
**Raw order data:** The response includes a `data` property containing the raw order data. This may include `owner_funds`, `Flags`, and other fields.
For details, see the rippled method [book_offers](https://ripple.com/build/rippled-apis/#book-offers).
### Example
```javascript
const orderbookInfo = {
"base": {
"currency": "USD",
"counterparty": "rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B"
},
"counter": {
"currency": "BTC",
"counterparty": "rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B"
}
};
const address = 'r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59';
return Promise.all(
[
this.api.request('book_offers', {
taker_gets: RippleAPI.renameCounterpartyToIssuer(orderbookInfo.base),
taker_pays: RippleAPI.renameCounterpartyToIssuer(orderbookInfo.counter),
ledger_index: 'validated',
limit: 20,
taker: address
}),
this.api.request('book_offers', {
taker_gets: RippleAPI.renameCounterpartyToIssuer(orderbookInfo.counter),
taker_pays: RippleAPI.renameCounterpartyToIssuer(orderbookInfo.base),
ledger_index: 'validated',
limit: 20,
taker: address
})
]
).then((directOfferResults, reverseOfferResults) => {
const directOffers = (directOfferResults ? directOfferResults : []).reduce((acc, res) => acc.concat(res.offers), [])
const reverseOffers = (reverseOfferResults ? reverseOfferResults : []).reduce((acc, res) => acc.concat(res.offers), [])
const orderbook = RippleAPI.formatBidsAndAsks(orderbookInfo, [...directOffers, ...reverseOffers]);
console.log(JSON.stringify(orderbook, null, 2));
});
```
```
{
"bids": [
{
"specification": {
"direction": "buy",
"quantity": {
"currency": "USD",
"value": "0.71800168",
"counterparty": "rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B"
},
"totalPrice": {
"currency": "BTC",
"value": "0.00016708342",
"counterparty": "rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B"
}
},
"properties": {
"maker": "rUKoQ1Zhn6c8EfPsaVa2Yx5NqaKN1JQSvq",
"sequence": 262660,
"makerExchangeRate": "4297.264683713081"
},
"data": {
"Account": "rUKoQ1Zhn6c8EfPsaVa2Yx5NqaKN1JQSvq",
"BookDirectory": "6EAB7C172DEFA430DBFAD120FDC373B5F5AF8B191649EC98580F4456E6FA8239",
"BookNode": "0000000000000000",
"Flags": 0,
"LedgerEntryType": "Offer",
"OwnerNode": "000000000000001D",
"PreviousTxnID": "16D75506C6317723FC03543130B5E0AAB13E8AD22514C1DB098BE05771C90447",
"PreviousTxnLgrSeq": 43127860,
"Sequence": 262660,
"TakerGets": {
"currency": "BTC",
"issuer": "rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B",
"value": "0.00016708342"
},
"TakerPays": {
"currency": "USD",
"issuer": "rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B",
"value": "0.71800168"
},
"index": "DE877FB94EF892A4BCC58DB8CDE063D97AB5133201905DE6C8650B5DEA19E11B",
"owner_funds": "0.03358376764081196",
"quality": "4297.264683713081"
}
},
{
"specification": {
"direction": "buy",
"quantity": {
"currency": "USD",
"value": "1.6770875",
"counterparty": "rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B"
},
"totalPrice": {
"currency": "BTC",
"value": "0.00038681218",
"counterparty": "rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B"
}
},
"properties": {
"maker": "rpmL45YbZWKgp8AH8EjBSknWo5c8dNuuBM",
"sequence": 231459,
"makerExchangeRate": "4335.663628792661"
},
"data": {
"Account": "rpmL45YbZWKgp8AH8EjBSknWo5c8dNuuBM",
"BookDirectory": "6EAB7C172DEFA430DBFAD120FDC373B5F5AF8B191649EC98580F67435A75B355",
"BookNode": "0000000000000000",
"Flags": 0,
"LedgerEntryType": "Offer",
"OwnerNode": "0000000000000001",
"PreviousTxnID": "F049EAFDDDA7B99970F77533743D95C9E12A16FE6C56215A0B09C32C4D23163F",
"PreviousTxnLgrSeq": 43127094,
"Sequence": 231459,
"TakerGets": {
"currency": "BTC",
"issuer": "rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B",
"value": "0.00038681218"
},
"TakerPays": {
"currency": "USD",
"issuer": "rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B",
"value": "1.6770875"
},
"index": "3B314A51BD57601CA1509834DF9462037BF4B05AFCC1E1EFD334DB4E2D7B2AA6",
"owner_funds": "0.03906802968738533",
"quality": "4335.663628792661"
}
},
// ... trimmed for brevity ...
],
"asks": [
{
"specification": {
"direction": "sell",
"quantity": {
"currency": "USD",
"value": "0.71085738",
"counterparty": "rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B"
},
"totalPrice": {
"currency": "BTC",
"value": "0.00016876265",
"counterparty": "rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B"
}
},
"properties": {
"maker": "rUKoQ1Zhn6c8EfPsaVa2Yx5NqaKN1JQSvq",
"sequence": 262664,
"makerExchangeRate": "0.0002374071856720401"
},
"data": {
"Account": "rUKoQ1Zhn6c8EfPsaVa2Yx5NqaKN1JQSvq",
"BookDirectory": "20294C923E80A51B487EB9547B3835FD483748B170D2D0A451086F34ADB0EA11",
"BookNode": "0000000000000000",
"Flags": 0,
"LedgerEntryType": "Offer",
"OwnerNode": "000000000000001D",
"PreviousTxnID": "54CE0B2783AF973718FAFA35E864A3C172BE488EBBB6F2852611C6DAC8893BDF",
"PreviousTxnLgrSeq": 43127875,
"Sequence": 262664,
"TakerGets": {
"currency": "USD",
"issuer": "rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B",
"value": "0.71085738"
},
"TakerPays": {
"currency": "BTC",
"issuer": "rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B",
"value": "0.00016876265"
},
"index": "2D4ED103D6B3FEFA21BC385C53B63359F5678E5AA5429DDE6E1D8FE8B41CD6A8",
"owner_funds": "142.8821425048244",
"quality": "0.0002374071856720401"
}
},
{
"specification": {
"direction": "sell",
"quantity": {
"currency": "USD",
"value": "1.6438778",
"counterparty": "rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B"
},
"totalPrice": {
"currency": "BTC",
"value": "0.00039462656",
"counterparty": "rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B"
}
},
"properties": {
"maker": "rpmL45YbZWKgp8AH8EjBSknWo5c8dNuuBM",
"sequence": 231483,
"makerExchangeRate": "0.0002400583303698121"
},
"data": {
"Account": "rpmL45YbZWKgp8AH8EjBSknWo5c8dNuuBM",
"BookDirectory": "20294C923E80A51B487EB9547B3835FD483748B170D2D0A4510887515B1216C9",
"BookNode": "0000000000000000",
"Flags": 0,
"LedgerEntryType": "Offer",
"OwnerNode": "0000000000000001",
"PreviousTxnID": "6FA370F52C45F6149482156FF7B4226713AECE991FB7D053F74172CB0B8F24E9",
"PreviousTxnLgrSeq": 43127158,
"Sequence": 231483,
"TakerGets": {
"currency": "USD",
"issuer": "rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B",
"value": "1.6438778"
},
"TakerPays": {
"currency": "BTC",
"issuer": "rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B",
"value": "0.00039462656"
},
"index": "735F9661AD006BA0776859BE371D445555FC0815604603AC056469C16AC84AE3",
"owner_funds": "166.0316626329364",
"quality": "0.0002400583303698121"
}
},
// ... trimmed for brevity ...
]
}
```
# API Methods
## connect
@@ -2442,6 +2765,10 @@ return api.getOrders(address).then(orders =>
Returns open orders for the specified account. Open orders are orders that have not yet been fully executed and are still in the order book.
**Breaking change:** In ripple-lib 1.1.0 and earlier, orders returned by this method were not sorted correctly. Orders are now sorted correctly, from best to worst.
**See also:** An alternative way to get orderbooks is with `request` and [`formatBidsAndAsks`](#formatbidsandasks).
### Parameters
Name | Type | Description
@@ -2484,9 +2811,7 @@ asks[] | object | An order in the order book.
*asks[].state.* fundedAmount | [amount](#amount) | How much of the amount the maker would have to pay that the maker currently holds.
*asks[].state.* priceOfFundedAmount | [amount](#amount) | How much the `fundedAmount` would convert to through the exchange rate of this order.
### Raw order data
(Requires ripple-lib 0.22.0 or higher.) The response includes a `data` property containing the raw order data. This may include `owner_funds`, `Flags`, and other fields.
**Raw order data:** The response includes a `data` property containing the raw order data. This may include `owner_funds`, `Flags`, and other fields.
For details, see the rippled method [book_offers](https://ripple.com/build/rippled-apis/#book-offers).

View File

@@ -0,0 +1,254 @@
## formatBidsAndAsks
`formatBidsAndAsks(orderbookInfo: {base: Issue, counter: Issue}, offers: BookOffer[]): orderbook`
Returns formatted bids and asks, which make up an orderbook.
This is a static method on the `RippleAPI` class.
### Parameters
This method takes two parameters.
1. An `OrderbookInfo` object: `{ base: Issue, counter: Issue }`.
2. An array of `BookOffer` objects.
### Return Value
This method returns an object with two properties: `bids` and `asks`, each of which is an array of bids (buy orders) or asks (sell orders), respectively. (Note: the structures of `bids` and `asks` are identical.)
Object structure:
<%- renderSchema('output/get-orderbook.json') %>
**Raw order data:** The response includes a `data` property containing the raw order data. This may include `owner_funds`, `Flags`, and other fields.
For details, see the rippled method [book_offers](https://ripple.com/build/rippled-apis/#book-offers).
### Example
```javascript
const orderbookInfo = {
"base": {
"currency": "USD",
"counterparty": "rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B"
},
"counter": {
"currency": "BTC",
"counterparty": "rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B"
}
};
const address = 'r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59';
return Promise.all(
[
this.api.request('book_offers', {
taker_gets: RippleAPI.renameCounterpartyToIssuer(orderbookInfo.base),
taker_pays: RippleAPI.renameCounterpartyToIssuer(orderbookInfo.counter),
ledger_index: 'validated',
limit: 20,
taker: address
}),
this.api.request('book_offers', {
taker_gets: RippleAPI.renameCounterpartyToIssuer(orderbookInfo.counter),
taker_pays: RippleAPI.renameCounterpartyToIssuer(orderbookInfo.base),
ledger_index: 'validated',
limit: 20,
taker: address
})
]
).then((directOfferResults, reverseOfferResults) => {
const directOffers = (directOfferResults ? directOfferResults : []).reduce((acc, res) => acc.concat(res.offers), [])
const reverseOffers = (reverseOfferResults ? reverseOfferResults : []).reduce((acc, res) => acc.concat(res.offers), [])
const orderbook = RippleAPI.formatBidsAndAsks(orderbookInfo, [...directOffers, ...reverseOffers]);
console.log(JSON.stringify(orderbook, null, 2));
});
```
```
{
"bids": [
{
"specification": {
"direction": "buy",
"quantity": {
"currency": "USD",
"value": "0.71800168",
"counterparty": "rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B"
},
"totalPrice": {
"currency": "BTC",
"value": "0.00016708342",
"counterparty": "rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B"
}
},
"properties": {
"maker": "rUKoQ1Zhn6c8EfPsaVa2Yx5NqaKN1JQSvq",
"sequence": 262660,
"makerExchangeRate": "4297.264683713081"
},
"data": {
"Account": "rUKoQ1Zhn6c8EfPsaVa2Yx5NqaKN1JQSvq",
"BookDirectory": "6EAB7C172DEFA430DBFAD120FDC373B5F5AF8B191649EC98580F4456E6FA8239",
"BookNode": "0000000000000000",
"Flags": 0,
"LedgerEntryType": "Offer",
"OwnerNode": "000000000000001D",
"PreviousTxnID": "16D75506C6317723FC03543130B5E0AAB13E8AD22514C1DB098BE05771C90447",
"PreviousTxnLgrSeq": 43127860,
"Sequence": 262660,
"TakerGets": {
"currency": "BTC",
"issuer": "rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B",
"value": "0.00016708342"
},
"TakerPays": {
"currency": "USD",
"issuer": "rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B",
"value": "0.71800168"
},
"index": "DE877FB94EF892A4BCC58DB8CDE063D97AB5133201905DE6C8650B5DEA19E11B",
"owner_funds": "0.03358376764081196",
"quality": "4297.264683713081"
}
},
{
"specification": {
"direction": "buy",
"quantity": {
"currency": "USD",
"value": "1.6770875",
"counterparty": "rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B"
},
"totalPrice": {
"currency": "BTC",
"value": "0.00038681218",
"counterparty": "rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B"
}
},
"properties": {
"maker": "rpmL45YbZWKgp8AH8EjBSknWo5c8dNuuBM",
"sequence": 231459,
"makerExchangeRate": "4335.663628792661"
},
"data": {
"Account": "rpmL45YbZWKgp8AH8EjBSknWo5c8dNuuBM",
"BookDirectory": "6EAB7C172DEFA430DBFAD120FDC373B5F5AF8B191649EC98580F67435A75B355",
"BookNode": "0000000000000000",
"Flags": 0,
"LedgerEntryType": "Offer",
"OwnerNode": "0000000000000001",
"PreviousTxnID": "F049EAFDDDA7B99970F77533743D95C9E12A16FE6C56215A0B09C32C4D23163F",
"PreviousTxnLgrSeq": 43127094,
"Sequence": 231459,
"TakerGets": {
"currency": "BTC",
"issuer": "rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B",
"value": "0.00038681218"
},
"TakerPays": {
"currency": "USD",
"issuer": "rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B",
"value": "1.6770875"
},
"index": "3B314A51BD57601CA1509834DF9462037BF4B05AFCC1E1EFD334DB4E2D7B2AA6",
"owner_funds": "0.03906802968738533",
"quality": "4335.663628792661"
}
},
// ... trimmed for brevity ...
],
"asks": [
{
"specification": {
"direction": "sell",
"quantity": {
"currency": "USD",
"value": "0.71085738",
"counterparty": "rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B"
},
"totalPrice": {
"currency": "BTC",
"value": "0.00016876265",
"counterparty": "rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B"
}
},
"properties": {
"maker": "rUKoQ1Zhn6c8EfPsaVa2Yx5NqaKN1JQSvq",
"sequence": 262664,
"makerExchangeRate": "0.0002374071856720401"
},
"data": {
"Account": "rUKoQ1Zhn6c8EfPsaVa2Yx5NqaKN1JQSvq",
"BookDirectory": "20294C923E80A51B487EB9547B3835FD483748B170D2D0A451086F34ADB0EA11",
"BookNode": "0000000000000000",
"Flags": 0,
"LedgerEntryType": "Offer",
"OwnerNode": "000000000000001D",
"PreviousTxnID": "54CE0B2783AF973718FAFA35E864A3C172BE488EBBB6F2852611C6DAC8893BDF",
"PreviousTxnLgrSeq": 43127875,
"Sequence": 262664,
"TakerGets": {
"currency": "USD",
"issuer": "rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B",
"value": "0.71085738"
},
"TakerPays": {
"currency": "BTC",
"issuer": "rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B",
"value": "0.00016876265"
},
"index": "2D4ED103D6B3FEFA21BC385C53B63359F5678E5AA5429DDE6E1D8FE8B41CD6A8",
"owner_funds": "142.8821425048244",
"quality": "0.0002374071856720401"
}
},
{
"specification": {
"direction": "sell",
"quantity": {
"currency": "USD",
"value": "1.6438778",
"counterparty": "rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B"
},
"totalPrice": {
"currency": "BTC",
"value": "0.00039462656",
"counterparty": "rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B"
}
},
"properties": {
"maker": "rpmL45YbZWKgp8AH8EjBSknWo5c8dNuuBM",
"sequence": 231483,
"makerExchangeRate": "0.0002400583303698121"
},
"data": {
"Account": "rpmL45YbZWKgp8AH8EjBSknWo5c8dNuuBM",
"BookDirectory": "20294C923E80A51B487EB9547B3835FD483748B170D2D0A4510887515B1216C9",
"BookNode": "0000000000000000",
"Flags": 0,
"LedgerEntryType": "Offer",
"OwnerNode": "0000000000000001",
"PreviousTxnID": "6FA370F52C45F6149482156FF7B4226713AECE991FB7D053F74172CB0B8F24E9",
"PreviousTxnLgrSeq": 43127158,
"Sequence": 231483,
"TakerGets": {
"currency": "USD",
"issuer": "rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B",
"value": "1.6438778"
},
"TakerPays": {
"currency": "BTC",
"issuer": "rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B",
"value": "0.00039462656"
},
"index": "735F9661AD006BA0776859BE371D445555FC0815604603AC056469C16AC84AE3",
"owner_funds": "166.0316626329364",
"quality": "0.0002400583303698121"
}
},
// ... trimmed for brevity ...
]
}
```

View File

@@ -4,6 +4,10 @@
Returns open orders for the specified account. Open orders are orders that have not yet been fully executed and are still in the order book.
**Breaking change:** In ripple-lib 1.1.0 and earlier, orders returned by this method were not sorted correctly. Orders are now sorted correctly, from best to worst.
**See also:** An alternative way to get orderbooks is with `request` and [`formatBidsAndAsks`](#formatbidsandasks).
### Parameters
<%- renderSchema('input/get-orderbook.json') %>
@@ -14,9 +18,7 @@ This method returns a promise that resolves with an object with the following st
<%- renderSchema('output/get-orderbook.json') %>
### Raw order data
(Requires ripple-lib 0.22.0 or higher.) The response includes a `data` property containing the raw order data. This may include `owner_funds`, `Flags`, and other fields.
**Raw order data:** The response includes a `data` property containing the raw order data. This may include `owner_funds`, `Flags`, and other fields.
For details, see the rippled method [book_offers](https://ripple.com/build/rippled-apis/#book-offers).

View File

@@ -8,6 +8,11 @@
<% 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 methods.md.ejs %>
<% include connect.md.ejs %>
<% include disconnect.md.ejs %>

View File

@@ -0,0 +1,37 @@
## renameCounterpartyToIssuer
`renameCounterpartyToIssuer(issue: {currency: string, counterparty: address}): {currency: string, issuer: address}`
Returns an object with the `counterparty` field renamed to `issuer`. This is useful because RippleAPI generally uses the name `counterparty` while the rippled API generally uses the name `issuer`.
This is a static method on the `RippleAPI` class.
### Parameters
This method takes one parameter, an object with a `counterparty` field.
### Return Value
This method returns a new object similar to the source object, but with `issuer` instead of `counterparty`.
### Example
```javascript
const orderbookInfo = {
"base": {
"currency": "USD",
"counterparty": "rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B"
},
"counter": {
"currency": "BTC",
"counterparty": "rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B"
}
};
console.log(RippleAPI.renameCounterpartyToIssuer(orderbookInfo.base))
console.log(RippleAPI.renameCounterpartyToIssuer(orderbookInfo.counter))
```
```
{ currency: 'USD', issuer: 'rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B' }
{ currency: 'BTC', issuer: 'rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B' }
```

View File

@@ -0,0 +1 @@
# Static Methods

View File

@@ -1,6 +1,6 @@
{
"name": "ripple-lib",
"version": "1.1.0",
"version": "1.1.1",
"license": "ISC",
"description": "A JavaScript API for interacting with Ripple in Node.js and the browser",
"files": [

View File

@@ -22,7 +22,8 @@ import getBalances from './ledger/balances'
import getBalanceSheet from './ledger/balance-sheet'
import getPaths from './ledger/pathfind'
import getOrders from './ledger/orders'
import getOrderbook 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'
@@ -69,7 +70,7 @@ import * as ledgerUtils from './ledger/utils'
import * as transactionUtils from './transaction/utils'
import * as schemaValidator from './common/schema-validator'
import {getServerInfo, getFee} from './common/serverinfo'
import {clamp} from './ledger/utils'
import {clamp, renameCounterpartyToIssuer} from './ledger/utils'
import {Instructions, Prepare} from './transaction/types'
export type APIOptions = {
@@ -114,6 +115,9 @@ class RippleAPI extends EventEmitter {
schemaValidator
}
static renameCounterpartyToIssuer = renameCounterpartyToIssuer
static formatBidsAndAsks = formatBidsAndAsks
constructor(options: APIOptions = {}) {
super()
validate.apiOptions(options)
@@ -295,8 +299,8 @@ class RippleAPI extends EventEmitter {
getBalances = getBalances
getBalanceSheet = getBalanceSheet
getPaths = getPaths
getOrders = getOrders
getOrderbook = getOrderbook
getOrders = getOrders
getSettings = getSettings
getAccountInfo = getAccountInfo
getAccountObjects = getAccountObjects

View File

@@ -1,16 +1,51 @@
import {txFlagIndices} from './txflags'
// Ordering from https://developers.ripple.com/accountroot.html
const accountRootFlags = {
PasswordSpent: 0x00010000, // password set fee is spent
RequireDestTag: 0x00020000, // require a DestinationTag for payments
RequireAuth: 0x00040000, // require authorization to hold IOUs
DepositAuth: 0x01000000, // require account to auth deposits
DisallowXRP: 0x00080000, // disallow sending XRP
DisableMaster: 0x00100000, // force regular key
NoFreeze: 0x00200000, // permanently disallowed freezing trustlines
GlobalFreeze: 0x00400000, // trustlines globally frozen
DefaultRipple: 0x00800000
// lsfDefaultRipple:
// Enable rippling on trust lines by default.
// Required for issuing addresses; discouraged for others.
DefaultRipple: 0x00800000,
// lsfDepositAuth:
// Require account to auth deposits.
// This account can only receive funds from transactions it sends,
// or preauthorized accounts.
DepositAuth: 0x01000000,
// lsfDisableMaster:
// Force regular key.
// Disallows use of the master key.
DisableMaster: 0x00100000,
// lsfDisallowXRP:
// Disallow sending XRP.
// Not enforced by rippled; client applications should check.
DisallowXRP: 0x00080000,
// lsfGlobalFreeze:
// Trustlines globally frozen.
GlobalFreeze: 0x00400000,
// lsfNoFreeze:
// Permanently disallowed freezing trustlines.
// Once enabled, cannot be disabled.
NoFreeze: 0x00200000,
// lsfPasswordSpent:
// Password set fee is spent.
// The account has used its free SetRegularKey transaction.
PasswordSpent: 0x00010000,
// lsfRequireAuth:
// Require authorization to hold IOUs (issuances).
RequireAuth: 0x00040000,
// lsfRequireDestTag:
// Require a DestinationTag for incoming payments.
RequireDestTag: 0x00020000
}
const AccountFlags = {

View File

@@ -8,6 +8,7 @@ import {validate} from '../common'
import {Amount, Issue} from '../common/types/objects'
import {BookOffer} from '../common/types/commands'
import {RippleAPI} from '../api'
import BigNumber from 'bignumber.js'
export type FormattedOrderbook = {
bids: FormattedOrderbookOrder[],
@@ -38,7 +39,7 @@ function alignOrder(base: Amount, order: FormattedOrderbookOrder) {
return isSameIssue(quantity, base) ? order : flipOrder(order)
}
function formatBidsAndAsks(
export function formatBidsAndAsks(
orderbook: OrderbookInfo, offers: BookOffer[]) {
// the "base" currency is the currency that you are buying or selling
// the "counter" is the currency that the "base" is priced in
@@ -50,7 +51,10 @@ function formatBidsAndAsks(
// for asks: lowest quality => lowest totalPrice/quantity => lowest price
// for both bids and asks, lowest quality is closest to mid-market
// we sort the orders so that earlier orders are closer to mid-market
const orders = _.sortBy(offers, 'quality').map(parseOrderbookOrder)
const orders = offers.sort((a, b) => {
return (new BigNumber(a.quality)).comparedTo(b.quality)
}).map(parseOrderbookOrder)
const alignedOrders = orders.map(_.partial(alignOrder, orderbook.base))
const bids = alignedOrders.filter(_.partial(directionFilter, 'buy'))
const asks = alignedOrders.filter(_.partial(directionFilter, 'sell'))
@@ -87,7 +91,7 @@ export type OrderbookInfo = {
counter: Issue
}
export default async function getOrderbook(
export async function getOrderbook(
this: RippleAPI,
address: string,
orderbook: OrderbookInfo,
@@ -105,5 +109,6 @@ export default async function getOrderbook(
directOfferResult => directOfferResult.offers)
const reverseOffers = _.flatMap(reverseOfferResults,
reverseOfferResult => reverseOfferResult.offers)
return formatBidsAndAsks(orderbook, [...directOffers, ...reverseOffers])
return formatBidsAndAsks(orderbook,
[...directOffers, ...reverseOffers])
}

View File

@@ -2,17 +2,18 @@ import keypairs = require('ripple-keypairs')
import * as common from '../common'
const {errors, validate} = common
function generateAddress(options?: object): object {
const secret = keypairs.generateSeed(options)
const keypair = keypairs.deriveKeypair(secret)
const address = keypairs.deriveAddress(keypair.publicKey)
return {secret, address}
export type GeneratedAddress = {
secret: string,
address: string
}
function generateAddressAPI(options?: object): object {
function generateAddressAPI(options?: any): GeneratedAddress {
validate.generateAddress({options})
try {
return generateAddress(options)
const secret = keypairs.generateSeed(options)
const keypair = keypairs.deriveKeypair(secret)
const address = keypairs.deriveAddress(keypair.publicKey)
return {secret, address}
} catch (error) {
throw new errors.UnexpectedError(error.message)
}

View File

@@ -2272,6 +2272,315 @@ describe('RippleAPI', function () {
});
});
describe('formatBidsAndAsks', function () {
it('normal', function () {
const orderbookInfo = {
"base": {
"currency": "USD",
"counterparty": "rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B"
},
"counter": {
"currency": "BTC",
"counterparty": "rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B"
}
};
return Promise.all(
[
this.api.request('book_offers', {
taker_gets: RippleAPI.renameCounterpartyToIssuer(orderbookInfo.base),
taker_pays: RippleAPI.renameCounterpartyToIssuer(orderbookInfo.counter),
ledger_index: 'validated',
limit: 20,
taker: address
}),
this.api.request('book_offers', {
taker_gets: RippleAPI.renameCounterpartyToIssuer(orderbookInfo.counter),
taker_pays: RippleAPI.renameCounterpartyToIssuer(orderbookInfo.base),
ledger_index: 'validated',
limit: 20,
taker: address
})
]
).then((directOfferResults, reverseOfferResults) => {
const directOffers = (directOfferResults ? directOfferResults : []).reduce((acc, res) => acc.concat(res.offers), [])
const reverseOffers = (reverseOfferResults ? reverseOfferResults : []).reduce((acc, res) => acc.concat(res.offers), [])
const orderbook = RippleAPI.formatBidsAndAsks(orderbookInfo, [...directOffers, ...reverseOffers]);
assert.deepEqual(orderbook, responses.getOrderbook.normal);
});
});
it('with XRP', function () {
const orderbookInfo = {
"base": {
"currency": "USD",
"counterparty": "rp8rJYTpodf8qbSCHVTNacf8nSW8mRakFw"
},
"counter": {
"currency": "XRP"
}
};
return Promise.all(
[
this.api.request('book_offers', {
taker_gets: RippleAPI.renameCounterpartyToIssuer(orderbookInfo.base),
taker_pays: RippleAPI.renameCounterpartyToIssuer(orderbookInfo.counter),
ledger_index: 'validated',
limit: 20,
taker: address
}),
this.api.request('book_offers', {
taker_gets: RippleAPI.renameCounterpartyToIssuer(orderbookInfo.counter),
taker_pays: RippleAPI.renameCounterpartyToIssuer(orderbookInfo.base),
ledger_index: 'validated',
limit: 20,
taker: address
})
]
).then((directOfferResults, reverseOfferResults) => {
const directOffers = (directOfferResults ? directOfferResults : []).reduce((acc, res) => acc.concat(res.offers), [])
const reverseOffers = (reverseOfferResults ? reverseOfferResults : []).reduce((acc, res) => acc.concat(res.offers), [])
const orderbook = RippleAPI.formatBidsAndAsks(orderbookInfo, [...directOffers, ...reverseOffers]);
assert.deepEqual(orderbook, responses.getOrderbook.withXRP);
});
});
function checkSortingOfOrders(orders) {
let previousRate = '0';
for (var i = 0; i < orders.length; i++) {
const order = orders[i];
let rate;
// We calculate the quality of output/input here as a test.
// This won't hold in general because when output and input amounts get tiny,
// the quality can differ significantly. However, the offer stays in the
// order book where it was originally placed. It would be more consistent
// to check the quality from the offer book, but for the test data set,
// this calculation holds.
if (order.specification.direction === 'buy') {
rate = (new BigNumber(order.specification.quantity.value))
.dividedBy(order.specification.totalPrice.value)
.toString();
} else {
rate = (new BigNumber(order.specification.totalPrice.value))
.dividedBy(order.specification.quantity.value)
.toString();
}
assert((new BigNumber(rate)).greaterThanOrEqualTo(previousRate),
'Rates must be sorted from least to greatest: ' +
rate + ' should be >= ' + previousRate);
previousRate = rate;
}
return true;
}
it('sample XRP/JPY book has orders sorted correctly', function () {
const orderbookInfo = {
"base": { // the first currency in pair
"currency": 'XRP'
},
"counter": {
"currency": 'JPY',
"counterparty": "rB3gZey7VWHYRqJHLoHDEJXJ2pEPNieKiS"
}
};
const myAddress = 'rE9qNjzJXpiUbVomdv7R4xhrXVeH2oVmGR';
return Promise.all(
[
this.api.request('book_offers', {
taker_gets: RippleAPI.renameCounterpartyToIssuer(orderbookInfo.base),
taker_pays: RippleAPI.renameCounterpartyToIssuer(orderbookInfo.counter),
ledger_index: 'validated',
limit: 400, // must match `test/fixtures/rippled/requests/1-taker_gets-XRP-taker_pays-JPY.json`
taker: myAddress
}),
this.api.request('book_offers', {
taker_gets: RippleAPI.renameCounterpartyToIssuer(orderbookInfo.counter),
taker_pays: RippleAPI.renameCounterpartyToIssuer(orderbookInfo.base),
ledger_index: 'validated',
limit: 400, // must match `test/fixtures/rippled/requests/2-taker_gets-JPY-taker_pays-XRP.json`
taker: myAddress
})
]
).then((directOfferResults, reverseOfferResults) => {
const directOffers = (directOfferResults ? directOfferResults : []).reduce((acc, res) => acc.concat(res.offers), [])
const reverseOffers = (reverseOfferResults ? reverseOfferResults : []).reduce((acc, res) => acc.concat(res.offers), [])
const orderbook = RippleAPI.formatBidsAndAsks(orderbookInfo, [...directOffers, ...reverseOffers]);
assert.deepStrictEqual([], orderbook.bids);
return checkSortingOfOrders(orderbook.asks);
});
});
it('sample USD/XRP book has orders sorted correctly', function () {
const orderbookInfo = { counter: { currency: 'XRP' },
base: { currency: 'USD',
counterparty: 'rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B' } };
const myAddress = 'rE9qNjzJXpiUbVomdv7R4xhrXVeH2oVmGR';
return Promise.all(
[
this.api.request('book_offers', {
taker_gets: RippleAPI.renameCounterpartyToIssuer(orderbookInfo.base),
taker_pays: RippleAPI.renameCounterpartyToIssuer(orderbookInfo.counter),
ledger_index: 'validated',
limit: 400, // must match `test/fixtures/rippled/requests/1-taker_gets-XRP-taker_pays-JPY.json`
taker: myAddress
}),
this.api.request('book_offers', {
taker_gets: RippleAPI.renameCounterpartyToIssuer(orderbookInfo.counter),
taker_pays: RippleAPI.renameCounterpartyToIssuer(orderbookInfo.base),
ledger_index: 'validated',
limit: 400, // must match `test/fixtures/rippled/requests/2-taker_gets-JPY-taker_pays-XRP.json`
taker: myAddress
})
]
).then((directOfferResults, reverseOfferResults) => {
const directOffers = (directOfferResults ? directOfferResults : []).reduce((acc, res) => acc.concat(res.offers), [])
const reverseOffers = (reverseOfferResults ? reverseOfferResults : []).reduce((acc, res) => acc.concat(res.offers), [])
const orderbook = RippleAPI.formatBidsAndAsks(orderbookInfo, [...directOffers, ...reverseOffers]);
return checkSortingOfOrders(orderbook.bids) && checkSortingOfOrders(orderbook.asks);
});
});
it('sorted so that best deals come first', function () {
const orderbookInfo = {
"base": {
"currency": "USD",
"counterparty": "rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B"
},
"counter": {
"currency": "BTC",
"counterparty": "rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B"
}
};
return Promise.all(
[
this.api.request('book_offers', {
taker_gets: RippleAPI.renameCounterpartyToIssuer(orderbookInfo.base),
taker_pays: RippleAPI.renameCounterpartyToIssuer(orderbookInfo.counter),
ledger_index: 'validated',
limit: 20,
taker: address
}),
this.api.request('book_offers', {
taker_gets: RippleAPI.renameCounterpartyToIssuer(orderbookInfo.counter),
taker_pays: RippleAPI.renameCounterpartyToIssuer(orderbookInfo.base),
ledger_index: 'validated',
limit: 20,
taker: address
})
]
).then((directOfferResults, reverseOfferResults) => {
const directOffers = (directOfferResults ? directOfferResults : []).reduce((acc, res) => acc.concat(res.offers), [])
const reverseOffers = (reverseOfferResults ? reverseOfferResults : []).reduce((acc, res) => acc.concat(res.offers), [])
const orderbook = RippleAPI.formatBidsAndAsks(orderbookInfo, [...directOffers, ...reverseOffers]);
const bidRates = orderbook.bids.map(bid => bid.properties.makerExchangeRate);
const askRates = orderbook.asks.map(ask => ask.properties.makerExchangeRate);
// makerExchangeRate = quality = takerPays.value/takerGets.value
// so the best deal for the taker is the lowest makerExchangeRate
// bids and asks should be sorted so that the best deals come first
assert.deepEqual(_.sortBy(bidRates, x => Number(x)), bidRates);
assert.deepEqual(_.sortBy(askRates, x => Number(x)), askRates);
});
});
it('currency & counterparty are correct', function () {
const orderbookInfo = {
"base": {
"currency": "USD",
"counterparty": "rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B"
},
"counter": {
"currency": "BTC",
"counterparty": "rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B"
}
};
return Promise.all(
[
this.api.request('book_offers', {
taker_gets: RippleAPI.renameCounterpartyToIssuer(orderbookInfo.base),
taker_pays: RippleAPI.renameCounterpartyToIssuer(orderbookInfo.counter),
ledger_index: 'validated',
limit: 20,
taker: address
}),
this.api.request('book_offers', {
taker_gets: RippleAPI.renameCounterpartyToIssuer(orderbookInfo.counter),
taker_pays: RippleAPI.renameCounterpartyToIssuer(orderbookInfo.base),
ledger_index: 'validated',
limit: 20,
taker: address
})
]
).then((directOfferResults, reverseOfferResults) => {
const directOffers = (directOfferResults ? directOfferResults : []).reduce((acc, res) => acc.concat(res.offers), [])
const reverseOffers = (reverseOfferResults ? reverseOfferResults : []).reduce((acc, res) => acc.concat(res.offers), [])
const orderbook = RippleAPI.formatBidsAndAsks(orderbookInfo, [...directOffers, ...reverseOffers]);
const orders = _.flatten([orderbook.bids, orderbook.asks]);
_.forEach(orders, order => {
const quantity = order.specification.quantity;
const totalPrice = order.specification.totalPrice;
const { base, counter } = requests.getOrderbook.normal;
assert.strictEqual(quantity.currency, base.currency);
assert.strictEqual(quantity.counterparty, base.counterparty);
assert.strictEqual(totalPrice.currency, counter.currency);
assert.strictEqual(totalPrice.counterparty, counter.counterparty);
});
});
});
it('direction is correct for bids and asks', function () {
const orderbookInfo = {
"base": {
"currency": "USD",
"counterparty": "rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B"
},
"counter": {
"currency": "BTC",
"counterparty": "rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B"
}
};
return Promise.all(
[
this.api.request('book_offers', {
taker_gets: RippleAPI.renameCounterpartyToIssuer(orderbookInfo.base),
taker_pays: RippleAPI.renameCounterpartyToIssuer(orderbookInfo.counter),
ledger_index: 'validated',
limit: 20,
taker: address
}),
this.api.request('book_offers', {
taker_gets: RippleAPI.renameCounterpartyToIssuer(orderbookInfo.counter),
taker_pays: RippleAPI.renameCounterpartyToIssuer(orderbookInfo.base),
ledger_index: 'validated',
limit: 20,
taker: address
})
]
).then((directOfferResults, reverseOfferResults) => {
const directOffers = (directOfferResults ? directOfferResults : []).reduce((acc, res) => acc.concat(res.offers), [])
const reverseOffers = (reverseOfferResults ? reverseOfferResults : []).reduce((acc, res) => acc.concat(res.offers), [])
const orderbook = RippleAPI.formatBidsAndAsks(orderbookInfo, [...directOffers, ...reverseOffers]);
assert(
_.every(orderbook.bids, bid => bid.specification.direction === 'buy'));
assert(
_.every(orderbook.asks, ask => ask.specification.direction === 'sell'));
});
});
});
describe('getOrderbook', function () {
it('normal', function () {
@@ -2296,7 +2605,69 @@ describe('RippleAPI', function () {
_.partial(checkResult, responses.getOrderbook.withXRP, 'getOrderbook'));
});
it('sorted so that best deals come first', function () {
function checkSortingOfOrders(orders) {
let previousRate = '0';
for (var i = 0; i < orders.length; i++) {
const order = orders[i];
let rate;
// We calculate the quality of output/input here as a test.
// This won't hold in general because when output and input amounts get tiny,
// the quality can differ significantly. However, the offer stays in the
// order book where it was originally placed. It would be more consistent
// to check the quality from the offer book, but for the test data set,
// this calculation holds.
if (order.specification.direction === 'buy') {
rate = (new BigNumber(order.specification.quantity.value))
.dividedBy(order.specification.totalPrice.value)
.toString();
} else {
rate = (new BigNumber(order.specification.totalPrice.value))
.dividedBy(order.specification.quantity.value)
.toString();
}
assert((new BigNumber(rate)).greaterThanOrEqualTo(previousRate),
'Rates must be sorted from least to greatest: ' +
rate + ' should be >= ' + previousRate);
previousRate = rate;
}
return true;
}
it('sample XRP/JPY book has orders sorted correctly', function () {
const orderbookInfo = {
"base": { // the first currency in pair
"currency": 'XRP'
},
"counter": {
"currency": 'JPY',
"counterparty": "rB3gZey7VWHYRqJHLoHDEJXJ2pEPNieKiS"
}
};
const myAddress = 'rE9qNjzJXpiUbVomdv7R4xhrXVeH2oVmGR';
return this.api.getOrderbook(myAddress, orderbookInfo).then(orderbook => {
assert.deepStrictEqual([], orderbook.bids);
return checkSortingOfOrders(orderbook.asks);
});
});
it('sample USD/XRP book has orders sorted correctly', function () {
const orderbookInfo = { counter: { currency: 'XRP' },
base: { currency: 'USD',
counterparty: 'rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B' } };
const myAddress = 'rE9qNjzJXpiUbVomdv7R4xhrXVeH2oVmGR';
return this.api.getOrderbook(myAddress, orderbookInfo).then(orderbook => {
return checkSortingOfOrders(orderbook.bids) && checkSortingOfOrders(orderbook.asks);
});
});
// WARNING: This test fails to catch the sorting bug, issue #766
it('sorted so that best deals come first [bad test]', function () {
return this.api.getOrderbook(address, requests.getOrderbook.normal)
.then(data => {
const bidRates = data.bids.map(bid => bid.properties.makerExchangeRate);

View File

@@ -2,470 +2,11 @@
'use strict'
const _ = require('lodash')
module.exports.requestBookOffersBidsResponse = function(request, options = {}) {
_.defaults(options, {
gets: {
currency: 'USD',
issuer: 'rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B'
},
pays: {
currency: 'BTC',
issuer: 'rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B'
}
})
return JSON.stringify({
id: request.id,
result: {
ledger_index: 10716345,
offers: [
{
Account: 'r49y2xKuKVG2dPkNHgWQAV61cjxk8gryjQ',
BookDirectory:
'20294C923E80A51B487EB9547B3835FD483748B170D2D0A4520B15A60037FFCF',
BookNode: '0000000000000000',
Flags: 0,
LedgerEntryType: 'Offer',
OwnerNode: '0000000000000000',
PreviousTxnID:
'544932DC56D72E845AF2B738821FE07865E32EC196270678AB0D947F54E9F49F',
PreviousTxnLgrSeq: 10679000,
Sequence: 434,
TakerGets: {
currency: options.gets.currency,
issuer: options.gets.issuer,
value: '3205.1'
},
TakerPays: {
currency: options.pays.currency,
issuer: options.pays.issuer,
value: '10'
},
index:
'CE457115A4ADCC8CB351B3E35A0851E48DE16605C23E305017A9B697B156DE5A',
owner_funds: '41952.95917199965',
quality: '0.003120027456241615'
},
{
Account: 'rDYCRhpahKEhCFV25xScg67Bwf4W9sTYAm',
BookDirectory:
'20294C923E80A51B487EB9547B3835FD483748B170D2D0A4520B1A2BC2EC5000',
BookNode: '0000000000000000',
Flags: 0,
LedgerEntryType: 'Offer',
OwnerNode: '0000000000000000',
PreviousTxnID:
'F68F9658AB3D462FEB027E6C380F054BC6D2514B43EC3C6AD46EE19C59BF1CC3',
PreviousTxnLgrSeq: 10704238,
Sequence: 233,
TakerGets: {
currency: options.gets.currency,
issuer: options.gets.issuer,
value: '1599.063669386278'
},
TakerPays: {
currency: options.pays.currency,
issuer: options.pays.issuer,
value: '4.99707396683212'
},
index:
'BF14FBB305159DBCAEA91B7E848408F5B559A91B160EBCB6D244958A6A16EA6B',
owner_funds: '3169.910902910102',
quality: '0.003125'
},
{
Account: 'raudnGKfTK23YKfnS7ixejHrqGERTYNFXk',
BookDirectory:
'20294C923E80A51B487EB9547B3835FD483748B170D2D0A4520B2BF1C2F4D4C9',
BookNode: '0000000000000000',
Expiration: 472785284,
Flags: 0,
LedgerEntryType: 'Offer',
OwnerNode: '00000000000008F0',
PreviousTxnID:
'446410E1CD718AC01929DD16B558FCF6B3A7B8BF208C420E67A280C089C5C59B',
PreviousTxnLgrSeq: 10713576,
Sequence: 110104,
TakerGets: {
currency: options.gets.currency,
issuer: options.gets.issuer,
value: '143.1050962074379'
},
TakerPays: {
currency: options.pays.currency,
issuer: options.pays.issuer,
value: '0.4499999999999999'
},
index:
'67924B0EAA15784CC00CCD5FDD655EE2D6D2AE40341776B5F14E52341E7FC73E',
owner_funds: '0',
quality: '0.003144542101755081',
taker_gets_funded: {
currency: options.gets.currency,
issuer: options.gets.issuer,
value: '0'
},
taker_pays_funded: {
currency: options.pays.currency,
issuer: options.pays.issuer,
value: '0'
}
},
{
Account: 'rDVBvAQScXrGRGnzrxRrcJPeNLeLeUTAqE',
BookDirectory:
'20294C923E80A51B487EB9547B3835FD483748B170D2D0A4520B2CD7A2BFBB75',
BookNode: '0000000000000000',
Expiration: 472772651,
Flags: 0,
LedgerEntryType: 'Offer',
OwnerNode: '00000000000003CD',
PreviousTxnID:
'D49164AB68DDA3AEC9DFCC69A35685C4F532B5C231D3C1D25FEA7D5D0224FB84',
PreviousTxnLgrSeq: 10711128,
Sequence: 35625,
TakerGets: {
currency: options.gets.currency,
issuer: options.gets.issuer,
value: '254.329207354604'
},
TakerPays: {
currency: options.pays.currency,
issuer: options.pays.issuer,
value: '0.8'
},
index:
'567BF2825173E3FB28FC94E436B6EB30D9A415FC2335E6D25CDE1BE47B25D120',
owner_funds: '0',
quality: '0.003145529403882357',
taker_gets_funded: {
currency: options.gets.currency,
issuer: options.gets.issuer,
value: '0'
},
taker_pays_funded: {
currency: options.pays.currency,
issuer: options.pays.issuer,
value: '0'
}
},
{
Account: 'rwBYyfufTzk77zUSKEu4MvixfarC35av1J',
BookDirectory:
'20294C923E80A51B487EB9547B3835FD483748B170D2D0A4520B3621DF140FDA',
BookNode: '0000000000000000',
Flags: 0,
LedgerEntryType: 'Offer',
OwnerNode: '0000000000000008',
PreviousTxnID:
'2E371E2B287C8A9FBB3424E4204B17AD9FA1BAA9F3B33C7D2261E3B038AFF083',
PreviousTxnLgrSeq: 10716291,
Sequence: 387756,
TakerGets: {
currency: options.gets.currency,
issuer: options.gets.issuer,
value: '390.4979'
},
TakerPays: {
currency: options.pays.currency,
issuer: options.pays.issuer,
value: '1.23231134568807'
},
index:
'8CA23E55BF9F46AC7E803D3DB40FD03225EFCA66650D4CF0CBDD28A7CCDC8400',
owner_funds: '5704.824764087842',
quality: '0.003155743848271834'
},
{
Account: 'rwjsRktX1eguUr1pHTffyHnC4uyrvX58V1',
BookDirectory:
'20294C923E80A51B487EB9547B3835FD483748B170D2D0A4520B3A4D41FF4211',
BookNode: '0000000000000000',
Flags: 0,
LedgerEntryType: 'Offer',
OwnerNode: '0000000000000000',
PreviousTxnID:
'91763FA7089C63CC4D5D14CBA6A5A5BF7ECE949B0D34F00FD35E733AF9F05AF1',
PreviousTxnLgrSeq: 10716292,
Sequence: 208927,
TakerGets: {
currency: options.gets.currency,
issuer: options.gets.issuer,
value: '1'
},
TakerPays: {
currency: options.pays.currency,
issuer: options.pays.issuer,
value: '0.003160328237957649'
},
index:
'7206866E39D9843623EE79E570242753DEE3C597F3856AEFB4631DD5AD8B0557',
owner_funds: '45.55665106096075',
quality: '0.003160328237957649'
},
{
Account: 'r49y2xKuKVG2dPkNHgWQAV61cjxk8gryjQ',
BookDirectory:
'20294C923E80A51B487EB9547B3835FD483748B170D2D0A4520B4748E68669A7',
BookNode: '0000000000000000',
Flags: 0,
LedgerEntryType: 'Offer',
OwnerNode: '0000000000000000',
PreviousTxnID:
'3B3CF6FF1A336335E78513CF77AFD3A784ACDD7B1B4D3F1F16E22957A060BFAE',
PreviousTxnLgrSeq: 10639969,
Sequence: 429,
TakerGets: {
currency: options.gets.currency,
issuer: options.gets.issuer,
value: '4725'
},
TakerPays: {
currency: options.pays.currency,
issuer: options.pays.issuer,
value: '15'
},
index:
'42894809370C7E6B23498EF8E22AD4B05F02B94F08E6983357A51EA96A95FF7F',
quality: '0.003174603174603175'
},
{
Account: 'rDbsCJr5m8gHDCNEHCZtFxcXHsD4S9jH83',
BookDirectory:
'20294C923E80A51B487EB9547B3835FD483748B170D2D0A4520B58077ED03C1B',
BookNode: '0000000000000000',
Flags: 131072,
LedgerEntryType: 'Offer',
OwnerNode: '0000000000000001',
PreviousTxnID:
'98F3F2D02D3BB0AEAC09EECCF2F24BBE5E1AB2C71C40D7BD0A5199E12541B6E2',
PreviousTxnLgrSeq: 10715839,
Sequence: 110099,
TakerGets: {
currency: options.gets.currency,
issuer: options.gets.issuer,
value: '1.24252537879871'
},
TakerPays: {
currency: options.pays.currency,
issuer: options.gets.issuer,
value: '0.003967400879423823'
},
index:
'F4404D6547149419D3607F81D7080979FBB3AFE2661F9A933E2F6C07AC1D1F6D',
owner_funds: '73.52163803897041',
quality: '0.003193013959408667'
},
{
Account: 'rDVBvAQScXrGRGnzrxRrcJPeNLeLeUTAqE',
BookDirectory:
'20294C923E80A51B487EB9547B3835FD483748B170D2D0A4520B72A555B981A3',
BookNode: '0000000000000000',
Expiration: 472772652,
Flags: 0,
LedgerEntryType: 'Offer',
OwnerNode: '00000000000003CD',
PreviousTxnID:
'146C8DBB047BAAFAE5B8C8DECCCDACD9DFCD7A464E5AB273230FF975E9B83CF7',
PreviousTxnLgrSeq: 10711128,
Sequence: 35627,
TakerGets: {
currency: options.gets.currency,
issuer: options.gets.issuer,
value: '496.5429474010489'
},
TakerPays: {
currency: options.pays.currency,
issuer: options.pays.issuer,
value: '1.6'
},
index:
'50CAA04E81D0009115B61C132FC9887FA9E5336E0CB8A2E7D3280ADBF6ABC043',
quality: '0.003222279177208227',
taker_gets_funded: {
currency: options.gets.currency,
issuer: options.gets.issuer,
value: '0'
},
taker_pays_funded: {
currency: options.pays.currency,
issuer: options.pays.issuer,
value: '0'
}
},
{
Account: 'r49y2xKuKVG2dPkNHgWQAV61cjxk8gryjQ',
BookDirectory:
'20294C923E80A51B487EB9547B3835FD483748B170D2D0A4520B730474DD96E5',
BookNode: '0000000000000000',
Flags: 0,
LedgerEntryType: 'Offer',
OwnerNode: '0000000000000000',
PreviousTxnID:
'624F9ADA85EC3BE845EAC075B47E01E4F89288EAF27823C715777B3DFFB21F24',
PreviousTxnLgrSeq: 10639989,
Sequence: 431,
TakerGets: {
currency: options.gets.currency,
issuer: options.gets.issuer,
value: '3103'
},
TakerPays: {
currency: options.pays.currency,
issuer: options.pays.issuer,
value: '10'
},
index:
'8A319A496288228AD9CAD74375E32FA81805C56A9AD84798A26756A8B3F9EE23',
quality: '0.003222687721559781'
}
],
validated: false
},
status: 'success',
type: 'response'
})
}
module.exports.requestBookOffersBidsPartialFundedResponse = function(
request,
options = {}
) {
_.defaults(options, {
gets: {
currency: 'BTC',
issuer: 'rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B'
},
pays: {
currency: 'USD',
issuer: 'rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B'
}
})
return JSON.stringify({
id: request.id,
status: 'success',
type: 'response',
result: {
ledger_current_index: 10714274,
offers: [
{
Account: 'rpUirQxhaFqMp7YHPLMZCWxgZQbaZkp4bM',
BookDirectory:
'20294C923E80A51B487EB9547B3835FD483748B170D2D0A4520B75DA97A99CE7',
BookNode: '0000000000000000',
Flags: 0,
LedgerEntryType: 'Offer',
OwnerNode: '0000000000000000',
PreviousTxnID:
'52801D1249261E410632BF6C00F503B1F51B31798C1E7DBD67B976FE65BE4DA4',
PreviousTxnLgrSeq: 10630313,
Sequence: 132,
TakerGets: {
currency: options.gets.currency,
issuer: options.gets.issuer,
value: '310'
},
TakerPays: {
currency: options.pays.currency,
issuer: options.pays.issuer,
value: '1'
},
index:
'861D15BECDA5DCA1327CF4D8080C181425F043AC969A992C5FAE5D12813785D0',
owner_funds: '259.7268806690133',
quality: '0.003225806451612903',
taker_gets_funded: {
currency: options.gets.currency,
issuer: options.gets.issuer,
value: '259.2084637415302'
},
taker_pays_funded: {
currency: options.pays.currency,
issuer: options.pays.issuer,
value: '0.8361563346500974'
}
}
]
}
})
}
module.exports.requestBookOffersAsksPartialFundedResponse = function(
request,
options = {}
) {
_.defaults(options, {
gets: {
currency: 'BTC',
issuer: 'rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B'
},
pays: {
currency: 'USD',
issuer: 'rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B'
}
})
return JSON.stringify({
id: request.id,
status: 'success',
type: 'response',
result: {
ledger_current_index: 10714274,
offers: [
{
Account: 'rPyYxUGK8L4dgEvjPs3aRc1B1jEiLr3Hx5',
BookDirectory:
'6EAB7C172DEFA430DBFAD120FDC373B5F5AF8B191649EC98570BCB85BCA78000',
BookNode: '0000000000000000',
Flags: 131072,
LedgerEntryType: 'Offer',
OwnerNode: '0000000000000000',
PreviousTxnID:
'D22993C68C94ACE3F2FCE4A334EBEA98CC46DCA92886C12B5E5B4780B5E17D4E',
PreviousTxnLgrSeq: 10711938,
Sequence: 392,
TakerGets: {
currency: options.gets.currency,
issuer: options.gets.issuer,
value: '0.8095'
},
TakerPays: {
currency: options.pays.currency,
issuer: options.pays.issuer,
value: '268.754'
},
index:
'18B136E08EF50F0DEE8521EA22D16A950CD8B6DDF5F6E07C35F7FDDBBB09718D',
owner_funds: '0.8095132334507441',
quality: '332',
taker_gets_funded: {
currency: options.gets.currency,
issuer: options.gets.issuer,
value: '0.8078974385735969'
},
taker_pays_funded: {
currency: options.pays.currency,
issuer: options.pays.issuer,
value: '268.2219496064341'
}
}
]
}
})
}
module.exports.requestBookOffersAsksResponse = function(request, options = {}) {
_.defaults(options, {
pays: {
currency: 'USD',
issuer: 'rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B'
},
gets: {
currency: 'BTC',
issuer: 'rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B'
}
})
module.exports.requestBookOffersBidsResponse = function(request) {
const options = {
gets: request.taker_gets,
pays: request.taker_pays
}
return JSON.stringify({
id: request.id,
@@ -782,6 +323,453 @@ module.exports.requestBookOffersAsksResponse = function(request, options = {}) {
})
}
module.exports.requestBookOffersBidsPartialFundedResponse = function(
request,
options = {}
) {
_.defaults(options, {
gets: {
currency: 'BTC',
issuer: 'rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B'
},
pays: {
currency: 'USD',
issuer: 'rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B'
}
})
return JSON.stringify({
id: request.id,
status: 'success',
type: 'response',
result: {
ledger_current_index: 10714274,
offers: [
{
Account: 'rpUirQxhaFqMp7YHPLMZCWxgZQbaZkp4bM',
BookDirectory:
'20294C923E80A51B487EB9547B3835FD483748B170D2D0A4520B75DA97A99CE7',
BookNode: '0000000000000000',
Flags: 0,
LedgerEntryType: 'Offer',
OwnerNode: '0000000000000000',
PreviousTxnID:
'52801D1249261E410632BF6C00F503B1F51B31798C1E7DBD67B976FE65BE4DA4',
PreviousTxnLgrSeq: 10630313,
Sequence: 132,
TakerGets: {
currency: options.gets.currency,
issuer: options.gets.issuer,
value: '310'
},
TakerPays: {
currency: options.pays.currency,
issuer: options.pays.issuer,
value: '1'
},
index:
'861D15BECDA5DCA1327CF4D8080C181425F043AC969A992C5FAE5D12813785D0',
owner_funds: '259.7268806690133',
quality: '0.003225806451612903',
taker_gets_funded: {
currency: options.gets.currency,
issuer: options.gets.issuer,
value: '259.2084637415302'
},
taker_pays_funded: {
currency: options.pays.currency,
issuer: options.pays.issuer,
value: '0.8361563346500974'
}
}
]
}
})
}
module.exports.requestBookOffersAsksPartialFundedResponse = function(
request,
options = {}
) {
_.defaults(options, {
gets: {
currency: 'BTC',
issuer: 'rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B'
},
pays: {
currency: 'USD',
issuer: 'rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B'
}
})
return JSON.stringify({
id: request.id,
status: 'success',
type: 'response',
result: {
ledger_current_index: 10714274,
offers: [
{
Account: 'rPyYxUGK8L4dgEvjPs3aRc1B1jEiLr3Hx5',
BookDirectory:
'6EAB7C172DEFA430DBFAD120FDC373B5F5AF8B191649EC98570BCB85BCA78000',
BookNode: '0000000000000000',
Flags: 131072,
LedgerEntryType: 'Offer',
OwnerNode: '0000000000000000',
PreviousTxnID:
'D22993C68C94ACE3F2FCE4A334EBEA98CC46DCA92886C12B5E5B4780B5E17D4E',
PreviousTxnLgrSeq: 10711938,
Sequence: 392,
TakerGets: {
currency: options.gets.currency,
issuer: options.gets.issuer,
value: '0.8095'
},
TakerPays: {
currency: options.pays.currency,
issuer: options.pays.issuer,
value: '268.754'
},
index:
'18B136E08EF50F0DEE8521EA22D16A950CD8B6DDF5F6E07C35F7FDDBBB09718D',
owner_funds: '0.8095132334507441',
quality: '332',
taker_gets_funded: {
currency: options.gets.currency,
issuer: options.gets.issuer,
value: '0.8078974385735969'
},
taker_pays_funded: {
currency: options.pays.currency,
issuer: options.pays.issuer,
value: '268.2219496064341'
}
}
]
}
})
}
module.exports.requestBookOffersAsksResponse = function(request) {
const options = {
gets: request.taker_gets,
pays: request.taker_pays
}
return JSON.stringify({
id: request.id,
result: {
ledger_index: 10716345,
offers: [
{
Account: 'r49y2xKuKVG2dPkNHgWQAV61cjxk8gryjQ',
BookDirectory:
'20294C923E80A51B487EB9547B3835FD483748B170D2D0A4520B15A60037FFCF',
BookNode: '0000000000000000',
Flags: 0,
LedgerEntryType: 'Offer',
OwnerNode: '0000000000000000',
PreviousTxnID:
'544932DC56D72E845AF2B738821FE07865E32EC196270678AB0D947F54E9F49F',
PreviousTxnLgrSeq: 10679000,
Sequence: 434,
TakerGets: {
currency: options.gets.currency,
issuer: options.gets.issuer,
value: '3205.1'
},
TakerPays: {
currency: options.pays.currency,
issuer: options.pays.issuer,
value: '10'
},
index:
'CE457115A4ADCC8CB351B3E35A0851E48DE16605C23E305017A9B697B156DE5A',
owner_funds: '41952.95917199965',
quality: '0.003120027456241615'
},
{
Account: 'rDYCRhpahKEhCFV25xScg67Bwf4W9sTYAm',
BookDirectory:
'20294C923E80A51B487EB9547B3835FD483748B170D2D0A4520B1A2BC2EC5000',
BookNode: '0000000000000000',
Flags: 0,
LedgerEntryType: 'Offer',
OwnerNode: '0000000000000000',
PreviousTxnID:
'F68F9658AB3D462FEB027E6C380F054BC6D2514B43EC3C6AD46EE19C59BF1CC3',
PreviousTxnLgrSeq: 10704238,
Sequence: 233,
TakerGets: {
currency: options.gets.currency,
issuer: options.gets.issuer,
value: '1599.063669386278'
},
TakerPays: {
currency: options.pays.currency,
issuer: options.pays.issuer,
value: '4.99707396683212'
},
index:
'BF14FBB305159DBCAEA91B7E848408F5B559A91B160EBCB6D244958A6A16EA6B',
owner_funds: '3169.910902910102',
quality: '0.003125'
},
{
Account: 'raudnGKfTK23YKfnS7ixejHrqGERTYNFXk',
BookDirectory:
'20294C923E80A51B487EB9547B3835FD483748B170D2D0A4520B2BF1C2F4D4C9',
BookNode: '0000000000000000',
Expiration: 472785284,
Flags: 0,
LedgerEntryType: 'Offer',
OwnerNode: '00000000000008F0',
PreviousTxnID:
'446410E1CD718AC01929DD16B558FCF6B3A7B8BF208C420E67A280C089C5C59B',
PreviousTxnLgrSeq: 10713576,
Sequence: 110104,
TakerGets: {
currency: options.gets.currency,
issuer: options.gets.issuer,
value: '143.1050962074379'
},
TakerPays: {
currency: options.pays.currency,
issuer: options.pays.issuer,
value: '0.4499999999999999'
},
index:
'67924B0EAA15784CC00CCD5FDD655EE2D6D2AE40341776B5F14E52341E7FC73E',
owner_funds: '0',
quality: '0.003144542101755081',
taker_gets_funded: {
currency: options.gets.currency,
issuer: options.gets.issuer,
value: '0'
},
taker_pays_funded: {
currency: options.pays.currency,
issuer: options.pays.issuer,
value: '0'
}
},
{
Account: 'rDVBvAQScXrGRGnzrxRrcJPeNLeLeUTAqE',
BookDirectory:
'20294C923E80A51B487EB9547B3835FD483748B170D2D0A4520B2CD7A2BFBB75',
BookNode: '0000000000000000',
Expiration: 472772651,
Flags: 0,
LedgerEntryType: 'Offer',
OwnerNode: '00000000000003CD',
PreviousTxnID:
'D49164AB68DDA3AEC9DFCC69A35685C4F532B5C231D3C1D25FEA7D5D0224FB84',
PreviousTxnLgrSeq: 10711128,
Sequence: 35625,
TakerGets: {
currency: options.gets.currency,
issuer: options.gets.issuer,
value: '254.329207354604'
},
TakerPays: {
currency: options.pays.currency,
issuer: options.pays.issuer,
value: '0.8'
},
index:
'567BF2825173E3FB28FC94E436B6EB30D9A415FC2335E6D25CDE1BE47B25D120',
owner_funds: '0',
quality: '0.003145529403882357',
taker_gets_funded: {
currency: options.gets.currency,
issuer: options.gets.issuer,
value: '0'
},
taker_pays_funded: {
currency: options.pays.currency,
issuer: options.pays.issuer,
value: '0'
}
},
{
Account: 'rwBYyfufTzk77zUSKEu4MvixfarC35av1J',
BookDirectory:
'20294C923E80A51B487EB9547B3835FD483748B170D2D0A4520B3621DF140FDA',
BookNode: '0000000000000000',
Flags: 0,
LedgerEntryType: 'Offer',
OwnerNode: '0000000000000008',
PreviousTxnID:
'2E371E2B287C8A9FBB3424E4204B17AD9FA1BAA9F3B33C7D2261E3B038AFF083',
PreviousTxnLgrSeq: 10716291,
Sequence: 387756,
TakerGets: {
currency: options.gets.currency,
issuer: options.gets.issuer,
value: '390.4979'
},
TakerPays: {
currency: options.pays.currency,
issuer: options.pays.issuer,
value: '1.23231134568807'
},
index:
'8CA23E55BF9F46AC7E803D3DB40FD03225EFCA66650D4CF0CBDD28A7CCDC8400',
owner_funds: '5704.824764087842',
quality: '0.003155743848271834'
},
{
Account: 'rwjsRktX1eguUr1pHTffyHnC4uyrvX58V1',
BookDirectory:
'20294C923E80A51B487EB9547B3835FD483748B170D2D0A4520B3A4D41FF4211',
BookNode: '0000000000000000',
Flags: 0,
LedgerEntryType: 'Offer',
OwnerNode: '0000000000000000',
PreviousTxnID:
'91763FA7089C63CC4D5D14CBA6A5A5BF7ECE949B0D34F00FD35E733AF9F05AF1',
PreviousTxnLgrSeq: 10716292,
Sequence: 208927,
TakerGets: {
currency: options.gets.currency,
issuer: options.gets.issuer,
value: '1'
},
TakerPays: {
currency: options.pays.currency,
issuer: options.pays.issuer,
value: '0.003160328237957649'
},
index:
'7206866E39D9843623EE79E570242753DEE3C597F3856AEFB4631DD5AD8B0557',
owner_funds: '45.55665106096075',
quality: '0.003160328237957649'
},
{
Account: 'r49y2xKuKVG2dPkNHgWQAV61cjxk8gryjQ',
BookDirectory:
'20294C923E80A51B487EB9547B3835FD483748B170D2D0A4520B4748E68669A7',
BookNode: '0000000000000000',
Flags: 0,
LedgerEntryType: 'Offer',
OwnerNode: '0000000000000000',
PreviousTxnID:
'3B3CF6FF1A336335E78513CF77AFD3A784ACDD7B1B4D3F1F16E22957A060BFAE',
PreviousTxnLgrSeq: 10639969,
Sequence: 429,
TakerGets: {
currency: options.gets.currency,
issuer: options.gets.issuer,
value: '4725'
},
TakerPays: {
currency: options.pays.currency,
issuer: options.pays.issuer,
value: '15'
},
index:
'42894809370C7E6B23498EF8E22AD4B05F02B94F08E6983357A51EA96A95FF7F',
quality: '0.003174603174603175'
},
{
Account: 'rDbsCJr5m8gHDCNEHCZtFxcXHsD4S9jH83',
BookDirectory:
'20294C923E80A51B487EB9547B3835FD483748B170D2D0A4520B58077ED03C1B',
BookNode: '0000000000000000',
Flags: 131072,
LedgerEntryType: 'Offer',
OwnerNode: '0000000000000001',
PreviousTxnID:
'98F3F2D02D3BB0AEAC09EECCF2F24BBE5E1AB2C71C40D7BD0A5199E12541B6E2',
PreviousTxnLgrSeq: 10715839,
Sequence: 110099,
TakerGets: {
currency: options.gets.currency,
issuer: options.gets.issuer,
value: '1.24252537879871'
},
TakerPays: {
currency: options.pays.currency,
issuer: options.gets.issuer,
value: '0.003967400879423823'
},
index:
'F4404D6547149419D3607F81D7080979FBB3AFE2661F9A933E2F6C07AC1D1F6D',
owner_funds: '73.52163803897041',
quality: '0.003193013959408667'
},
{
Account: 'rDVBvAQScXrGRGnzrxRrcJPeNLeLeUTAqE',
BookDirectory:
'20294C923E80A51B487EB9547B3835FD483748B170D2D0A4520B72A555B981A3',
BookNode: '0000000000000000',
Expiration: 472772652,
Flags: 0,
LedgerEntryType: 'Offer',
OwnerNode: '00000000000003CD',
PreviousTxnID:
'146C8DBB047BAAFAE5B8C8DECCCDACD9DFCD7A464E5AB273230FF975E9B83CF7',
PreviousTxnLgrSeq: 10711128,
Sequence: 35627,
TakerGets: {
currency: options.gets.currency,
issuer: options.gets.issuer,
value: '496.5429474010489'
},
TakerPays: {
currency: options.pays.currency,
issuer: options.pays.issuer,
value: '1.6'
},
index:
'50CAA04E81D0009115B61C132FC9887FA9E5336E0CB8A2E7D3280ADBF6ABC043',
quality: '0.003222279177208227',
taker_gets_funded: {
currency: options.gets.currency,
issuer: options.gets.issuer,
value: '0'
},
taker_pays_funded: {
currency: options.pays.currency,
issuer: options.pays.issuer,
value: '0'
}
},
{
Account: 'r49y2xKuKVG2dPkNHgWQAV61cjxk8gryjQ',
BookDirectory:
'20294C923E80A51B487EB9547B3835FD483748B170D2D0A4520B730474DD96E5',
BookNode: '0000000000000000',
Flags: 0,
LedgerEntryType: 'Offer',
OwnerNode: '0000000000000000',
PreviousTxnID:
'624F9ADA85EC3BE845EAC075B47E01E4F89288EAF27823C715777B3DFFB21F24',
PreviousTxnLgrSeq: 10639989,
Sequence: 431,
TakerGets: {
currency: options.gets.currency,
issuer: options.gets.issuer,
value: '3103'
},
TakerPays: {
currency: options.pays.currency,
issuer: options.pays.issuer,
value: '10'
},
index:
'8A319A496288228AD9CAD74375E32FA81805C56A9AD84798A26756A8B3F9EE23',
quality: '0.003222687721559781'
}
],
validated: false
},
status: 'success',
type: 'response'
})
}
module.exports.requestBookOffersXRPBaseResponse = function(request) {
return JSON.stringify({
id: request.id,

View File

@@ -0,0 +1,13 @@
{
"taker_gets": {
"currency": "XRP"
},
"taker_pays": {
"currency": "JPY",
"issuer": "rB3gZey7VWHYRqJHLoHDEJXJ2pEPNieKiS"
},
"ledger_index": "validated",
"limit": 400,
"taker": "rE9qNjzJXpiUbVomdv7R4xhrXVeH2oVmGR",
"command": "book_offers"
}

View File

@@ -0,0 +1,13 @@
{
"taker_gets": {
"currency": "JPY",
"issuer": "rB3gZey7VWHYRqJHLoHDEJXJ2pEPNieKiS"
},
"taker_pays": {
"currency": "XRP"
},
"ledger_index": "validated",
"limit": 400,
"taker": "rE9qNjzJXpiUbVomdv7R4xhrXVeH2oVmGR",
"command": "book_offers"
}

View File

@@ -0,0 +1,13 @@
{
"taker_gets": {
"currency": "USD",
"issuer": "rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B"
},
"taker_pays": {
"currency": "XRP"
},
"ledger_index": "validated",
"limit": 400,
"taker": "rE9qNjzJXpiUbVomdv7R4xhrXVeH2oVmGR",
"command": "book_offers"
}

View File

@@ -0,0 +1,13 @@
{
"taker_gets": {
"currency": "XRP"
},
"taker_pays": {
"currency": "USD",
"issuer": "rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B"
},
"ledger_index": "validated",
"limit": 400,
"taker": "rE9qNjzJXpiUbVomdv7R4xhrXVeH2oVmGR",
"command": "book_offers"
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,6 @@
{
"ledger_hash": "C4F68C1CF2E0BFC09284690067ED7B1A38D4509A09DF26D66EABCE4F196CE9E9",
"ledger_index": 42595629,
"offers": [],
"validated": true
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -11,6 +11,7 @@ const accountLinesResponse = require('./fixtures/rippled/account-lines');
const accountObjectsResponse = require('./fixtures/rippled/account-objects');
const fullLedger = require('./fixtures/rippled/ledger-full-38129.json');
const { getFreePort } = require('./utils/net-utils');
const fs = require('fs');
function isUSD(json) {
return json === 'USD' || json === '0000000000000000000000005553440000000000';
@@ -464,6 +465,8 @@ module.exports = function createMockRippled(port) {
}
});
let requestsCache = undefined;
mock.on('request_book_offers', function (request, conn) {
if (request.taker_pays.issuer === 'rp8rJYTpodf8qbSCHVTNacf8nSW8mRakFw') {
conn.send(createResponse(request, fixtures.book_offers.xrp_usd));
@@ -479,6 +482,30 @@ module.exports = function createMockRippled(port) {
conn.send(
fixtures.book_offers.fabric.requestBookOffersAsksResponse(request));
} else {
const rippledDir = 'test/fixtures/rippled';
if (!requestsCache) {
requestsCache = fs.readdirSync(rippledDir + '/requests');
}
for (var i = 0; i < requestsCache.length; i++) {
const file = requestsCache[i];
const json = fs.readFileSync(rippledDir + '/requests/' + file, 'utf8');
const r = JSON.parse(json);
const requestWithoutId = Object.assign({}, request);
delete requestWithoutId.id;
if (JSON.stringify(requestWithoutId) === JSON.stringify(r)) {
const responseFile = rippledDir + '/responses/' + file.split('.')[0] + '-res.json';
const res = fs.readFileSync(responseFile, 'utf8');
const response = createResponse(request, {
"id": 0,
"type": "response",
"status": "success",
"result": JSON.parse(res)
});
conn.send(response);
return;
}
}
assert(false, 'Unrecognized order book: ' + JSON.stringify(request));
}
});