@cowprotocol/cow-sdk 0.0.8-RC.0 → 0.0.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (56) hide show
  1. package/README.md +102 -23
  2. package/dist/CowSdk.d.ts +2 -1
  3. package/dist/api/cow/index.d.ts +1 -1
  4. package/dist/api/cow/types.d.ts +34 -1
  5. package/dist/api/cow-subgraph/graphql.d.ts +2603 -0
  6. package/dist/api/cow-subgraph/index.d.ts +17 -0
  7. package/dist/api/cow-subgraph/queries.d.ts +3 -0
  8. package/dist/api/index.d.ts +1 -0
  9. package/dist/api/metadata/index.d.ts +3 -1
  10. package/dist/index.d.ts +3 -2
  11. package/dist/index.js +28 -1
  12. package/dist/index.js.map +1 -1
  13. package/dist/index.modern.js +28 -1
  14. package/dist/index.modern.js.map +1 -1
  15. package/dist/index.module.js +28 -1
  16. package/dist/index.module.js.map +1 -1
  17. package/dist/utils/context.d.ts +12 -3
  18. package/dist/utils/ipfs.d.ts +8 -0
  19. package/package.json +27 -6
  20. package/.babelrc +0 -4
  21. package/.eslintrc.json +0 -15
  22. package/.github/workflows/build.yml +0 -50
  23. package/.github/workflows/lint.yml +0 -19
  24. package/.github/workflows/publish.yml +0 -20
  25. package/.github/workflows/test.yml +0 -47
  26. package/.nvmrc +0 -1
  27. package/.prettierignore +0 -1
  28. package/.prettierrc +0 -5
  29. package/COPYRIGHT.md +0 -13
  30. package/LICENSE-APACHE +0 -201
  31. package/LICENSE-MIT +0 -21
  32. package/babel.config.js +0 -3
  33. package/docs/images/CoW.png +0 -0
  34. package/src/CowSdk.ts +0 -53
  35. package/src/api/cow/errors/OperatorError.ts +0 -142
  36. package/src/api/cow/errors/QuoteError.ts +0 -115
  37. package/src/api/cow/index.ts +0 -367
  38. package/src/api/cow/types.ts +0 -82
  39. package/src/api/index.ts +0 -2
  40. package/src/api/metadata/index.ts +0 -37
  41. package/src/api/metadata/types.ts +0 -17
  42. package/src/constants/chains.ts +0 -11
  43. package/src/constants/index.ts +0 -16
  44. package/src/constants/tokens.ts +0 -16
  45. package/src/index.ts +0 -4
  46. package/src/schemas/appData.schema.json +0 -70
  47. package/src/types/index.ts +0 -6
  48. package/src/utils/appData.spec.ts +0 -109
  49. package/src/utils/appData.ts +0 -58
  50. package/src/utils/common.ts +0 -35
  51. package/src/utils/context.ts +0 -89
  52. package/src/utils/price.ts +0 -44
  53. package/src/utils/sign.ts +0 -224
  54. package/src/utils/tokens.ts +0 -12
  55. package/src/workflows/publish.sh +0 -49
  56. package/tsconfig.json +0 -17
