test: write tests for sugar functions (#1631)

* test: write tests for sugar functions
This commit is contained in:
Mukul Jangid
2021-09-23 16:04:58 -04:00
committed by Mayukha Vadari
parent 98c9b9bc14
commit f2216446e5
8 changed files with 275 additions and 338 deletions

View File

@@ -41,16 +41,19 @@ async function getBalances(
options: GetBalancesOptions = {}, options: GetBalancesOptions = {},
): Promise<Balance[]> { ): Promise<Balance[]> {
// 1. Get XRP Balance // 1. Get XRP Balance
const xrpRequest: AccountInfoRequest = { const xrpBalance: Balance[] = []
command: 'account_info', if (!options.peer) {
account, const xrpRequest: AccountInfoRequest = {
ledger_index: options.ledger_index ?? 'validated', command: 'account_info',
ledger_hash: options.ledger_hash, account,
ledger_index: options.ledger_index ?? 'validated',
ledger_hash: options.ledger_hash,
}
const balance = await this.request(xrpRequest).then(
(response) => response.result.account_data.Balance,
)
xrpBalance.push({ currency: 'XRP', value: dropsToXrp(balance) })
} }
const balance = await this.request(xrpRequest).then(
(response) => response.result.account_data.Balance,
)
const xrpBalance = { currency: 'XRP', value: dropsToXrp(balance) }
// 2. Get Non-XRP Balance // 2. Get Non-XRP Balance
const linesRequest: AccountLinesRequest = { const linesRequest: AccountLinesRequest = {
command: 'account_lines', command: 'account_lines',
@@ -64,7 +67,7 @@ async function getBalances(
const accountLinesBalance = _.flatMap(responses, (response) => const accountLinesBalance = _.flatMap(responses, (response) =>
formatBalances(response.result.lines), formatBalances(response.result.lines),
) )
return [xrpBalance, ...accountLinesBalance] return [...xrpBalance, ...accountLinesBalance].slice(0, options.limit)
} }
export default getBalances export default getBalances

View File

@@ -1,3 +1,4 @@
/* eslint-disable max-lines-per-function -- Needs to process orderbooks. */
import BigNumber from 'bignumber.js' import BigNumber from 'bignumber.js'
import _ from 'lodash' import _ from 'lodash'
@@ -53,7 +54,7 @@ async function getOrderbook(
command: 'book_offers', command: 'book_offers',
taker_pays: takerPays, taker_pays: takerPays,
taker_gets: takerGets, taker_gets: takerGets,
ledger_index: options.ledger_index ?? 'validated', ledger_index: options.ledger_index,
ledger_hash: options.ledger_hash, ledger_hash: options.ledger_hash,
limit: options.limit ?? DEFAULT_LIMIT, limit: options.limit ?? DEFAULT_LIMIT,
taker: options.taker, taker: options.taker,
@@ -73,12 +74,8 @@ async function getOrderbook(
(reverseOfferResult) => reverseOfferResult.result.offers, (reverseOfferResult) => reverseOfferResult.result.offers,
) )
// Sort the orders
// for both buys and sells, lowest quality is closest to mid-market
// we sort the orders so that earlier orders are closer to mid-market
const orders = [...directOffers, ...reverseOffers] const orders = [...directOffers, ...reverseOffers]
// separate out the orders amongst buy and sell // separate out the buy and sell orders
const buy: BookOffer[] = [] const buy: BookOffer[] = []
const sell: BookOffer[] = [] const sell: BookOffer[] = []
orders.forEach((order) => { orders.forEach((order) => {
@@ -89,7 +86,13 @@ async function getOrderbook(
sell.push(order) sell.push(order)
} }
}) })
return { buy: sortOffers(buy), sell: sortOffers(sell) } // Sort the orders
// for both buys and sells, lowest quality is closest to mid-market
// we sort the orders so that earlier orders are closer to mid-market
return {
buy: sortOffers(buy).slice(0, options.limit),
sell: sortOffers(sell).slice(0, options.limit),
}
} }
export default getOrderbook export default getOrderbook

View File

