Skip to content

Commit

Permalink
Support for automated market makers (CAP-38) (#693).
Browse files Browse the repository at this point in the history
* Use stellar-base 6.0.1 from the npm registry.
* Correctly process transaction response for offers based on XDR changes (#681)
* Adds a basic call builder for the `/liquidity_pools` endpoint. (#682)
* Add call builder for liquidity pools, w/ filters by reserve asset
* Update TradesCallBuilder to accept the trade_type filter and support Liquidity Pool trades (#685)
* [CD/CI] Add GitHub Actions to run tests on PRs (#686)
* Support filtering accounts participating in a given LP and update accounts balance response (#688)
* Allow querying a single liquidity pool by its specific ID. (#687)
* Allow querying actions (ops, txs, fx) related to a specific liquidity pool. (#689)
* Add new effect types (#690)
* Refactors call builders to simplify referencing 'neighbor' endpoints (#691)
* Update with CAP-38 operations (#692)
* Simplifies an expression to be more readable (#695)
* Updates the CHANGELOG to be more uniform and specific. (#694)
* Fix how the ?reserves filter works on the /accounts endpoint (#698)
* Update more call builders to use the new helper API. (#699)
* Add integration tests against the real mock API server (#697)
* Prepares the v9.0.0 branch for merging into master (#701)
* Update Horizon API fields to reflect the coming post-AMM API (#702)

Co-authored-by: Marcelo Salloum dos Santos <marcelo@stellar.org>
Co-authored-by: George <Shaptic@users.noreply.github.com>
Co-authored-by: George Kudrayvtsev <george@stellar.org>
  • Loading branch information
3 people committed Sep 2, 2021
1 parent 8e85393 commit e924deb
Show file tree
Hide file tree
Showing 23 changed files with 2,257 additions and 108 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/npm_publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,6 @@ jobs:
run: gulp

- name: Publish npm package
run: yarn publish
run: yarn publish --tag beta
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
75 changes: 74 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,84 @@

A breaking change will get clearly marked in this log.


## Unreleased

### Fix
### Add

- Introduced a `LiquidityPoolCallBuilder` to make calls to a new endpoint:
* `/liquidity_pools[?reserves=...]` - a collection of liquidity pools, optionally filtered by one or more assets ([#682](https://github.com/stellar/js-stellar-sdk/pull/682))
* `/liquidity_pools/:id` - a specific liquidity pool ([#687](https://github.com/stellar/js-stellar-sdk/pull/687))

- Expanded the `TransactionCallBuilder`, `OperationCallBuilder`, and `EffectsCallBuilder`s to apply to specific liquidity pools ([#689](https://github.com/stellar/js-stellar-sdk/pull/689)). This corresponds to the following new endpoints:
* `/liquidity_pools/:id/transactions`
* `/liquidity_pools/:id/operations`
* `/liquidity_pools/:id/effects`

- Expanded the `TradesCallBuilder` to support fetching liquidity pool trades and accepts a new `trade_type` filter ([#685](https://github.com/stellar/js-stellar-sdk/pull/685)):
* `/trades?trade_type={orderbook,liquidity_pools}`
* A liquidity pool trade contains the following fields:
- `liquidity_pool_fee_bp`: LP fee expressed in basis points, and *either*
- `base_liquidity_pool_id` or `counter_liquidity_pool_id`

- Added new effects related to liquidity pools ([#690](https://github.com/stellar/js-stellar-sdk/pull/690)):
* `DepositLiquidityEffect`
* `WithdrawLiquidityEffect`
* `LiquidityPoolTradeEffect`
* `LiquidityPoolCreatedEffect`
* `LiquidityPoolRemovedEffect`
* `LiquidityPoolRevokedEffect`

- Added new responses related to liquidity pool operations ([#692](https://github.com/stellar/js-stellar-sdk/pull/692)):
* `DepositLiquidityOperationResponse`
* `WithdrawLiquidityOperationResponse`

### Updates

- Updated the underlying `stellar-base` library to [v6.0.1](https://github.com/stellar/js-stellar-base/releases/tag/v6.0.1) to include CAP-38 changes ([#681](https://github.com/stellar/js-stellar-sdk/pull/681)).

- Updated various developer dependencies to secure versions ([#671](https://github.com/stellar/js-stellar-sdk/pull/671)).

- Updated `AccountResponse` to include liquidity pool shares in its `balances` field ([#688](https://github.com/stellar/js-stellar-sdk/pull/688)).

- Updated `AccountCallBuilder` to allow filtering based on participation in a certain liquidity pool ([#688](https://github.com/stellar/js-stellar-sdk/pull/688)), corresponding to the following new filter:
* `/accounts?reserves=[...list of assets...]`

- Updated `RevokeSponsorshipOperationResponse` to contain an optional attribute `trustline_liquidity_pool_id`, for when a liquidity pool trustline is revoked ([#690](https://github.com/stellar/js-stellar-sdk/pull/690)).

### Breaking changes

- A `TradeRecord` can now correspond to two different types of trades and has changed ([#685](https://github.com/stellar/js-stellar-sdk/pull/685)):
* `Orderbook` (the existing structure)
- `counter_offer_id` and `base_offer_id` only show up in these records
* `LiquidityPool` (new)
- `base_account` xor `counter_account` will appear in these records
* `price` fields changed from `number`s to `string`s
* The links to `base` and `counter` can now point to *either* an account or a liquidity pool

- An account's `balances` array can now include a new type ([#688](https://github.com/stellar/js-stellar-sdk/pull/688)):
* `asset_type` can now be `liquidity_pool_shares`
* The following fields are *not* included in pool share balances:
- `buying_liabilities`
- `selling_liabilities`
- `asset_code`
- `asset_issue`

- The `ChangeTrustOperationResponse` has changed ([#688](https://github.com/stellar/js-stellar-sdk/pull/688), [#692](https://github.com/stellar/js-stellar-sdk/pull/692)):
* `asset_type` can now be `liquidity_pool_shares`
* `asset_code`, `asset_issuer`, and `trustee` are now optional
* `liquidity_pool_id` is a new optional field

- The trustline effects (`TrustlineCreated`, `TrustlineUpdated`, `TrustlineRevoked`) have changed ([#690](https://github.com/stellar/js-stellar-sdk/pull/690)):
* the asset type can now be `liquidity_pool_shares`
* they can optionally include a `liquidity_pool_id`

- Trustline sponsorship effects (`TrustlineSponsorshipCreated`, `TrustlineSponsorshipUpdated`, `TrustlineSponsorshipRemoved`) have been updated ([#690](https://github.com/stellar/js-stellar-sdk/pull/690)):
* the `asset` field is now optional, and is replaced by
* the `liquidity_pool_id` field for liquidity pools

- `TradeRecord`s no longer have an `offer_id` field. This field is redundant, being represented by `base_offer_id` in given an `Orderbook` trade.


## [v8.2.5](https://github.com/stellar/js-stellar-sdk/compare/v8.2.4...v8.2.5)

Expand Down
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -132,12 +132,13 @@
"@types/urijs": "^1.19.6",
"axios": "0.21.1",
"bignumber.js": "^4.0.0",
"chai-http": "^4.3.0",
"detect-node": "^2.0.4",
"es6-promise": "^4.2.4",
"eventsource": "^1.0.7",
"lodash": "^4.17.21",
"randombytes": "^2.1.0",
"stellar-base": "^5.3.2",
"stellar-base": "^6.0.1",
"toml": "^2.3.0",
"tslib": "^1.10.0",
"urijs": "^1.19.1",
Expand Down
13 changes: 12 additions & 1 deletion src/account_call_builder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ export class AccountCallBuilder extends CallBuilder<
*
* @see [Account Details](https://www.stellar.org/developers/horizon/reference/endpoints/accounts-single.html)
* @param {string} id For example: `GDGQVOKHW4VEJRU2TETD6DBRKEO5ERCNF353LW5WBFW3JJWQ2BRQ6KDD`
* @returns {CallBuilder} current AccountCallBuilder instance
* @returns {CallBuilder} a new CallBuilder instance for the /accounts/:id endpoint
*/
public accountId(id: string): CallBuilder<ServerApi.AccountRecord> {
const builder = new CallBuilder<ServerApi.AccountRecord>(this.url.clone());
Expand Down Expand Up @@ -67,4 +67,15 @@ export class AccountCallBuilder extends CallBuilder<
this.url.setQuery("sponsor", id);
return this;
}

/**
* This endpoint filters accounts holding a trustline to the given liquidity pool.
*
* @param {string} id The ID of the liquidity pool. For example: `dd7b1ab831c273310ddbec6f97870aa83c2fbd78ce22aded37ecbf4f3380fac7`.
* @returns {AccountCallBuilder} current AccountCallBuilder instance
*/
public forLiquidityPool(id: string): this {
this.url.setQuery("liquidity_pool", id);
return this;
}
}
27 changes: 26 additions & 1 deletion src/call_builder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,11 +50,13 @@ export class CallBuilder<
protected url: URI;
public filter: string[][];
protected originalSegments: string[];
protected neighborRoot: string;

constructor(serverUrl: URI) {
constructor(serverUrl: URI, neighborRoot: string = "") {
this.url = serverUrl.clone();
this.filter = [];
this.originalSegments = this.url.segment() || [];
this.neighborRoot = neighborRoot;
}

/**
Expand Down Expand Up @@ -242,6 +244,29 @@ export class CallBuilder<
return this;
}

/**
* A helper method to craft queries to "neighbor" endpoints.
*
* For example, we have an `/effects` suffix endpoint on many different
* "root" endpoints, such as `/transactions/:id` and `/accounts/:id`. So,
* it's helpful to be able to conveniently create queries to the
* `/accounts/:id/effects` endpoint:
*
* this.forEndpoint("accounts", accountId)`.
*
* @param {string} endpoint neighbor endpoint in question, like /operations
* @param {string} param filter parameter, like an operation ID
*
* @returns {CallBuilder} this CallBuilder instance
*/
protected forEndpoint(endpoint: string, param: string): this {
if (this.neighborRoot === "") {
throw new Error("Invalid usage: neighborRoot not set in constructor");
}
this.filter.push([endpoint, param, this.neighborRoot]);
return this;
}

/**
* @private
* @returns {void}
Expand Down
28 changes: 15 additions & 13 deletions src/effect_call_builder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ export class EffectCallBuilder extends CallBuilder<
ServerApi.CollectionPage<ServerApi.EffectRecord>
> {
constructor(serverUrl: URI) {
super(serverUrl);
super(serverUrl, "effects");
this.url.segment("effects");
}

Expand All @@ -26,8 +26,7 @@ export class EffectCallBuilder extends CallBuilder<
* @returns {EffectCallBuilder} this EffectCallBuilder instance
*/
public forAccount(accountId: string): this {
this.filter.push(["accounts", accountId, "effects"]);
return this;
return this.forEndpoint("accounts", accountId);
}

/**
Expand All @@ -39,12 +38,7 @@ export class EffectCallBuilder extends CallBuilder<
* @returns {EffectCallBuilder} this EffectCallBuilder instance
*/
public forLedger(sequence: number | string): this {
this.filter.push([
"ledgers",
typeof sequence === "number" ? sequence.toString() : sequence,
"effects",
]);
return this;
return this.forEndpoint("ledgers", sequence.toString());
}

/**
Expand All @@ -54,8 +48,7 @@ export class EffectCallBuilder extends CallBuilder<
* @returns {EffectCallBuilder} this EffectCallBuilder instance
*/
public forTransaction(transactionId: string): this {
this.filter.push(["transactions", transactionId, "effects"]);
return this;
return this.forEndpoint("transactions", transactionId);
}

/**
Expand All @@ -65,7 +58,16 @@ export class EffectCallBuilder extends CallBuilder<
* @returns {EffectCallBuilder} this EffectCallBuilder instance
*/
public forOperation(operationId: string): this {
this.filter.push(["operations", operationId, "effects"]);
return this;
return this.forEndpoint("operations", operationId);
}

/**
* This endpoint represents all effects involving a particular liquidity pool.
*
* @param {string} poolId liquidity pool ID
* @returns {EffectCallBuilder} this EffectCallBuilder instance
*/
public forLiquidityPool(poolId: string): this {
return this.forEndpoint("liquidity_pools", poolId);
}
}
65 changes: 60 additions & 5 deletions src/horizon_api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,17 @@ export namespace Horizon {
buying_liabilities: string;
selling_liabilities: string;
}
export interface BalanceLineLiquidityPool {
liquidity_pool_id: string;
asset_type: AssetType.liquidityPoolShares;
balance: string;
limit: string;
last_modified_ledger: number;
is_authorized: boolean;
is_authorized_to_maintain_liabilities: boolean;
is_clawback_enabled: boolean;
sponsor?: string;
}
export interface BalanceLineAsset<
T extends AssetType.credit4 | AssetType.credit12 =
| AssetType.credit4
Expand All @@ -78,6 +89,7 @@ export namespace Horizon {
last_modified_ledger: number;
is_authorized: boolean;
is_authorized_to_maintain_liabilities: boolean;
is_clawback_enabled: boolean;
sponsor?: string;
}
export type BalanceLine<
Expand All @@ -86,7 +98,9 @@ export namespace Horizon {
? BalanceLineNative
: T extends AssetType.credit4 | AssetType.credit12
? BalanceLineAsset<T>
: BalanceLineNative | BalanceLineAsset;
: T extends AssetType.liquidityPoolShares
? BalanceLineLiquidityPool
: BalanceLineNative | BalanceLineAsset | BalanceLineLiquidityPool;

export interface AssetAccounts {
authorized: number;
Expand Down Expand Up @@ -153,6 +167,10 @@ export namespace Horizon {
num_sponsored: number;
}

export enum LiquidityPoolType {
constantProduct = "constant_product",
}

export enum OperationResponseType {
createAccount = "create_account",
payment = "payment",
Expand All @@ -176,6 +194,8 @@ export namespace Horizon {
clawback = "clawback",
clawbackClaimableBalance = "clawback_claimable_balance",
setTrustLineFlags = "set_trust_line_flags",
liquidityPoolDeposit = "liquidity_pool_deposit",
liquidityPoolWithdraw = "liquidity_pool_withdraw",
}
export enum OperationResponseTypeI {
createAccount = 0,
Expand All @@ -200,6 +220,8 @@ export namespace Horizon {
clawback = 19,
clawbackClaimableBalance = 20,
setTrustLineFlags = 21,
liquidityPoolDeposit = 22,
liquidityPoolWithdraw = 23,
}
export interface BaseOperationResponse<
T extends OperationResponseType = OperationResponseType,
Expand Down Expand Up @@ -340,10 +362,14 @@ export namespace Horizon {
OperationResponseType.changeTrust,
OperationResponseTypeI.changeTrust
> {
asset_type: AssetType.credit4 | AssetType.credit12;
asset_code: string;
asset_issuer: string;
trustee: string;
asset_type:
| AssetType.credit4
| AssetType.credit12
| AssetType.liquidityPoolShares;
asset_code?: string;
asset_issuer?: string;
liquidity_pool_id?: string;
trustee?: string;
trustor: string;
limit: string;
}
Expand Down Expand Up @@ -448,6 +474,7 @@ export namespace Horizon {
offer_id?: string;
trustline_account_id?: string;
trustline_asset?: string;
trustline_liquidity_pool_id?: string;
signer_account_id?: string;
signer_key?: string;
}
Expand Down Expand Up @@ -484,6 +511,34 @@ export namespace Horizon {
set_flags: Array<1 | 2 | 4>;
clear_flags: Array<1 | 2 | 4>;
}
export interface Reserve {
asset: string;
amount: string;
}
export interface DepositLiquidityOperationResponse
extends BaseOperationResponse<
OperationResponseType.liquidityPoolDeposit,
OperationResponseTypeI.liquidityPoolDeposit
> {
liquidity_pool_id: string;
reserves_max: Reserve[];
min_price: string;
min_price_r: PriceRShorthand;
max_price: string;
max_price_r: PriceRShorthand;
reserves_deposited: Reserve[];
shares_received: string;
}
export interface WithdrawLiquidityOperationResponse
extends BaseOperationResponse<
OperationResponseType.liquidityPoolWithdraw,
OperationResponseTypeI.liquidityPoolWithdraw
> {
liquidity_pool_id: string;
reserves_min: Reserve[];
shares: string;
reserves_received: Reserve[];
}

export interface ResponseCollection<T extends BaseResponse = BaseResponse> {
_links: {
Expand Down
Loading

0 comments on commit e924deb

Please sign in to comment.