From 5b0094922d04ca5168405ed2ba55ff8b4963f3fb Mon Sep 17 00:00:00 2001 From: Marcelo Salloum dos Santos Date: Mon, 30 Aug 2021 11:55:25 -0300 Subject: [PATCH] Update TradesCallBuilder to accept the trade_type filter and support Liquidity Pool trades (#685) --- CHANGELOG.md | 15 ++- src/server_api.ts | 71 +++++++++----- src/trades_call_builder.ts | 10 ++ test/unit/server_test.js | 188 ++++++++++++++++++++++++++++++++++++- 4 files changed, 258 insertions(+), 26 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c5e2b5de7..401e099bf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,10 +9,23 @@ A breaking change will get clearly marked in this log. ## [v9.0.0](https://github.com/stellar/js-stellar-sdk/compare/v8.2.5...v9.0.0) ### Add + - Introduced a `LiquidityPoolCallBuilder` to make calls to the new `/liquidity_pools` endpoint, including filtering by reserve asset ([#682](https://github.com/stellar/js-stellar-sdk/pull/682)). -### Update +### Updates + - Update `stellar-base` version to `6.0.1` ([#681](https://github.com/stellar/js-stellar-sdk/pull/681)). +- A new kind of trade of type `liquidity_pool` was added. For that reason, the `/trades` endpoint suffered a few changes ([#685](https://github.com/stellar/js-stellar-sdk/pull/685)): + - There's a new field `trade_type` that can be either `orderbook` or `liquidity_pool`. You can filter by that field. + - Liquidity pool trades will contain the field `liquidity_pool_fee_bp` and either `base_liquidity_pool_id` or `counter_liquidity_pool_id`. + - There are a few breaking changes to this endpoint listed in the section below. + +### Breaking changes + +- The response from `/trades` endpoint can now contain two different kinds of trades, `orderbook` and `liquidity_pool` (new), which brought a few breaking changes ([#685](https://github.com/stellar/js-stellar-sdk/pull/685)): + - Some previously mandatory fields were made optional: `counter_offer_id`, `base_offer_id` will only show up in orderbook trades while only one of `base_account` and `counter_account` will appear in liquidity pool trades. + - The `price` field changed from `{n: number; d: number;}` to `{n: string; d: string;}`. + - The links to "base" and "counter" returned from horizon can now point to either an account or a liquidity pool. ### Fix - Updated various developer dependencies to secure versions ([#671](https://github.com/stellar/js-stellar-sdk/pull/671)). diff --git a/src/server_api.ts b/src/server_api.ts index a8e3c7100..62b35a03f 100644 --- a/src/server_api.ts +++ b/src/server_api.ts @@ -123,6 +123,11 @@ export namespace ServerApi { asset: string; }; } + export enum TradeType { + all = "all", + liquidityPools = "liquidity_pools", + orderbook = "orderbook", + } interface EffectRecordMethods { operation?: CallFunction; precedes?: CallFunction; @@ -297,29 +302,53 @@ export namespace ServerApi { | BeginSponsoringFutureReservesOperationRecord | EndSponsoringFutureReservesOperationRecord | RevokeSponsorshipOperationRecord; - export interface TradeRecord extends Horizon.BaseResponse { - id: string; - paging_token: string; - ledger_close_time: string; - offer_id: string; - base_offer_id: string; - base_account: string; - base_amount: string; - base_asset_type: string; - base_asset_code?: string; - base_asset_issuer?: string; - counter_offer_id: string; - counter_account: string; - counter_amount: string; - counter_asset_type: string; - counter_asset_code?: string; - counter_asset_issuer?: string; - base_is_seller: boolean; - base: CallFunction; - counter: CallFunction; - operation: CallFunction; + export namespace TradeRecord { + interface Base extends Horizon.BaseResponse { + id: string; + paging_token: string; + ledger_close_time: string; + offer_id: string; + trade_type: TradeType; + base_account?: string; + base_amount: string; + base_asset_type: string; + base_asset_code?: string; + base_asset_issuer?: string; + counter_account?: string; + counter_amount: string; + counter_asset_type: string; + counter_asset_code?: string; + counter_asset_issuer?: string; + base_is_seller: boolean; + price?: { + n: string; + d: string; + }; + + operation: CallFunction; + } + export interface Orderbook extends Base { + trade_type: TradeType.orderbook; + base_offer_id: string; + base_account: string; + counter_offer_id: string; + counter_account: string; + + base: CallFunction; + counter: CallFunction; + } + export interface LiquidityPool extends Base { + trade_type: TradeType.liquidityPools; + base_liquidity_pool_id?: string; + counter_liquidity_pool_id?: string; + liquidity_pool_fee_bp: number; + + base: CallFunction; + counter: CallFunction; + } } + export type TradeRecord = TradeRecord.Orderbook | TradeRecord.LiquidityPool; export interface TransactionRecord extends Omit { ledger_attr: Horizon.TransactionResponse["ledger"]; diff --git a/src/trades_call_builder.ts b/src/trades_call_builder.ts index 133d07f72..ac1f7b4ec 100644 --- a/src/trades_call_builder.ts +++ b/src/trades_call_builder.ts @@ -54,6 +54,16 @@ export class TradesCallBuilder extends CallBuilder< return this; } + /** + * Filter trades by a specific type. + * @param {ServerApi.TradeType} tradeType the trade type to filter by. + * @returns {TradesCallBuilder} current TradesCallBuilder instance. + */ + public forType(tradeType: ServerApi.TradeType): this { + this.url.setQuery("trade_type", tradeType); + return this; + } + /** * Filter trades for a specific account * @see [Trades for Account](https://www.stellar.org/developers/horizon/reference/endpoints/trades-for-account.html) diff --git a/test/unit/server_test.js b/test/unit/server_test.js index 26b1cdb06..7501bb5dc 100644 --- a/test/unit/server_test.js +++ b/test/unit/server_test.js @@ -1844,6 +1844,7 @@ describe('server.js non-transaction tests', function() { paging_token: '64199539053039617-0', ledger_close_time: '2017-12-07T16:45:19Z', offer_id: '278232', + trade_type: 'orderbook', base_account: 'GB7JKG66CJN3ACX5DX43FOZTTSOI7GZUP547I3BSXIJVUX3NRYUXHE6W', base_amount: '1269.2134875', @@ -1855,7 +1856,11 @@ describe('server.js non-transaction tests', function() { counter_asset_code: 'JPY', counter_asset_issuer: 'GBVAOIACNSB7OVUXJYC5UE2D4YK2F7A24T7EE5YOMN4CE6GCHUTOUQXM', - base_is_seller: true + base_is_seller: true, + price: { + n: "1", + d: "2" + } } ] } @@ -1917,6 +1922,7 @@ describe('server.js non-transaction tests', function() { paging_token: '64199539053039617-0', ledger_close_time: '2017-12-07T16:45:19Z', offer_id: '278232', + trade_type: 'orderbook', base_account: 'GB7JKG66CJN3ACX5DX43FOZTTSOI7GZUP547I3BSXIJVUX3NRYUXHE6W', base_amount: '1269.2134875', @@ -1928,7 +1934,11 @@ describe('server.js non-transaction tests', function() { counter_asset_code: 'JPY', counter_asset_issuer: 'GBVAOIACNSB7OVUXJYC5UE2D4YK2F7A24T7EE5YOMN4CE6GCHUTOUQXM', - base_is_seller: true + base_is_seller: true, + price: { + n: "1", + d: "2" + } } ] } @@ -2001,6 +2011,7 @@ describe('server.js non-transaction tests', function() { paging_token: '64199539053039617-0', ledger_close_time: '2017-12-07T16:45:19Z', offer_id: '278232', + trade_type: 'orderbook', base_account: 'GB7JKG66CJN3ACX5DX43FOZTTSOI7GZUP547I3BSXIJVUX3NRYUXHE6W', base_amount: '1269.2134875', @@ -2012,7 +2023,11 @@ describe('server.js non-transaction tests', function() { counter_asset_code: 'JPY', counter_asset_issuer: 'GBVAOIACNSB7OVUXJYC5UE2D4YK2F7A24T7EE5YOMN4CE6GCHUTOUQXM', - base_is_seller: true + base_is_seller: true, + price: { + n: "1", + d: "2" + } } ] } @@ -2081,6 +2096,7 @@ describe('server.js non-transaction tests', function() { id: '77434489365606401-1', paging_token: '77434489365606401-1', offer_id: '', + trade_type: 'orderbook', seller: 'GBDTBUKFHJOEAFAVNPGIY65CBIH75DYEZ5VQXOE7YHZM7AJKDNEOW5JG', sold_amount: '', @@ -2158,6 +2174,7 @@ describe('server.js non-transaction tests', function() { paging_token: '64199676491993090-0', ledger_close_time: '2017-12-07T16:47:59Z', offer_id: '278245', + trade_type: 'orderbook', base_account: 'GBBHSWC3XSUFKEFDPQO346BCLM3EAJHICWRVSVIQOG4YBIH3A2VCJ6G2', base_amount: '0.0000128', @@ -2172,7 +2189,11 @@ describe('server.js non-transaction tests', function() { counter_asset_code: 'ETH', counter_asset_issuer: 'GBSTRH4QOTWNSVA6E4HFERETX4ZLSR3CIUBLK7AXYII277PFJC4BBYOG', - base_is_seller: false + base_is_seller: false, + price: { + n: "1", + d: "2" + } } ] } @@ -2203,6 +2224,165 @@ describe('server.js non-transaction tests', function() { done(err); }); }); + + it('trades() requests the correct endpoint for type orderbook', function(done) { + let tradesResponse = { + _links: { + self: { + href: + 'https://horizon-live.stellar.org:1337/trades?order=asc&limit=200&trade_type=orderbook&cursor=' + }, + next: { + href: + 'https://horizon-live.stellar.org:1337/trades?order=asc&limit=200&trade_type=orderbook&cursor=64199539053039617-0' + }, + prev: { + href: + 'https://horizon-live.stellar.org:1337/trades?order=desc&limit=200&trade_type=orderbook&cursor=64199539053039617-0' + } + }, + _embedded: { + records: [ + { + _links: { + base: { + href: + 'https://horizon-live.stellar.org:1337/accounts/GB7JKG66CJN3ACX5DX43FOZTTSOI7GZUP547I3BSXIJVUX3NRYUXHE6W' + }, + counter: { + href: + 'https://horizon-live.stellar.org:1337/accounts/GC6APVH2HCFB7QLSTG3U55IYSW7ZRNSCTOZZYZJCNHWX2FONCNJNULYN' + }, + operation: { + href: + 'https://horizon-live.stellar.org:1337/operations/64199539053039617' + } + }, + id: '64199539053039617-0', + paging_token: '64199539053039617-0', + ledger_close_time: '2017-12-07T16:45:19Z', + offer_id: '278232', + trade_type: 'orderbook', + base_account: + 'GB7JKG66CJN3ACX5DX43FOZTTSOI7GZUP547I3BSXIJVUX3NRYUXHE6W', + base_amount: '1269.2134875', + base_asset_type: 'native', + counter_account: + 'GC6APVH2HCFB7QLSTG3U55IYSW7ZRNSCTOZZYZJCNHWX2FONCNJNULYN', + counter_amount: '19637.5167985', + counter_asset_type: 'credit_alphanum4', + counter_asset_code: 'JPY', + counter_asset_issuer: + 'GBVAOIACNSB7OVUXJYC5UE2D4YK2F7A24T7EE5YOMN4CE6GCHUTOUQXM', + base_is_seller: true, + price: { + n: "1", + d: "2" + } + } + ] + } + }; + + this.axiosMock + .expects('get') + .withArgs(sinon.match('https://horizon-live.stellar.org:1337/trades?trade_type=orderbook')) + .returns(Promise.resolve({ data: tradesResponse })); + + this.server + .trades() + .forType('orderbook') + .call() + .then(function(response) { + expect(response.records).to.be.deep.equal( + tradesResponse._embedded.records + ); + done(); + }) + .catch(function(err) { + done(err); + }); + }); + + it('trades() requests the correct endpoint for type liquidity_pool', function(done) { + let tradesResponse = { + _links: { + self: { + href: + 'https://horizon-live.stellar.org:1337/trades?order=asc&limit=200&trade_type=liquidity_pool&cursor=' + }, + next: { + href: + 'https://horizon-live.stellar.org:1337/trades?order=asc&limit=200&trade_type=liquidity_pool&cursor=64199539053039617-0' + }, + prev: { + href: + 'https://horizon-live.stellar.org:1337/trades?order=desc&limit=200&trade_type=liquidity_pool&cursor=64199539053039617-0' + } + }, + _embedded: { + records: [ + { + _links: { + base: { + href: + 'https://horizon-live.stellar.org:1337/accounts/GB7JKG66CJN3ACX5DX43FOZTTSOI7GZUP547I3BSXIJVUX3NRYUXHE6W' + }, + counter: { + href: + 'https://horizon-live.stellar.org:1337/liquidity_pool/dd7b1ab831c273310ddbec6f97870aa83c2fbd78ce22aded37ecbf4f3380fac7' + }, + operation: { + href: + 'https://horizon-live.stellar.org:1337/operations/64199539053039617' + } + }, + id: '64199539053039617-0', + paging_token: '64199539053039617-0', + ledger_close_time: '2017-12-07T16:45:19Z', + offer_id: '4616800602922426369', + trade_type: 'liquidity_pool', + liquidity_pool_fee_bp: 30, + base_account: + 'GB7JKG66CJN3ACX5DX43FOZTTSOI7GZUP547I3BSXIJVUX3NRYUXHE6W', + base_amount: '1269.2134875', + base_asset_type: 'native', + counter_liquidity_pool_id: + 'dd7b1ab831c273310ddbec6f97870aa83c2fbd78ce22aded37ecbf4f3380fac7', + counter_amount: '19637.5167985', + counter_asset_type: 'credit_alphanum4', + counter_asset_code: 'JPY', + counter_asset_issuer: + 'GBVAOIACNSB7OVUXJYC5UE2D4YK2F7A24T7EE5YOMN4CE6GCHUTOUQXM', + base_is_seller: true, + price: { + n: "1", + d: "2" + } + } + ] + } + }; + + this.axiosMock + .expects('get') + .withArgs(sinon.match('https://horizon-live.stellar.org:1337/trades?trade_type=liquidity_pool')) + .returns(Promise.resolve({ data: tradesResponse })); + + this.server + .trades() + .forType('liquidity_pool') + .call() + .then(function(response) { + expect(response.records).to.be.deep.equal( + tradesResponse._embedded.records + ); + done(); + }) + .catch(function(err) { + done(err); + }); + }); }); describe('StrictReceivePathCallBuilder', function() {