@@ -29,86 +29,75 @@ describe('getBalances', function () {
assertResultMatch(result, responses.getBalances, 'getBalances') assertResultMatch(result, responses.getBalances, 'getBalances')
}) })
// it('getBalances - limit', async function () { it('getBalances - limit', async function () {
// const options = { limit: 3, ledgerVersion: 123456 } const request = {
// this.mockRippled.addResponse( account: testcase.address,
// 'account_info', options: {
// rippled.account_info.normal, limit: 10,
// ) },
// this.mockRippled.addResponse( }
// 'account_lines', this.mockRippled.addResponse(
// rippledAccountLines.normal, 'account_info',
// ) rippled.account_info.normal,
// this.mockRippled.addResponse('ledger', rippled.ledger.normal) )
// const expectedResponse = responses.getBalances.slice(0, 3) this.mockRippled.addResponse(
// const result = await this.client.getBalances(testcase.address, options) 'account_lines',
// assertResultMatch(result, expectedResponse, 'getBalances') rippledAccountLines.normal,
// }) )
this.mockRippled.addResponse('ledger', rippled.ledger.normal)
const expectedResponse = responses.getBalances.slice(
0,
request.options.limit,
)
const result = await this.client.getBalances(
request.account,
request.options,
)
assertResultMatch(result, expectedResponse, 'getBalances')
})
// it('getBalances - limit & currency', async function () { it('getBalances - peer', async function () {
// const options = { currency: 'USD', limit: 3 } const options = {
// this.mockRippled.addResponse( peer: 'rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B',
// 'account_info', }
// rippled.account_info.normal, this.mockRippled.addResponse(
// ) 'account_info',
// this.mockRippled.addResponse( rippled.account_info.normal,
// 'account_lines', )
// rippledAccountLines.normal, this.mockRippled.addResponse(
// ) 'account_lines',
// this.mockRippled.addResponse('ledger', rippled.ledger.normal) rippledAccountLines.normal,
// const expectedResponse = responses.getBalances )
// .filter((item) => item.currency === 'USD') this.mockRippled.addResponse('ledger', rippled.ledger.normal)
// .slice(0, 3)
// const result = await this.client.getBalances(testcase.address, options)
// assertResultMatch(result, expectedResponse, 'getBalances')
// })
// it("getBalances - limit & currency", async function () { const expectedResponse = responses.getBalances.filter(
// const options = { currency: "USD", limit: 3 }; (item) => item.issuer === options.peer,
// this.mockRippled.addResponse( )
// "account_info", const result = await this.client.getBalances(testcase.address, options)
// rippled.account_info.normal assertResultMatch(result, expectedResponse, 'getBalances')
// ); })
// this.mockRippled.addResponse(
// "account_lines",
// rippledAccountLines.normal
// );
// this.mockRippled.addResponse("ledger", rippled.ledger.normal);
// const expectedResponse = responses.getBalances
// .filter((item) => item.currency === "USD")
// .slice(0, 3);
// const result = await this.client.getBalances(test.address, options);
// console.log(expectedResponse);
// assertResultMatch(result, expectedResponse, "getBalances");
// });
// it("getBalances - limit & currency & issuer", async function () { it('getBalances - limit & peer', async function () {
// const options = { const options = {
// currency: "USD", peer: 'rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B',
// issuer: "rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B", limit: 10,
// limit: 3, }
// }; this.mockRippled.addResponse(
// this.mockRippled.addResponse( 'account_info',
// "account_info", rippled.account_info.normal,
// rippled.account_info.normal )
// ); this.mockRippled.addResponse(
// this.mockRippled.addResponse( 'account_lines',
// "account_lines", rippledAccountLines.normal,
// rippledAccountLines.normal )
// ); this.mockRippled.addResponse('ledger', rippled.ledger.normal)
// this.mockRippled.addResponse("ledger", rippled.ledger.normal);
// const expectedResponse = responses.getBalances const expectedResponse = responses.getBalances
// .filter( .filter((item) => item.issuer === options.peer)
// (item) => .slice(0, options.limit)
// item.currency === "USD" && const result = await this.client.getBalances(testcase.address, options)
// item.issuer === "rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B" assertResultMatch(result, expectedResponse, 'getBalances')
// ) })
// .slice(0, 3);
// const result = await this.client.getBalances(test.address, options);
// console.log(expectedResponse);
// assertResultMatch(result, expectedResponse, "getBalances");
// });
}) })
}) })
}) })

