Skip to content

Commit 9a97711

Browse files
Feature/DF-18812 add vwap endpoint to blocksize capital ea (#3025)
* DF-18812 blocksize capital vwap endpoint * add changeset * update readme * review fix for fixedvwap types * Include error messages in logs --------- Co-authored-by: Alec Gard <[email protected]>
1 parent 878c80c commit 9a97711

File tree

13 files changed

+296
-90
lines changed

13 files changed

+296
-90
lines changed

.changeset/young-tomatoes-float.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@chainlink/blocksize-capital-adapter': minor
3+
---
4+
5+
Add vwap endpoint to blocksize-capital EA

packages/sources/blocksize-capital/README.md

+30-3
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,9 @@ There are no rate limits for this adapter.
2121

2222
## Input Parameters
2323

24-
| Required? | Name | Description | Type | Options | Default |
25-
| :-------: | :------: | :-----------------: | :----: | :------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :-----: |
26-
| | endpoint | The endpoint to use | string | [crypto-lwba](#crypto-lwba-endpoint), [crypto](#price-endpoint), [crypto_lwba](#crypto-lwba-endpoint), [cryptolwba](#crypto-lwba-endpoint), [price](#price-endpoint) | `price` |
24+
| Required? | Name | Description | Type | Options | Default |
25+
| :-------: | :------: | :-----------------: | :----: | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :-----: |
26+
| | endpoint | The endpoint to use | string | [crypto-lwba](#crypto-lwba-endpoint), [crypto-vwap](#vwap-endpoint), [crypto](#price-endpoint), [crypto_lwba](#crypto-lwba-endpoint), [cryptolwba](#crypto-lwba-endpoint), [price](#price-endpoint), [vwap](#vwap-endpoint) | `price` |
2727

2828
## Price Endpoint
2929

@@ -79,4 +79,31 @@ Request:
7979

8080
---
8181

82+
## Vwap Endpoint
83+
84+
Supported names for this endpoint are: `crypto-vwap`, `vwap`.
85+
86+
### Input Params
87+
88+
| Required? | Name | Aliases | Description | Type | Options | Default | Depends On | Not Valid With |
89+
| :-------: | :---: | :------------: | :--------------------------------------------: | :----: | :-----: | :-----: | :--------: | :------------: |
90+
|| base | `coin`, `from` | The symbol of symbols of the currency to query | string | | | | |
91+
|| quote | `market`, `to` | The symbol of the currency to convert to | string | | | | |
92+
93+
### Example
94+
95+
Request:
96+
97+
```json
98+
{
99+
"data": {
100+
"endpoint": "vwap",
101+
"base": "ETH",
102+
"quote": "USD"
103+
}
104+
}
105+
```
106+
107+
---
108+
82109
MIT License
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
export { endpoint as price } from './price'
22
export { endpoint as cryptolwba } from './crypto-lwba'
3+
export { endpoint as vwap } from './vwap'
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import {
2+
PriceEndpoint,
3+
priceEndpointInputParametersDefinition,
4+
} from '@chainlink/external-adapter-framework/adapter'
5+
import { InputParameters } from '@chainlink/external-adapter-framework/validation'
6+
import { config } from '../config'
7+
import { transport } from '../transport/vwap'
8+
import { SingleNumberResultResponse } from '@chainlink/external-adapter-framework/util'
9+
10+
const inputParameters = new InputParameters(priceEndpointInputParametersDefinition, [
11+
{
12+
base: 'AMPL',
13+
quote: 'USD',
14+
},
15+
])
16+
17+
export type BaseEndpointTypes = {
18+
Parameters: typeof inputParameters.definition
19+
Settings: typeof config.settings
20+
Response: SingleNumberResultResponse
21+
}
22+
23+
export const endpoint = new PriceEndpoint({
24+
name: 'vwap',
25+
aliases: ['crypto-vwap'],
26+
transport,
27+
inputParameters,
28+
})

packages/sources/blocksize-capital/src/index.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
import { expose, ServerInstance } from '@chainlink/external-adapter-framework'
22
import { PriceAdapter } from '@chainlink/external-adapter-framework/adapter'
33
import { config } from './config'
4-
import { cryptolwba, price } from './endpoint'
4+
import { cryptolwba, price, vwap } from './endpoint'
55

66
export const adapter = new PriceAdapter({
77
name: 'BLOCKSIZE_CAPITAL',
8-
endpoints: [price, cryptolwba],
8+
endpoints: [price, cryptolwba, vwap],
99
defaultEndpoint: price.name,
1010
config,
1111
})

packages/sources/blocksize-capital/src/transport/crypto-lwba.ts

+11-17
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,16 @@
11
import { BaseEndpointTypes } from '../endpoint/crypto-lwba'
22
import { WebsocketReverseMappingTransport } from '@chainlink/external-adapter-framework/transports/websocket'
33
import { makeLogger, ProviderResult } from '@chainlink/external-adapter-framework/util'
4-
import { BaseMessage, blocksizeDefaultWebsocketOpenHandler } from './utils'
4+
import {
5+
BaseMessage,
6+
blocksizeDefaultUnsubscribeMessageBuilder,
7+
blocksizeDefaultWebsocketOpenHandler,
8+
buildBlocksizeWebsocketTickersMessage,
9+
} from './utils'
510

611
const logger = makeLogger('BlocksizeCapitalLwbaWebsocketEndpoint')
712

8-
export interface Message extends BaseMessage {
13+
export interface BidAskMessage extends BaseMessage {
914
method: 'bidask'
1015
params: {
1116
updates: {
@@ -22,7 +27,7 @@ export interface Message extends BaseMessage {
2227

2328
export type WsTransportTypes = BaseEndpointTypes & {
2429
Provider: {
25-
WsMessage: Message
30+
WsMessage: BidAskMessage
2631
}
2732
}
2833

@@ -75,20 +80,9 @@ export const transport: WebsocketReverseMappingTransport<WsTransportTypes, strin
7580
subscribeMessage: (params) => {
7681
const pair = `${params.base}${params.quote}`.toUpperCase()
7782
transport.setReverseMapping(pair, params)
78-
return {
79-
jsonrpc: '2.0',
80-
method: 'bidask_subscribe',
81-
params: { tickers: [pair] },
82-
}
83-
},
84-
85-
unsubscribeMessage: (params) => {
86-
const pair = `${params.base}${params.quote}`.toUpperCase()
87-
return {
88-
jsonrpc: '2.0',
89-
method: 'bidask_unsubscribe',
90-
params: { tickers: [pair] },
91-
}
83+
return buildBlocksizeWebsocketTickersMessage('bidask_subscribe', pair)
9284
},
85+
unsubscribeMessage: (params) =>
86+
blocksizeDefaultUnsubscribeMessageBuilder(params.base, params.quote, 'bidask_unsubscribe'),
9387
},
9488
})
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,24 @@
11
import { BaseEndpointTypes } from '../endpoint/price'
22
import { WebsocketReverseMappingTransport } from '@chainlink/external-adapter-framework/transports/websocket'
3-
import { makeLogger, ProviderResult } from '@chainlink/external-adapter-framework/util'
4-
import { BaseMessage, blocksizeDefaultWebsocketOpenHandler } from './utils'
3+
import {
4+
BaseMessage,
5+
blocksizeDefaultUnsubscribeMessageBuilder,
6+
blocksizeDefaultWebsocketOpenHandler,
7+
buildBlocksizeWebsocketTickersMessage,
8+
handlePriceUpdates,
9+
VwapUpdate,
10+
} from './utils'
511

6-
const logger = makeLogger('BlocksizeCapitalWebsocketEndpoint')
7-
8-
export interface Message extends BaseMessage {
12+
export interface VwapMessage extends BaseMessage {
913
method: 'vwap'
1014
params: {
11-
updates: {
12-
ticker: string
13-
price?: number
14-
size?: number
15-
volume?: number
16-
ts: number
17-
}[]
15+
updates: VwapUpdate[]
1816
}
1917
}
2018

2119
export type WsTransportTypes = BaseEndpointTypes & {
2220
Provider: {
23-
WsMessage: Message
21+
WsMessage: VwapMessage
2422
}
2523
}
2624

@@ -33,58 +31,16 @@ export const transport: WebsocketReverseMappingTransport<WsTransportTypes, strin
3331
message: (message) => {
3432
if (message.method !== 'vwap') return []
3533
const updates = message.params.updates
36-
const results: ProviderResult<WsTransportTypes>[] = []
37-
for (const update of updates) {
38-
const params = transport.getReverseMapping(update.ticker)
39-
if (!params) {
40-
continue
41-
}
42-
if (!update.price) {
43-
const errorMessage = `The data provider didn't return any value for ${params.base}/${params.quote}`
44-
logger.info(errorMessage)
45-
results.push({
46-
params,
47-
response: {
48-
statusCode: 502,
49-
errorMessage,
50-
},
51-
})
52-
} else {
53-
results.push({
54-
params,
55-
response: {
56-
result: update.price,
57-
data: {
58-
result: update.price,
59-
},
60-
timestamps: {
61-
providerIndicatedTimeUnixMs: update.ts,
62-
},
63-
},
64-
})
65-
}
66-
}
67-
return results
34+
return handlePriceUpdates(updates, transport)
6835
},
6936
},
7037
builders: {
7138
subscribeMessage: (params) => {
7239
const pair = `${params.base}${params.quote}`.toUpperCase()
7340
transport.setReverseMapping(pair, params)
74-
return {
75-
jsonrpc: '2.0',
76-
method: 'vwap_subscribe',
77-
params: { tickers: [pair] },
78-
}
79-
},
80-
81-
unsubscribeMessage: (params) => {
82-
const pair = `${params.base}${params.quote}`.toUpperCase()
83-
return {
84-
jsonrpc: '2.0',
85-
method: 'vwap_unsubscribe',
86-
params: { tickers: [pair] },
87-
}
41+
return buildBlocksizeWebsocketTickersMessage('vwap_subscribe', pair)
8842
},
43+
unsubscribeMessage: (params) =>
44+
blocksizeDefaultUnsubscribeMessageBuilder(params.base, params.quote, 'vwap_unsubscribe'),
8945
},
9046
})
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,49 @@
1-
import { makeLogger } from '@chainlink/external-adapter-framework/util'
1+
import { WebsocketReverseMappingTransport } from '@chainlink/external-adapter-framework/transports'
2+
import { ProviderResult, makeLogger } from '@chainlink/external-adapter-framework/util'
3+
import { WsTransportTypes as PriceWsTransportTypes } from './price'
4+
import { WsTransportTypes as VwapWsTransportTypes } from './vwap'
25

36
const logger = makeLogger('BlocksizeCapitalTransportUtils')
47

58
export interface BaseMessage {
69
jsonrpc: string
710
id?: string | number | null
8-
method: string
11+
method?: string
12+
}
13+
14+
export type VwapUpdate = {
15+
ticker: string
16+
price?: number
17+
size?: number
18+
volume?: number
19+
ts: number
20+
}
21+
22+
export type ProviderParams = {
23+
tickers?: string[]
24+
api_key?: string
25+
}
26+
27+
const buildBlocksizeWebsocketMessage = (method: string, params: ProviderParams): unknown => {
28+
return {
29+
jsonrpc: '2.0',
30+
method: method,
31+
params: params,
32+
}
33+
}
34+
35+
export const buildBlocksizeWebsocketAuthMessage = (apiKey: string) =>
36+
buildBlocksizeWebsocketMessage('authentication_logon', { api_key: apiKey })
37+
export const buildBlocksizeWebsocketTickersMessage = (method: string, pair: string) =>
38+
buildBlocksizeWebsocketMessage(method, { tickers: [pair] })
39+
40+
export const blocksizeDefaultUnsubscribeMessageBuilder = (
41+
base: string,
42+
quote: string,
43+
method: string,
44+
): unknown => {
45+
const pair = `${base}${quote}`.toUpperCase()
46+
return buildBlocksizeWebsocketTickersMessage(method, pair)
947
}
1048

1149
// use as open handler for standard WS connections
@@ -20,14 +58,48 @@ export const blocksizeDefaultWebsocketOpenHandler = (
2058
logger.debug('Got logged in response, connection is ready')
2159
resolve()
2260
} else {
23-
reject(new Error('Failed to make WS connection'))
61+
reject(new Error(`Failed to make WS connection: ${JSON.stringify(parsed)}`))
2462
}
2563
})
26-
const options = {
27-
jsonrpc: '2.0',
28-
method: 'authentication_logon',
29-
params: { api_key: apiKey },
30-
}
31-
connection.send(JSON.stringify(options))
64+
const message = buildBlocksizeWebsocketAuthMessage(apiKey)
65+
connection.send(JSON.stringify(message))
3266
})
3367
}
68+
69+
export const handlePriceUpdates = (
70+
updates: VwapUpdate[],
71+
transport: WebsocketReverseMappingTransport<any, any>,
72+
): ProviderResult<PriceWsTransportTypes | VwapWsTransportTypes>[] | undefined => {
73+
const results = []
74+
for (const update of updates) {
75+
const params = transport.getReverseMapping(update.ticker)
76+
if (!params) {
77+
continue
78+
}
79+
if (!update.price) {
80+
const errorMessage = `The data provider didn't return any value for ${params.base}/${params.quote}`
81+
logger.info(errorMessage)
82+
results.push({
83+
params,
84+
response: {
85+
statusCode: 502,
86+
errorMessage,
87+
},
88+
})
89+
} else {
90+
results.push({
91+
params,
92+
response: {
93+
result: update.price,
94+
data: {
95+
result: update.price,
96+
},
97+
timestamps: {
98+
providerIndicatedTimeUnixMs: update.ts,
99+
},
100+
},
101+
})
102+
}
103+
}
104+
return results
105+
}

0 commit comments

Comments
 (0)