@@ -1,142 +0,0 @@
1
- import log from 'loglevel'
2
- import { CowError, logPrefix } from '../../../utils/common'
3
-
4
- type ApiActionType = 'get' | 'create' | 'delete'
5
-
6
- export interface ApiErrorObject {
7
- errorType: ApiErrorCodes
8
- description: string
9
- data?: any
10
- }
11
-
12
- // Conforms to backend API
13
- // https://github.com/gnosis/gp-v2-services/blob/d932e11c9a2125fdba239530be7684799f694909/crates/orderbook/openapi.yml#L801
14
- // and
15
- // https://github.com/gnosis/gp-v2-services/blob/d932e11c9a2125fdba239530be7684799f694909/crates/orderbook/openapi.yml#L740
16
- export enum ApiErrorCodes {
17
- DuplicateOrder = 'DuplicateOrder',
18
- InvalidSignature = 'InvalidSignature',
19
- MissingOrderData = 'MissingOrderData',
20
- InsufficientValidTo = 'InsufficientValidTo',
21
- InsufficientAllowance = 'InsufficientAllowance',
22
- InsufficientBalance = 'InsufficientBalance',
23
- InsufficientFee = 'InsufficientFee',
24
- WrongOwner = 'WrongOwner',
25
- NotFound = 'NotFound',
26
- OrderNotFound = 'OrderNotFound',
27
- AlreadyCancelled = 'AlreadyCancelled',
28
- OrderFullyExecuted = 'OrderFullyExecuted',
29
- OrderExpired = 'OrderExpired',
30
- NoLiquidity = 'NoLiquidity',
31
- UnsupportedToken = 'UnsupportedToken',
32
- AmountIsZero = 'AmountIsZero',
33
- SellAmountDoesNotCoverFee = 'SellAmountDoesNotCoverFee',
34
- TransferEthToContract = 'TransferEthToContract',
35
- UNHANDLED_GET_ERROR = 'UNHANDLED_GET_ERROR',
36
- UNHANDLED_CREATE_ERROR = 'UNHANDLED_CREATE_ERROR',
37
- UNHANDLED_DELETE_ERROR = 'UNHANDLED_DELETE_ERROR',
38
- }
39
-
40
- export enum ApiErrorCodeDetails {
41
- DuplicateOrder = 'There was another identical order already submitted. Please try again.',
42
- InsufficientFee = "The signed fee is insufficient. It's possible that is higher now due to a change in the gas price, ether price, or the sell token price. Please try again to get an updated fee quote.",
43
- InvalidSignature = 'The order signature is invalid. Check whether your Wallet app supports off-chain signing.',
44
- MissingOrderData = 'The order has missing information',
45
- InsufficientValidTo = 'The order you are signing is already expired. This can happen if you set a short expiration in the settings and waited too long before signing the transaction. Please try again.',
46
- InsufficientAllowance = "The account doesn't have enough funds",
47
- InsufficientBalance = 'The account needs to approve the selling token in order to trade',
48
- WrongOwner = "The signature is invalid.\n\nIt's likely that the signing method provided by your wallet doesn't comply with the standards required by CowSwap.\n\nCheck whether your Wallet app supports off-chain signing (EIP-712 or ETHSIGN).",
49
- NotFound = 'Token pair selected has insufficient liquidity',
50
- OrderNotFound = 'The order you are trying to cancel does not exist',
51
- AlreadyCancelled = 'Order is already cancelled',
52
- OrderFullyExecuted = 'Order is already filled',
53
- OrderExpired = 'Order is expired',
54
- NoLiquidity = 'Token pair selected has insufficient liquidity',
55
- UnsupportedToken = 'One of the tokens you are trading is unsupported. Please read the FAQ for more info.',
56
- AmountIsZero = 'Amount is zero',
57
- SellAmountDoesNotCoverFee = 'Sell amount does not sufficiently cover the current fee',
58
- TransferEthToContract = 'Sending the native currency to smart contract wallets is not currently supported',
59
- UNHANDLED_GET_ERROR = 'Order fetch failed. This may be due to a server or network connectivity issue. Please try again later.',
60
- UNHANDLED_CREATE_ERROR = 'The order was not accepted by the network',
61
- UNHANDLED_DELETE_ERROR = 'The order cancellation was not accepted by the network',
62
- }
63
-
64
- function _mapActionToErrorDetail(action?: ApiActionType) {
65
- switch (action) {
66
- case 'get':
67
- return ApiErrorCodeDetails.UNHANDLED_GET_ERROR
68
- case 'create':
69
- return ApiErrorCodeDetails.UNHANDLED_CREATE_ERROR
70
- case 'delete':
71
- return ApiErrorCodeDetails.UNHANDLED_DELETE_ERROR
72
- default:
73
- log.error(
74
- logPrefix,
75
- '[OperatorError::_mapActionToErrorDetails] Uncaught error mapping error action type to server error. Please try again later.'
76
- )
77
- return 'Something failed. Please try again later.'
78
- }
79
- }
80
-
81
- export default class OperatorError extends CowError {
82
- name = 'OperatorError'
83
- description: ApiErrorObject['description']
84
-
85
- // Status 400 errors
86
- // https://github.com/gnosis/gp-v2-services/blob/9014ae55412a356e46343e051aefeb683cc69c41/orderbook/openapi.yml#L563
87
- static apiErrorDetails = ApiErrorCodeDetails
88
-
89
- public static async getErrorMessage(response: Response, action: ApiActionType) {
90
- try {
91
- const orderPostError: ApiErrorObject = await response.json()
92
-
93
- if (orderPostError.errorType) {
94
- const errorMessage = OperatorError.apiErrorDetails[orderPostError.errorType]
95
- // shouldn't fall through as this error constructor expects the error code to exist but just in case
96
- return errorMessage || orderPostError.errorType
97
- } else {
98
- log.error(logPrefix, 'Unknown reason for bad order submission', orderPostError)
99
- return orderPostError.description
100
- }
101
- } catch (error) {
102
- log.error(logPrefix, 'Error handling a 400 error. Likely a problem deserialising the JSON response')
103
- return _mapActionToErrorDetail(action)
104
- }
105
- }
106
- static async getErrorFromStatusCode(response: Response, action: 'create' | 'delete') {
107
- switch (response.status) {
108
- case 400:
109
- case 404:
110
- return this.getErrorMessage(response, action)
111
-
112
- case 403:
113
- return `The order cannot be ${action === 'create' ? 'accepted' : 'cancelled'}. Your account is deny-listed.`
114
-
115
- case 429:
116
- return `The order cannot be ${
117
- action === 'create' ? 'accepted. Too many order placements' : 'cancelled. Too many order cancellations'
118
- }. Please, retry in a minute`
119
-
120
- case 500:
121
- default:
122
- log.error(
123
- logPrefix,
124
- `[OperatorError::getErrorFromStatusCode] Error ${
125
- action === 'create' ? 'creating' : 'cancelling'
126
- } the order, status code:`,
127
- response.status || 'unknown'
128
- )
129
- return `Error ${action === 'create' ? 'creating' : 'cancelling'} the order`
130
- }
131
- }
132
- constructor(apiError: ApiErrorObject) {
133
- super(apiError.description, apiError.errorType)
134
-
135
- this.description = apiError.description
136
- this.message = ApiErrorCodeDetails[apiError.errorType]
137
- }
138
- }
139
-
140
- export function isValidOperatorError(error: any): error is OperatorError {
141
- return error instanceof OperatorError
142
- }
@@ -1,115 +0,0 @@
1
- import log from 'loglevel'
2
- import { CowError, logPrefix } from '../../../utils/common'
3
- import { ApiErrorCodes, ApiErrorObject } from './OperatorError'
4
-
5
- export interface GpQuoteErrorObject {
6
- errorType: GpQuoteErrorCodes
7
- description: string
8
- data?: any
9
- }
10
-
11
- // Conforms to backend API
12
- // https://github.com/gnosis/gp-v2-services/blob/0bd5f7743bebaa5acd3be13e35ede2326a096f14/orderbook/openapi.yml#L562
13
- export enum GpQuoteErrorCodes {
14
- UnsupportedToken = 'UnsupportedToken',
15
- InsufficientLiquidity = 'InsufficientLiquidity',
16
- FeeExceedsFrom = 'FeeExceedsFrom',
17
- ZeroPrice = 'ZeroPrice',
18
- UNHANDLED_ERROR = 'UNHANDLED_ERROR',
19
- }
20
-
21
- export enum GpQuoteErrorDetails {
22
- UnsupportedToken = 'One of the tokens you are trading is unsupported. Please read the FAQ for more info.',
23
- InsufficientLiquidity = 'Token pair selected has insufficient liquidity',
24
- FeeExceedsFrom = 'Current fee exceeds entered "from" amount',
25
- ZeroPrice = 'Quoted price is zero. This is likely due to a significant price difference between the two tokens. Please try increasing amounts.',
26
- UNHANDLED_ERROR = 'Quote fetch failed. This may be due to a server or network connectivity issue. Please try again later.',
27
- }
28
-
29
- export function mapOperatorErrorToQuoteError(error?: ApiErrorObject): GpQuoteErrorObject {
30
- switch (error?.errorType) {
31
- case ApiErrorCodes.NotFound:
32
- case ApiErrorCodes.NoLiquidity:
33
- return {
34
- errorType: GpQuoteErrorCodes.InsufficientLiquidity,
35
- description: GpQuoteErrorDetails.InsufficientLiquidity,
36
- }
37
-
38
- case ApiErrorCodes.SellAmountDoesNotCoverFee:
39
- return {
40
- errorType: GpQuoteErrorCodes.FeeExceedsFrom,
41
- description: GpQuoteErrorDetails.FeeExceedsFrom,
42
- data: error?.data,
43
- }
44
-
45
- case ApiErrorCodes.UnsupportedToken:
46
- return {
47
- errorType: GpQuoteErrorCodes.UnsupportedToken,
48
- description: error.description,
49
- }
50
- case ApiErrorCodes.SellAmountDoesNotCoverFee:
51
- return {
52
- errorType: GpQuoteErrorCodes.FeeExceedsFrom,
53
- description: error.description,
54
- }
55
- default:
56
- return { errorType: GpQuoteErrorCodes.UNHANDLED_ERROR, description: GpQuoteErrorDetails.UNHANDLED_ERROR }
57
- }
58
- }
59
-
60
- export default class GpQuoteError extends CowError {
61
- name = 'QuoteErrorObject'
62
- description: string
63
- // any data attached
64
- data?: any
65
-
66
- // Status 400 errors
67
- // https://github.com/gnosis/gp-v2-services/blob/9014ae55412a356e46343e051aefeb683cc69c41/orderbook/openapi.yml#L563
68
- static quoteErrorDetails = GpQuoteErrorDetails
69
-
70
- public static async getErrorMessage(response: Response) {
71
- try {
72
- const orderPostError: GpQuoteErrorObject = await response.json()
73
-
74
- if (orderPostError.errorType) {
75
- const errorMessage = GpQuoteError.quoteErrorDetails[orderPostError.errorType]
76
- // shouldn't fall through as this error constructor expects the error code to exist but just in case
77
- return errorMessage || orderPostError.errorType
78
- } else {
79
- log.error(logPrefix, 'Unknown reason for bad quote fetch', orderPostError)
80
- return orderPostError.description
81
- }
82
- } catch (error) {
83
- log.error(logPrefix, 'Error handling 400/404 error. Likely a problem deserialising the JSON response')
84
- return GpQuoteError.quoteErrorDetails.UNHANDLED_ERROR
85
- }
86
- }
87
-
88
- static async getErrorFromStatusCode(response: Response) {
89
- switch (response.status) {
90
- case 400:
91
- case 404:
92
- return this.getErrorMessage(response)
93
-
94
- case 500:
95
- default:
96
- log.error(
97
- logPrefix,
98
- '[QuoteError::getErrorFromStatusCode] Error fetching quote, status code:',
99
- response.status || 'unknown'
100
- )
101
- return 'Error fetching quote'
102
- }
103
- }
104
- constructor(quoteError: GpQuoteErrorObject) {
105
- super(quoteError.description, quoteError.errorType)
106
-
107
- this.description = quoteError.description
108
- this.message = GpQuoteError.quoteErrorDetails[quoteError.errorType]
109
- this.data = quoteError?.data
110
- }
111
- }
112
-
113
- export function isValidQuoteError(error: any): error is GpQuoteError {
114
- return error instanceof GpQuoteError
115
- }
@@ -1,367 +0,0 @@
1
- import log from 'loglevel'
2
- import fetch from 'cross-fetch'
3
- import { OrderKind, QuoteQuery } from '@gnosis.pm/gp-v2-contracts'
4
- import { SupportedChainId as ChainId } from '../../constants/chains'
5
- import { getSigningSchemeApiValue, OrderCreation } from '../../utils/sign'
6
- import OperatorError, { ApiErrorCodeDetails, ApiErrorCodes, ApiErrorObject } from './errors/OperatorError'
7
- import QuoteError, {
8
- GpQuoteErrorCodes,
9
- GpQuoteErrorObject,
10
- mapOperatorErrorToQuoteError,
11
- GpQuoteErrorDetails,
12
- } from './errors/QuoteError'
13
- import { toErc20Address } from '../../utils/tokens'
14
- import { FeeQuoteParams, PriceInformation, PriceQuoteParams, SimpleGetQuoteResponse } from '../../utils/price'
15
-
16
- import { ZERO_ADDRESS } from '../../constants'
17
- import {
18
- GetOrdersParams,
19
- GetTradesParams,
20
- OrderCancellationParams,
21
- OrderID,
22
- OrderMetaData,
23
- ProfileData,
24
- TradeMetaData,
25
- } from './types'
26
- import { CowError, logPrefix, objectToQueryString } from '../../utils/common'
27
- import { Context } from '../../utils/context'
28
-
29
- function getGnosisProtocolUrl(isDev: boolean): Partial<Record<ChainId, string>> {
30
- if (isDev) {
31
- return {
32
- [ChainId.MAINNET]: 'https://barn.api.cow.fi/mainnet/api',
33
- [ChainId.RINKEBY]: 'https://barn.api.cow.fi/rinkeby/api',
34
- [ChainId.GNOSIS_CHAIN]: 'https://barn.api.cow.fi/xdai/api',
35
- }
36
- }
37
-
38
- return {
39
- [ChainId.MAINNET]: 'https://api.cow.fi/mainnet/api',
40
- [ChainId.RINKEBY]: 'https://api.cow.fi/rinkeby/api',
41
- [ChainId.GNOSIS_CHAIN]: 'https://api.cow.fi/xdai/api',
42
- }
43
- }
44
-
45
- function getProfileUrl(isDev: boolean): Partial<Record<ChainId, string>> {
46
- if (isDev) {
47
- return {
48
- [ChainId.MAINNET]: 'https://barn.api.cow.fi/affiliate/api',
49
- }
50
- }
51
-
52
- return {
53
- [ChainId.MAINNET]: 'https://api.cow.fi/affiliate/api',
54
- }
55
- }
56
-
57
- const UNHANDLED_QUOTE_ERROR: GpQuoteErrorObject = {
58
- errorType: GpQuoteErrorCodes.UNHANDLED_ERROR,
59
- description: GpQuoteErrorDetails.UNHANDLED_ERROR,
60
- }
61
-
62
- const UNHANDLED_ORDER_ERROR: ApiErrorObject = {
63
- errorType: ApiErrorCodes.UNHANDLED_CREATE_ERROR,
64
- description: ApiErrorCodeDetails.UNHANDLED_CREATE_ERROR,
65
- }
66
-
67
- async function _handleQuoteResponse<T = any, P extends QuoteQuery = QuoteQuery>(
68
- response: Response,
69
- params?: P
70
- ): Promise<T> {
71
- if (!response.ok) {
72
- const errorObj: ApiErrorObject = await response.json()
73
-
74
- // we need to map the backend error codes to match our own for quotes
75
- const mappedError = mapOperatorErrorToQuoteError(errorObj)
76
- const quoteError = new QuoteError(mappedError)
77
-
78
- if (params) {
79
- const { sellToken, buyToken } = params
80
- log.error(logPrefix, `Error querying fee from API - sellToken: ${sellToken}, buyToken: ${buyToken}`)
81
- }
82
-
83
- throw quoteError
84
- } else {
85
- return response.json()
86
- }
87
- }
88
-
89
- export class CowApi {
90
- context: Context
91
-
92
- API_NAME = 'CoW Protocol'
93
-
94
- constructor(context: Context) {
95
- this.context = context
96
- }
97
-
98
- get DEFAULT_HEADERS() {
99
- return { 'Content-Type': 'application/json', 'X-AppId': this.context.appDataHash }
100
- }
101
-
102
- get API_BASE_URL() {
103
- return getGnosisProtocolUrl(this.context.isDevEnvironment)
104
- }
105
-
106
- get PROFILE_API_BASE_URL(): Partial<Record<ChainId, string>> {
107
- return getProfileUrl(this.context.isDevEnvironment)
108
- }
109
-
110
- async getProfileData(address: string): Promise<ProfileData | null> {
111
- const chainId = await this.context.chainId
112
- log.debug(logPrefix, `[api:${this.API_NAME}] Get profile data for`, chainId, address)
113
- if (chainId !== ChainId.MAINNET) {
114
- log.info(logPrefix, 'Profile data is only available for mainnet')
115
- return null
116
- }
117
-
118
- const response = await this.getProfile(`/profile/${address}`)
119
-
120
- if (!response.ok) {
121
- const errorResponse = await response.json()
122
- log.error(logPrefix, errorResponse)
123
- throw new CowError(errorResponse?.description)
124
- } else {
125
- return response.json()
126
- }
127
- }
128
-
129
- async getTrades(params: GetTradesParams): Promise<TradeMetaData[]> {
130
- const { owner, limit, offset } = params
131
- const qsParams = objectToQueryString({ owner, limit, offset })
132
- const chainId = await this.context.chainId
133
- log.debug(logPrefix, '[util:operator] Get trades for', chainId, owner, { limit, offset })
134
- try {
135
- const response = await this.get(`/trades${qsParams}`)
136
-
137
- if (!response.ok) {
138
- const errorResponse = await response.json()
139
- throw new CowError(errorResponse)
140
- } else {
141
- return response.json()
142
- }
143
- } catch (error) {
144
- log.error(logPrefix, 'Error getting trades:', error)
145
- throw new CowError('Error getting trades: ' + error)
146
- }
147
- }
148
-
149
- async getOrders(params: GetOrdersParams): Promise<OrderMetaData[]> {
150
- const { owner, limit = 1000, offset = 0 } = params
151
- const queryString = objectToQueryString({ limit, offset })
152
- const chainId = await this.context.chainId
153
- log.debug(logPrefix, `[api:${this.API_NAME}] Get orders for `, chainId, owner, limit, offset)
154
-
155
- try {
156
- const response = await this.get(`/account/${owner}/orders/${queryString}`)
157
-
158
- if (!response.ok) {
159
- const errorResponse: ApiErrorObject = await response.json()
160
- throw new OperatorError(errorResponse)
161
- } else {
162
- return response.json()
163
- }
164
- } catch (error) {
165
- log.error(logPrefix, 'Error getting orders information:', error)
166
- throw new OperatorError(UNHANDLED_ORDER_ERROR)
167
- }
168
- }
169
-
170
- async getTxOrders(txHash: string): Promise<OrderMetaData[]> {
171
- const chainId = await this.context.chainId
172
- log.debug(`[api:${this.API_NAME}] Get tx orders for `, chainId, txHash)
173
-
174
- try {
175
- const response = await this.get(`/transactions/${txHash}/orders`)
176
-
177
- if (!response.ok) {
178
- const errorResponse: ApiErrorObject = await response.json()
179
- throw new OperatorError(errorResponse)
180
- } else {
181
- return response.json()
182
- }
183
- } catch (error) {
184
- log.error('Error getting transaction orders information:', error)
185
- if (error instanceof OperatorError) throw error
186
- throw new OperatorError(UNHANDLED_ORDER_ERROR)
187
- }
188
- }
189
-
190
- async getOrder(orderId: string): Promise<OrderMetaData | null> {
191
- const chainId = await this.context.chainId
192
- log.debug(logPrefix, `[api:${this.API_NAME}] Get order for `, chainId, orderId)
193
- try {
194
- const response = await this.get(`/orders/${orderId}`)
195
-
196
- if (!response.ok) {
197
- const errorResponse: ApiErrorObject = await response.json()
198
- throw new OperatorError(errorResponse)
199
- } else {
200
- return response.json()
201
- }
202
- } catch (error) {
203
- log.error(logPrefix, 'Error getting order information:', error)
204
- throw new OperatorError(UNHANDLED_ORDER_ERROR)
205
- }
206
- }
207
-
208
- async getPriceQuoteLegacy(params: PriceQuoteParams): Promise<PriceInformation | null> {
209
- const { baseToken, quoteToken, amount, kind } = params
210
- const chainId = await this.context.chainId
211
- log.debug(logPrefix, `[api:${this.API_NAME}] Get price from API`, params, 'for', chainId)
212
-
213
- const response = await this.get(
214
- `/markets/${toErc20Address(baseToken, chainId)}-${toErc20Address(quoteToken, chainId)}/${kind}/${amount}`
215
- ).catch((error) => {
216
- log.error(logPrefix, 'Error getting price quote:', error)
217
- throw new QuoteError(UNHANDLED_QUOTE_ERROR)
218
- })
219
-
220
- return _handleQuoteResponse<PriceInformation | null>(response)
221
- }
222
-
223
- async getQuote(params: FeeQuoteParams): Promise<SimpleGetQuoteResponse> {
224
- const chainId = await this.context.chainId
225
- const quoteParams = this.mapNewToLegacyParams(params, chainId)
226
- const response = await this.post('/quote', quoteParams)
227
-
228
- return _handleQuoteResponse<SimpleGetQuoteResponse>(response)
229
- }
230
-
231
- async sendSignedOrderCancellation(params: OrderCancellationParams): Promise<void> {
232
- const { cancellation, owner: from } = params
233
- const chainId = await this.context.chainId
234
- log.debug(logPrefix, `[api:${this.API_NAME}] Delete signed order for network`, chainId, cancellation)
235
-
236
- const response = await this.delete(`/orders/${cancellation.orderUid}`, {
237
- signature: cancellation.signature,
238
- signingScheme: getSigningSchemeApiValue(cancellation.signingScheme),
239
- from,
240
- })
241
-
242
- if (!response.ok) {
243
- // Raise an exception
244
- const errorMessage = await OperatorError.getErrorFromStatusCode(response, 'delete')
245
- throw new CowError(errorMessage)
246
- }
247
-
248
- log.debug(logPrefix, `[api:${this.API_NAME}] Cancelled order`, cancellation.orderUid, chainId)
249
- }
250
-
251
- async sendOrder(params: { order: Omit<OrderCreation, 'appData'>; owner: string }): Promise<OrderID> {
252
- const fullOrder: OrderCreation = { ...params.order, appData: this.context.appDataHash }
253
- const chainId = await this.context.chainId
254
- const { owner } = params
255
- log.debug(logPrefix, `[api:${this.API_NAME}] Post signed order for network`, chainId, fullOrder)
256
-
257
- // Call API
258
- const response = await this.post(`/orders`, {
259
- ...fullOrder,
260
- signingScheme: getSigningSchemeApiValue(fullOrder.signingScheme),
261
- from: owner,
262
- })
263
-
264
- // Handle response
265
- if (!response.ok) {
266
- // Raise an exception
267
- const errorMessage = await OperatorError.getErrorFromStatusCode(response, 'create')
268
- throw new CowError(errorMessage)
269
- }
270
-
271
- const uid = (await response.json()) as string
272
- log.debug(logPrefix, `[api:${this.API_NAME}] Success posting the signed order`, uid)
273
- return uid
274
- }
275
-
276
- getOrderLink(orderId: OrderID): string {
277
- const baseUrl = this.getApiBaseUrl()
278
-
279
- return baseUrl + `/orders/${orderId}`
280
- }
281
-
282
- private mapNewToLegacyParams(params: FeeQuoteParams, chainId: ChainId): QuoteQuery {
283
- const { amount, kind, userAddress, receiver, validTo, sellToken, buyToken } = params
284
- const fallbackAddress = userAddress || ZERO_ADDRESS
285
-
286
- const baseParams = {
287
- sellToken: toErc20Address(sellToken, chainId),
288
- buyToken: toErc20Address(buyToken, chainId),
289
- from: fallbackAddress,
290
- receiver: receiver || fallbackAddress,
291
- appData: this.context.appDataHash,
292
- validTo,
293
- partiallyFillable: false,
294
- }
295
-
296
- const finalParams: QuoteQuery =
297
- kind === OrderKind.SELL
298
- ? {
299
- kind: OrderKind.SELL,
300
- sellAmountBeforeFee: amount,
301
- ...baseParams,
302
- }
303
- : {
304
- kind: OrderKind.BUY,
305
- buyAmountAfterFee: amount,
306
- ...baseParams,
307
- }
308
-
309
- return finalParams
310
- }
311
-
312
- private async getApiBaseUrl(): Promise<string> {
313
- const chainId = await this.context.chainId
314
- const baseUrl = this.API_BASE_URL[chainId]
315
-
316
- if (!baseUrl) {
317
- throw new CowError(`Unsupported Network. The ${this.API_NAME} API is not deployed in the Network ` + chainId)
318
- } else {
319
- return baseUrl + '/v1'
320
- }
321
- }
322
-
323
- private async getProfileApiBaseUrl(): Promise<string> {
324
- const chainId = await this.context.chainId
325
- const baseUrl = this.PROFILE_API_BASE_URL[chainId]
326
-
327
- if (!baseUrl) {
328
- throw new CowError(`Unsupported Network. The ${this.API_NAME} API is not deployed in the Network ` + chainId)
329
- } else {
330
- return baseUrl + '/v1'
331
- }
332
- }
333
-
334
- private async fetch(url: string, method: 'GET' | 'POST' | 'DELETE', data?: any): Promise<Response> {
335
- const baseUrl = await this.getApiBaseUrl()
336
- return fetch(baseUrl + url, {
337
- headers: this.DEFAULT_HEADERS,
338
- method,
339
- body: data !== undefined ? JSON.stringify(data) : data,
340
- })
341
- }
342
-
343
- private async fetchProfile(url: string, method: 'GET' | 'POST' | 'DELETE', data?: any): Promise<Response> {
344
- const baseUrl = await this.getProfileApiBaseUrl()
345
- return fetch(baseUrl + url, {
346
- headers: this.DEFAULT_HEADERS,
347
- method,
348
- body: data !== undefined ? JSON.stringify(data) : data,
349
- })
350
- }
351
-
352
- private post(url: string, data: any): Promise<Response> {
353
- return this.fetch(url, 'POST', data)
354
- }
355
-
356
- private get(url: string): Promise<Response> {
357
- return this.fetch(url, 'GET')
358
- }
359
-
360
- private getProfile(url: string): Promise<Response> {
361
- return this.fetchProfile(url, 'GET')
362
- }
363
-
364
- private delete(url: string, data: any): Promise<Response> {
365
- return this.fetch(url, 'DELETE', data)
366
- }
367
- }