View File

@@ -1,45 +1,26 @@
// import BigNumber from "bignumber.js"; import BigNumber from 'bignumber.js'
// import { assert } from "chai";
import { assert } from 'chai' import { assert } from 'chai'
import { BookOffersRequest } from '../../src' import { BookOffersRequest } from '../../src'
import { OfferLedgerFlags } from '../../src/models/ledger/offer'
import requests from '../fixtures/requests' import requests from '../fixtures/requests'
import responses from '../fixtures/responses' import responses from '../fixtures/responses'
import rippled from '../fixtures/rippled' import rippled from '../fixtures/rippled'
import { setupClient, teardownClient } from '../setupClient' import { setupClient, teardownClient } from '../setupClient'
import { addressTests } from '../testUtils' import { assertResultMatch, assertRejects } from '../testUtils'
// function checkSortingOfOrders(orders) { function checkSortingOfOrders(orders): void {
// let previousRate = "0"; let previousRate = '0'
// for (let i = 0; i < orders.length; i++) { for (const order of orders) {
// const order = orders[i]; assert(
// let rate; new BigNumber(order.quality).isGreaterThanOrEqualTo(previousRate),
`Rates must be sorted from least to greatest: ${
// // We calculate the quality of output/input here as a test. order.quality as number
// // This won't hold in general because when output and input amounts get tiny, } should be >= ${previousRate}`,
// // the quality can differ significantly. However, the offer stays in the )
// // order book where it was originally placed. It would be more consistent previousRate = order.quality
// // 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).isGreaterThanOrEqualTo(previousRate),
// `Rates must be sorted from least to greatest: ${rate} should be >= ${previousRate}`
// );
// previousRate = rate;
// }
// return true;
// }
function isUSD(currency: string): boolean { function isUSD(currency: string): boolean {
return ( return (
@@ -73,142 +54,141 @@ function normalRippledResponse(
throw new Error('unexpected end') throw new Error('unexpected end')
} }
// function xrpRippledResponse( function xrpRippledResponse(
// request: BookOffersRequest, request: BookOffersRequest,
// ): Record<string, unknown> { ): Record<string, unknown> {
// if (request.taker_pays.issuer === 'rp8rJYTpodf8qbSCHVTNacf8nSW8mRakFw') { if (request.taker_pays.issuer === 'rp8rJYTpodf8qbSCHVTNacf8nSW8mRakFw') {
// return rippled.book_offers.xrp_usd return rippled.book_offers.xrp_usd
// } }
// if (request.taker_gets.issuer === 'rp8rJYTpodf8qbSCHVTNacf8nSW8mRakFw') { if (request.taker_gets.issuer === 'rp8rJYTpodf8qbSCHVTNacf8nSW8mRakFw') {
// return rippled.book_offers.usd_xrp return rippled.book_offers.usd_xrp
// } }
// throw new Error('unexpected end') throw new Error('unexpected end')
// } }
describe('client.getOrderbook', function () { describe('client.getOrderbook', function () {
beforeEach(setupClient) beforeEach(setupClient)
afterEach(teardownClient) afterEach(teardownClient)
addressTests.forEach(function (testcase) { it('normal', async function () {
describe(testcase.type, function () { this.mockRippled.addResponse('book_offers', normalRippledResponse)
it('normal', async function () { const request = {
this.mockRippled.addResponse('book_offers', normalRippledResponse) takerPays: requests.getOrderbook.normal.takerPays,
const response = await this.client.getOrderbook( takerGets: requests.getOrderbook.normal.takerGets,
requests.getOrderbook.normal.taker_pays, options: {
requests.getOrderbook.normal.taker_gets, limit: 1,
{ limit: 1 }, },
) }
assert.deepEqual(response, responses.getOrderbook.normal) const response = await this.client.getOrderbook(
}) request.takerPays,
request.takerGets,
request.options,
)
const expectedResponse = {
buy: responses.getOrderbook.normal.buy.slice(0, request.options.limit),
sell: responses.getOrderbook.normal.sell.slice(0, request.options.limit),
}
assertResultMatch(response, expectedResponse, 'getOrderbook')
})
// it('invalid options', async function () { it('invalid options', async function () {
// this.mockRippled.addResponse('book_offers', normalRippledResponse) this.mockRippled.addResponse('book_offers', normalRippledResponse)
// assertRejects( assertRejects(
// this.client.getOrderbook( this.client.getOrderbook(
// testcase.address, requests.getOrderbook.normal.takerPays,
// requests.getOrderbook.normal, requests.getOrderbook.normal.takerGets,
// { {
// invalid: 'options', invalid: 'options',
// }, },
// ), ),
// this.client.errors.ValidationError, this.client.errors.ValidationError,
// ) )
// }) })
// it('with XRP', async function () {
// this.mockRippled.addResponse('book_offers', xrpRippledResponse) it('with XRP', async function () {
// const response = await this.client.getOrderbook( this.mockRippled.addResponse('book_offers', xrpRippledResponse)
// testcase.address, const response = await this.client.getOrderbook(
// requests.getOrderbook.withXRP, requests.getOrderbook.withXRP.takerPays,
// ) requests.getOrderbook.withXRP.takerGets,
// assertResultMatch( )
// response, assertResultMatch(response, responses.getOrderbook.withXRP, 'getOrderbook')
// responses.getOrderbook.withXRP, })
// 'getOrderbook',
// ) it('sample USD/XRP book has orders sorted correctly', async function () {
// }) this.mockRippled.addResponse('book_offers', xrpRippledResponse)
// 'sample XRP/JPY book has orders sorted correctly', async function () { const response = await this.client.getOrderbook(
// const orderbookInfo = { requests.getOrderbook.withXRP.takerPays,
// base: { requests.getOrderbook.withXRP.takerGets,
// // the first currency in pair )
// currency: 'XRP' checkSortingOfOrders(response.buy)
// }, checkSortingOfOrders(response.sell)
// counter: { })
// currency: 'JPY',
// counterparty: 'rB3gZey7VWHYRqJHLoHDEJXJ2pEPNieKiS' it('sorted so that best deals come first [failure test]', async function () {
// } this.mockRippled.addResponse('book_offers', normalRippledResponse)
// } const response = await this.client.getOrderbook(
// const myAddress = 'rE9qNjzJXpiUbVomdv7R4xhrXVeH2oVmGR' requests.getOrderbook.normal.takerPays,
// const response = await this.client.getOrderbook(myAddress, orderbookInfo) requests.getOrderbook.normal.takerGets,
// assert.deepStrictEqual([], response.bids) )
// checkSortingOfOrders(response.asks) const buyRates = response.buy.map(async (item) => item.quality as number)
// }, const sellRates = response.sell.map(async (item) => item.quality as number)
// 'sample USD/XRP book has orders sorted correctly', async function () { // buy and sell orders should be sorted so that the best deals come first
// const orderbookInfo = { assert.deepEqual(
// counter: {currency: 'XRP'}, buyRates.sort((item) => Number(item)),
// base: { buyRates,
// currency: 'USD', )
// counterparty: 'rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B' assert.deepEqual(
// } sellRates.sort((item) => Number(item)),
// } sellRates,
// const myAddress = 'rE9qNjzJXpiUbVomdv7R4xhrXVeH2oVmGR' )
// const response = await this.client.getOrderbook(myAddress, orderbookInfo) })
// checkSortingOfOrders(response.bids)
// checkSortingOfOrders(response.asks) it('sorted so that best deals come first [bad test](XRP)', async function () {
// }, this.mockRippled.addResponse('book_offers', xrpRippledResponse)
// WARNING: This test fails to catch the sorting bug, issue #766 const response = await this.client.getOrderbook(
// it("sorted so that best deals come first [bad test]", async function () { requests.getOrderbook.withXRP.takerPays,
// this.mockRippled.addResponse("book_offers", normalRippledResponse); requests.getOrderbook.withXRP.takerGets,
// const response = await this.client.getOrderbook( )
// test.address, const buyRates = response.buy.map(async (item) => item.quality as number)
// requests.getOrderbook.normal const sellRates = response.sell.map(async (item) => item.quality as number)
// ); // buy and sell orders should be sorted so that the best deals come first
// const bidRates = response.bids.map( assert.deepEqual(
// (bid) => bid.properties.makerExchangeRate buyRates.sort((item) => Number(item)),
// ); buyRates,
// const askRates = response.asks.map( )
// (ask) => ask.properties.makerExchangeRate assert.deepEqual(
// ); sellRates.sort((item) => Number(item)),
// // makerExchangeRate = quality = takerPays.value/takerGets.value sellRates,
// // 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(
// bidRates.sort((x) => Number(x)), it('direction is correct for buy and sell', async function () {
// bidRates this.mockRippled.addResponse('book_offers', normalRippledResponse)
// ); const response = await this.client.getOrderbook(
// assert.deepEqual( requests.getOrderbook.normal.takerPays,
// askRates.sort((x) => Number(x)), requests.getOrderbook.normal.takerGets,
// askRates )
// ); assert.strictEqual(
// }); response.buy.every((item) => item.Flags !== OfferLedgerFlags.lsfSell),
// it("currency & counterparty are correct", async function () { true,
// this.mockRippled.addResponse("book_offers", normalRippledResponse); )
// const response = await this.client.getOrderbook( assert.strictEqual(
// test.address, response.sell.every((item) => item.Flags === OfferLedgerFlags.lsfSell),
// requests.getOrderbook.normal true,
// ); )
// [...response.bids, ...response.asks].forEach((order) => { })
// const quantity = order.specification.quantity;
// const totalPrice = order.specification.totalPrice; it('getOrderbook - limit', async function () {
// const { base, counter } = requests.getOrderbook.normal; this.mockRippled.addResponse('book_offers', normalRippledResponse)
// assert.strictEqual(quantity.currency, base.currency); const LIMIT = 3
// assert.strictEqual(quantity.counterparty, base.counterparty); const response = await this.client.getOrderbook(
// assert.strictEqual(totalPrice.currency, counter.currency); requests.getOrderbook.normal.takerPays,
// assert.strictEqual(totalPrice.counterparty, counter.counterparty); requests.getOrderbook.normal.takerGets,
// }); {
// }); limit: LIMIT,
// it("direction is correct for bids and asks", async function () { },
// this.mockRippled.addResponse("book_offers", normalRippledResponse); )
// const response = await this.client.getOrderbook( assert(response.buy.length <= LIMIT)
// test.address, assert(response.sell.length <= LIMIT)
// requests.getOrderbook.normal
// );
// assert(
// response.bids.every((bid) => bid.specification.direction === "buy")
// );
// assert(
// response.asks.every((ask) => ask.specification.direction === "sell")
// );
// });
})
}) })
}) })

View File

@@ -1,9 +1,9 @@
{ {
"taker_pays": { "takerPays": {
"currency": "USD", "currency": "USD",
"issuer": "rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B" "issuer": "rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B"
}, },
"taker_gets": { "takerGets": {
"currency": "BTC", "currency": "BTC",
"issuer": "rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B" "issuer": "rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B"
} }

View File

@@ -1,9 +1,9 @@
{ {
"base": { "takerPays": {
"currency": "USD", "currency": "USD",
"counterparty": "rp8rJYTpodf8qbSCHVTNacf8nSW8mRakFw" "issuer": "rp8rJYTpodf8qbSCHVTNacf8nSW8mRakFw"
}, },
"counter": { "takerGets": {
"currency": "XRP" "currency": "XRP"
} }
} }

View File

@@ -1,83 +1,45 @@
{ {
"bids": [ "buy": [
{ {
"specification": { "Account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
"direction": "buy", "BookDirectory": "A118405CF7C2C89AB0CC084417187B86870DC14325C861A0470E1AEE5CBE20D9",
"quantity": { "BookNode": "0000000000000000",
"currency": "USD", "Flags": 0,
"value": "10.1", "LedgerEntryType": "Offer",
"counterparty": "rp8rJYTpodf8qbSCHVTNacf8nSW8mRakFw" "OwnerNode": "0000000000000000",
}, "PreviousTxnID": "9DD36CC7338FEB9E501A33EAAA4C00DBE4ED3A692704C62DDBD1848EE1F6E762",
"totalPrice": { "PreviousTxnLgrSeq": 11,
"currency": "XRP", "Sequence": 5,
"value": "254391353" "TakerGets": "254391353000000",
} "TakerPays": {
"currency": "USD",
"issuer": "rp8rJYTpodf8qbSCHVTNacf8nSW8mRakFw",
"value": "10.1"
}, },
"properties": { "index": "BF656DABDD84E6128A45039F8D557C9477D4DA31F5B00868F2191F0A11FE3798",
"maker": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh", "owner_funds": "99999998959999928",
"sequence": 5, "quality": "3970260734451929e-29"
"makerExchangeRate": "3.970260734451929e-8"
},
"data": {
"Account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
"BookDirectory": "A118405CF7C2C89AB0CC084417187B86870DC14325C861A0470E1AEE5CBE20D9",
"BookNode": "0000000000000000",
"Flags": 0,
"LedgerEntryType": "Offer",
"OwnerNode": "0000000000000000",
"PreviousTxnID": "9DD36CC7338FEB9E501A33EAAA4C00DBE4ED3A692704C62DDBD1848EE1F6E762",
"PreviousTxnLgrSeq": 11,
"Sequence": 5,
"TakerGets": "254391353000000",
"TakerPays": {
"currency": "USD",
"issuer": "rp8rJYTpodf8qbSCHVTNacf8nSW8mRakFw",
"value": "10.1"
},
"index": "BF656DABDD84E6128A45039F8D557C9477D4DA31F5B00868F2191F0A11FE3798",
"owner_funds": "99999998959999928",
"quality": "3970260734451929e-29"
}
} }
], ],
"asks": [ "sell": [
{ {
"specification": { "Account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
"direction": "sell", "BookDirectory": "A118405CF7C2C89AB0CC084417187B86870DC14325C861A0561BB6E89EFF509C",
"quantity": { "BookNode": "0000000000000000",
"currency": "USD", "Flags": 131072,
"value": "10453252347.1", "LedgerEntryType": "Offer",
"counterparty": "rp8rJYTpodf8qbSCHVTNacf8nSW8mRakFw" "OwnerNode": "0000000000000000",
}, "PreviousTxnID": "CFB5786459E568DFC504E7319C515658DED657A7F4EFB5957B33E5E3BD9A1353",
"totalPrice": { "PreviousTxnLgrSeq": 13,
"currency": "XRP", "Sequence": 6,
"value": "134" "TakerGets": {
} "currency": "USD",
"issuer": "rp8rJYTpodf8qbSCHVTNacf8nSW8mRakFw",
"value": "10453252347.1"
}, },
"properties": { "TakerPays": "134000000",
"maker": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh", "index": "C72CDC1BA4DA529B062871F22C6D175A4D97D4F1160D0D7E646E60699278B5B5",
"sequence": 6, "quality": "78.0093458738806"
"makerExchangeRate": "0.0000780093458738806"
},
"data": {
"Account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
"BookDirectory": "A118405CF7C2C89AB0CC084417187B86870DC14325C861A0561BB6E89EFF509C",
"BookNode": "0000000000000000",
"Flags": 131072,
"LedgerEntryType": "Offer",
"OwnerNode": "0000000000000000",
"PreviousTxnID": "CFB5786459E568DFC504E7319C515658DED657A7F4EFB5957B33E5E3BD9A1353",
"PreviousTxnLgrSeq": 13,
"Sequence": 6,
"TakerPays": "134000000",
"TakerGets": {
"currency": "USD",
"issuer": "rp8rJYTpodf8qbSCHVTNacf8nSW8mRakFw",
"value": "10453252347.1"
},
"index": "C72CDC1BA4DA529B062871F22C6D175A4D97D4F1160D0D7E646E60699278B5B5",
"quality": "78.0093458738806"
}
} }
] ]
} }

View File

@@ -66,7 +66,7 @@ export default function createMockRippled(port: number): MockedWebSocketServer {
throw new Error(`Request has no id: ${requestJSON}`) throw new Error(`Request has no id: ${requestJSON}`)
} }
if (request.command == null) { if (request.command == null) {
throw new Error(`Request has no id: ${requestJSON}`) throw new Error(`Request has no command: ${requestJSON}`)
} }
if (request.command === 'ping') { if (request.command === 'ping') {
ping(conn, request) ping(conn, request)