Skip to content

Commit

Permalink
feat: upload appData, get data, surplus, version, and solver competit…
Browse files Browse the repository at this point in the history
…ion (#131)

* Update SDK with the latest methods

* Add total surplus tests

* Create RC0

* Fix surplus endpoint

* Make a test RC

* fix tests

* 2.3.0-rc.3

* 2.3.0-rc.4

* Update version

* Improve fetch implementation to allow you to serialise the JSON yourself

* chore: update upload appData to new swagger

* chore: update to latest api implementation for app-data

* RC9

* Fix lint error

* Set version
  • Loading branch information
anxolin committed Aug 2, 2023
1 parent b0abac1 commit ad0c108
Show file tree
Hide file tree
Showing 11 changed files with 419 additions and 6 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@cowprotocol/cow-sdk",
"version": "2.2.1",
"version": "2.3.0",
"license": "(MIT OR Apache-2.0)",
"files": [
"/dist"
Expand Down
129 changes: 129 additions & 0 deletions src/order-book/api.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import { OrderBookApi } from './api'
import { BuyTokenDestination, EcdsaSigningScheme, OrderKind, SellTokenSource, SigningScheme } from './generated'
import { SupportedChainId } from '../common/chains'
import { BUY_ETH_ADDRESS } from './transformOrder'
import { AUCTION } from './mock'

enableFetchMocks()

Expand Down Expand Up @@ -117,6 +118,22 @@ describe('CoW Api', () => {
jest.restoreAllMocks()
})

test('Valid: Get version', async () => {
// given
fetchMock.mockResponseOnce(JSON.stringify('v1.2.3'), {
status: HTTP_STATUS_OK,
headers: HEADERS,
})

// when
const version = await orderBookApi.getVersion()

// then
expect(fetchMock).toHaveBeenCalledTimes(1)
expect(fetchMock).toHaveBeenCalledWith('https://api.cow.fi/xdai/api/v1/version', FETCH_RESPONSE_PARAMETERS)
expect(version).toEqual('v1.2.3')
})

test('Valid: Get orders link', async () => {
const orderLink = await orderBookApi.getOrderLink(ORDER_RESPONSE.uid)
expect(orderLink).toEqual(`https://api.cow.fi/xdai/api/v1/orders/${ORDER_RESPONSE.uid}`)
Expand Down Expand Up @@ -608,4 +625,116 @@ describe('CoW Api', () => {
FETCH_RESPONSE_PARAMETERS
)
})

test('Valid: Get total surplus', async () => {
// given
const address = '0x6810e776880c02933d47db1b9fc05908e5386b96'
const totalSurplus = {
totalSurplus: '123456789',
}
fetchMock.mockResponseOnce(JSON.stringify(totalSurplus), {
status: HTTP_STATUS_OK,
headers: HEADERS,
})

// when
const surplus = await orderBookApi.getTotalSurplus(address)

// then
expect(fetchMock).toHaveBeenCalledTimes(1)
expect(fetchMock).toHaveBeenCalledWith(
`https://api.cow.fi/xdai/api/v1/users/${address}/total_surplus`,
FETCH_RESPONSE_PARAMETERS
)
expect(surplus).toEqual(totalSurplus)
})

test('Valid: Get AppData', async () => {
// given
const appDataHash = '0x1fddf237451709522e5ac66887f979db70c3501efd4623ee86225ff914423fa1'
const appDataBody = {
fullAppData: '{"hello": "world"}',
}
fetchMock.mockResponseOnce(JSON.stringify(appDataBody), {
status: HTTP_STATUS_OK,
headers: HEADERS,
})

// when
const appData = await orderBookApi.getAppData(appDataHash)

// then
expect(fetchMock).toHaveBeenCalledTimes(1)
expect(fetchMock).toHaveBeenCalledWith(
`https://api.cow.fi/xdai/api/v1/app_data/${appDataHash}`,
FETCH_RESPONSE_PARAMETERS
)
expect(appData).toEqual(appDataBody)
})

test('Valid: Upload AppData', async () => {
// given
const appDataHash = '0x1fddf237451709522e5ac66887f979db70c3501efd4623ee86225ff914423fa1'
const appDataBody = {
fullAppData: '{"hello": "world"}',
}
fetchMock.mockResponseOnce(JSON.stringify(appDataHash), {
status: HTTP_STATUS_OK,
headers: HEADERS,
})

// when
const appDataHashResult = await orderBookApi.uploadAppData(appDataHash, appDataBody.fullAppData)

// then
expect(fetchMock).toHaveBeenCalledTimes(1)
expect(fetchMock).toHaveBeenCalledWith(
`https://api.cow.fi/xdai/api/v1/app_data/${appDataHash}`,
expect.objectContaining({
body: JSON.stringify(appDataBody),
method: 'PUT',
})
)
expect(appDataHashResult).toEqual(appDataHash)
})

test('Valid: Get solver competition by auctionId', async () => {
// given
const auctionId = 7841036
fetchMock.mockResponseOnce(JSON.stringify(AUCTION), {
status: HTTP_STATUS_OK,
headers: HEADERS,
})

// when
const competition = await orderBookApi.getSolverCompetition(auctionId)

// then
expect(fetchMock).toHaveBeenCalledTimes(1)
expect(fetchMock).toHaveBeenCalledWith(
`https://api.cow.fi/xdai/api/v1/solver_competition/${auctionId}`,
FETCH_RESPONSE_PARAMETERS
)
expect(competition).toEqual(AUCTION)
})

test('Valid: Get solver competition by tx hash', async () => {
// given
const txHash = '0xe395eac238e7c6b2f4c5dea57d4a3d9a2b42d9f4ae5574dd003f9e5dd76abeee'
fetchMock.mockResponseOnce(JSON.stringify(AUCTION), {
status: HTTP_STATUS_OK,
headers: HEADERS,
})

// when
const competition = await orderBookApi.getSolverCompetition(txHash)

// then
expect(fetchMock).toHaveBeenCalledTimes(1)
expect(fetchMock).toHaveBeenCalledWith(
`https://api.cow.fi/xdai/api/v1/solver_competition/by_tx_hash/${txHash}`,
FETCH_RESPONSE_PARAMETERS
)
expect(competition).toEqual(AUCTION)
})
})
43 changes: 43 additions & 0 deletions src/order-book/api.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
import 'cross-fetch/polyfill'
import {
Address,
AppDataDocument,
AppDataHash,
NativePriceResponse,
Order,
OrderCancellations,
OrderCreation,
OrderQuoteRequest,
OrderQuoteResponse,
SolverCompetitionResponse,
TotalSurplus,
Trade,
TransactionHash,
UID,
Expand Down Expand Up @@ -57,6 +61,10 @@ export class OrderBookApi {
this.rateLimiter = new RateLimiter(context.limiterOpts || DEFAULT_LIMITER_OPTIONS)
}

getVersion(contextOverride: PartialApiContext = {}): Promise<string> {
return this.fetch({ path: '/api/v1/version', method: 'GET' }, contextOverride)
}

getTrades(
request: { owner?: Address; orderUid?: UID },
contextOverride: PartialApiContext = {}
Expand Down Expand Up @@ -148,6 +156,41 @@ export class OrderBookApi {
getNativePrice(tokenAddress: Address, contextOverride: PartialApiContext = {}): Promise<NativePriceResponse> {
return this.fetch({ path: `/api/v1/token/${tokenAddress}/native_price`, method: 'GET' }, contextOverride)
}
getTotalSurplus(address: Address, contextOverride: PartialApiContext = {}): Promise<TotalSurplus> {
return this.fetch({ path: `/api/v1/users/${address}/total_surplus`, method: 'GET' }, contextOverride)
}

getAppData(appDataHash: AppDataHash, contextOverride: PartialApiContext = {}): Promise<AppDataDocument> {
return this.fetch({ path: `/api/v1/app_data/${appDataHash}`, method: 'GET' }, contextOverride)
}

uploadAppData(
appDataHash: AppDataHash,
fullAppData: string,
contextOverride: PartialApiContext = {}
): Promise<AppDataDocument> {
return this.fetch(
{ path: `/api/v1/app_data/${appDataHash}`, method: 'PUT', body: { fullAppData } },
contextOverride
)
}

getSolverCompetition(auctionId: number, contextOverride?: PartialApiContext): Promise<SolverCompetitionResponse>

getSolverCompetition(txHash: string, contextOverride?: PartialApiContext): Promise<SolverCompetitionResponse>

getSolverCompetition(
auctionIdorTx: number | string,
contextOverride: PartialApiContext = {}
): Promise<SolverCompetitionResponse> {
return this.fetch(
{
path: `/api/v1/solver_competition${typeof auctionIdorTx === 'string' ? '/by_tx_hash' : ''}/${auctionIdorTx}`,
method: 'GET',
},
contextOverride
)
}

getOrderLink(uid: UID, contextOverride?: PartialApiContext): string {
const { chainId, env } = this.getContextWithOverride(contextOverride)
Expand Down
3 changes: 2 additions & 1 deletion src/order-book/generated/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@
/* eslint-disable */

export type { Address } from './models/Address';
export type { AppDataDocument } from './models/AppDataDocument';
export type { AppDataHash } from './models/AppDataHash';
export type { Auction } from './models/Auction';
export type { AuctionPrices } from './models/AuctionPrices';
export type { BackendAppData } from './models/BackendAppData';
export type { BigUint } from './models/BigUint';
export { BuyTokenDestination } from './models/BuyTokenDestination';
export type { CallData } from './models/CallData';
Expand Down Expand Up @@ -34,6 +34,7 @@ export type { OrderQuoteValidity } from './models/OrderQuoteValidity';
export { OrderStatus } from './models/OrderStatus';
export type { PreSignature } from './models/PreSignature';
export { PriceQuality } from './models/PriceQuality';
export type { ProtocolAppData } from './models/ProtocolAppData';
export { ReplaceOrderError } from './models/ReplaceOrderError';
export { SellTokenSource } from './models/SellTokenSource';
export type { Signature } from './models/Signature';
Expand Down
17 changes: 17 additions & 0 deletions src/order-book/generated/models/AppDataDocument.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
/* istanbul ignore file */
/* tslint:disable */
/* eslint-disable */

/**
* An `appData` document that is registered with the API.
*/
export type AppDataDocument = {
/**
* The string encoding of a JSON object representing some `appData`. The
* format of the JSON expected in the `appData` field is defined
* [here](https://github.com/cowprotocol/app-data).
*
*/
fullAppData?: string;
};

2 changes: 2 additions & 0 deletions src/order-book/generated/models/OrderParameters.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import type { AppDataHash } from './AppDataHash';
import type { BuyTokenDestination } from './BuyTokenDestination';
import type { OrderKind } from './OrderKind';
import type { SellTokenSource } from './SellTokenSource';
import type { SigningScheme } from './SigningScheme';
import type { TokenAmount } from './TokenAmount';

/**
Expand Down Expand Up @@ -54,5 +55,6 @@ export type OrderParameters = {
partiallyFillable: boolean;
sellTokenBalance?: SellTokenSource;
buyTokenBalance?: BuyTokenDestination;
signingScheme?: SigningScheme;
};

7 changes: 6 additions & 1 deletion src/order-book/generated/models/PriceQuality.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,15 @@
/**
* How good should the price estimate be?
*
* **NOTE**: Orders are supposed to be created from `optimal` price estimates.
* Fast: The price estimate is chosen among the fastest N price estimates.
* Optimal: The price estimate is chosen among all price estimates.
* Verified: The price estimate is chosen among all verified/simulated price estimates.
*
* **NOTE**: Orders are supposed to be created from `verified` price estimates.
*
*/
export enum PriceQuality {
FAST = 'fast',
OPTIMAL = 'optimal',
VERIFIED = 'verified',
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,6 @@
/* tslint:disable */
/* eslint-disable */

export type BackendAppData = {
export type ProtocolAppData = {
};

Loading

0 comments on commit ad0c108

Please sign in to comment.