Skip to content

Commit

Permalink
Feature/DF-18812 add vwap endpoint to blocksize capital ea (#3025)
Browse files Browse the repository at this point in the history
* 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]>
  • Loading branch information
mmcallister-cll and alecgard authored Oct 17, 2023
1 parent 878c80c commit 9a97711
Show file tree
Hide file tree
Showing 13 changed files with 296 additions and 90 deletions.
5 changes: 5 additions & 0 deletions .changeset/young-tomatoes-float.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@chainlink/blocksize-capital-adapter': minor
---

Add vwap endpoint to blocksize-capital EA
33 changes: 30 additions & 3 deletions packages/sources/blocksize-capital/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,9 @@ There are no rate limits for this adapter.

## Input Parameters

| Required? | Name | Description | Type | Options | Default |
| :-------: | :------: | :-----------------: | :----: | :------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :-----: |
| | 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` |
| Required? | Name | Description | Type | Options | Default |
| :-------: | :------: | :-----------------: | :----: | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :-----: |
| | 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` |

## Price Endpoint

Expand Down Expand Up @@ -79,4 +79,31 @@ Request:

---

## Vwap Endpoint

Supported names for this endpoint are: `crypto-vwap`, `vwap`.

### Input Params

| Required? | Name | Aliases | Description | Type | Options | Default | Depends On | Not Valid With |
| :-------: | :---: | :------------: | :--------------------------------------------: | :----: | :-----: | :-----: | :--------: | :------------: |
|| base | `coin`, `from` | The symbol of symbols of the currency to query | string | | | | |
|| quote | `market`, `to` | The symbol of the currency to convert to | string | | | | |

### Example

Request:

```json
{
"data": {
"endpoint": "vwap",
"base": "ETH",
"quote": "USD"
}
}
```

---

MIT License
1 change: 1 addition & 0 deletions packages/sources/blocksize-capital/src/endpoint/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
export { endpoint as price } from './price'
export { endpoint as cryptolwba } from './crypto-lwba'
export { endpoint as vwap } from './vwap'
28 changes: 28 additions & 0 deletions packages/sources/blocksize-capital/src/endpoint/vwap.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import {
PriceEndpoint,
priceEndpointInputParametersDefinition,
} from '@chainlink/external-adapter-framework/adapter'
import { InputParameters } from '@chainlink/external-adapter-framework/validation'
import { config } from '../config'
import { transport } from '../transport/vwap'
import { SingleNumberResultResponse } from '@chainlink/external-adapter-framework/util'

const inputParameters = new InputParameters(priceEndpointInputParametersDefinition, [
{
base: 'AMPL',
quote: 'USD',
},
])

export type BaseEndpointTypes = {
Parameters: typeof inputParameters.definition
Settings: typeof config.settings
Response: SingleNumberResultResponse
}

export const endpoint = new PriceEndpoint({
name: 'vwap',
aliases: ['crypto-vwap'],
transport,
inputParameters,
})
4 changes: 2 additions & 2 deletions packages/sources/blocksize-capital/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import { expose, ServerInstance } from '@chainlink/external-adapter-framework'
import { PriceAdapter } from '@chainlink/external-adapter-framework/adapter'
import { config } from './config'
import { cryptolwba, price } from './endpoint'
import { cryptolwba, price, vwap } from './endpoint'

export const adapter = new PriceAdapter({
name: 'BLOCKSIZE_CAPITAL',
endpoints: [price, cryptolwba],
endpoints: [price, cryptolwba, vwap],
defaultEndpoint: price.name,
config,
})
Expand Down
28 changes: 11 additions & 17 deletions packages/sources/blocksize-capital/src/transport/crypto-lwba.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,16 @@
import { BaseEndpointTypes } from '../endpoint/crypto-lwba'
import { WebsocketReverseMappingTransport } from '@chainlink/external-adapter-framework/transports/websocket'
import { makeLogger, ProviderResult } from '@chainlink/external-adapter-framework/util'
import { BaseMessage, blocksizeDefaultWebsocketOpenHandler } from './utils'
import {
BaseMessage,
blocksizeDefaultUnsubscribeMessageBuilder,
blocksizeDefaultWebsocketOpenHandler,
buildBlocksizeWebsocketTickersMessage,
} from './utils'

const logger = makeLogger('BlocksizeCapitalLwbaWebsocketEndpoint')

export interface Message extends BaseMessage {
export interface BidAskMessage extends BaseMessage {
method: 'bidask'
params: {
updates: {
Expand All @@ -22,7 +27,7 @@ export interface Message extends BaseMessage {

export type WsTransportTypes = BaseEndpointTypes & {
Provider: {
WsMessage: Message
WsMessage: BidAskMessage
}
}

Expand Down Expand Up @@ -75,20 +80,9 @@ export const transport: WebsocketReverseMappingTransport<WsTransportTypes, strin
subscribeMessage: (params) => {
const pair = `${params.base}${params.quote}`.toUpperCase()
transport.setReverseMapping(pair, params)
return {
jsonrpc: '2.0',
method: 'bidask_subscribe',
params: { tickers: [pair] },
}
},

unsubscribeMessage: (params) => {
const pair = `${params.base}${params.quote}`.toUpperCase()
return {
jsonrpc: '2.0',
method: 'bidask_unsubscribe',
params: { tickers: [pair] },
}
return buildBlocksizeWebsocketTickersMessage('bidask_subscribe', pair)
},
unsubscribeMessage: (params) =>
blocksizeDefaultUnsubscribeMessageBuilder(params.base, params.quote, 'bidask_unsubscribe'),
},
})
74 changes: 15 additions & 59 deletions packages/sources/blocksize-capital/src/transport/price.ts
Original file line number Diff line number Diff line change
@@ -1,26 +1,24 @@
import { BaseEndpointTypes } from '../endpoint/price'
import { WebsocketReverseMappingTransport } from '@chainlink/external-adapter-framework/transports/websocket'
import { makeLogger, ProviderResult } from '@chainlink/external-adapter-framework/util'
import { BaseMessage, blocksizeDefaultWebsocketOpenHandler } from './utils'
import {
BaseMessage,
blocksizeDefaultUnsubscribeMessageBuilder,
blocksizeDefaultWebsocketOpenHandler,
buildBlocksizeWebsocketTickersMessage,
handlePriceUpdates,
VwapUpdate,
} from './utils'

const logger = makeLogger('BlocksizeCapitalWebsocketEndpoint')

export interface Message extends BaseMessage {
export interface VwapMessage extends BaseMessage {
method: 'vwap'
params: {
updates: {
ticker: string
price?: number
size?: number
volume?: number
ts: number
}[]
updates: VwapUpdate[]
}
}

export type WsTransportTypes = BaseEndpointTypes & {
Provider: {
WsMessage: Message
WsMessage: VwapMessage
}
}

Expand All @@ -33,58 +31,16 @@ export const transport: WebsocketReverseMappingTransport<WsTransportTypes, strin
message: (message) => {
if (message.method !== 'vwap') return []
const updates = message.params.updates
const results: ProviderResult<WsTransportTypes>[] = []
for (const update of updates) {
const params = transport.getReverseMapping(update.ticker)
if (!params) {
continue
}
if (!update.price) {
const errorMessage = `The data provider didn't return any value for ${params.base}/${params.quote}`
logger.info(errorMessage)
results.push({
params,
response: {
statusCode: 502,
errorMessage,
},
})
} else {
results.push({
params,
response: {
result: update.price,
data: {
result: update.price,
},
timestamps: {
providerIndicatedTimeUnixMs: update.ts,
},
},
})
}
}
return results
return handlePriceUpdates(updates, transport)
},
},
builders: {
subscribeMessage: (params) => {
const pair = `${params.base}${params.quote}`.toUpperCase()
transport.setReverseMapping(pair, params)
return {
jsonrpc: '2.0',
method: 'vwap_subscribe',
params: { tickers: [pair] },
}
},

unsubscribeMessage: (params) => {
const pair = `${params.base}${params.quote}`.toUpperCase()
return {
jsonrpc: '2.0',
method: 'vwap_unsubscribe',
params: { tickers: [pair] },
}
return buildBlocksizeWebsocketTickersMessage('vwap_subscribe', pair)
},
unsubscribeMessage: (params) =>
blocksizeDefaultUnsubscribeMessageBuilder(params.base, params.quote, 'vwap_unsubscribe'),
},
})
90 changes: 81 additions & 9 deletions packages/sources/blocksize-capital/src/transport/utils.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,49 @@
import { makeLogger } from '@chainlink/external-adapter-framework/util'
import { WebsocketReverseMappingTransport } from '@chainlink/external-adapter-framework/transports'
import { ProviderResult, makeLogger } from '@chainlink/external-adapter-framework/util'
import { WsTransportTypes as PriceWsTransportTypes } from './price'
import { WsTransportTypes as VwapWsTransportTypes } from './vwap'

const logger = makeLogger('BlocksizeCapitalTransportUtils')

export interface BaseMessage {
jsonrpc: string
id?: string | number | null
method: string
method?: string
}

export type VwapUpdate = {
ticker: string
price?: number
size?: number
volume?: number
ts: number
}

export type ProviderParams = {
tickers?: string[]
api_key?: string
}

const buildBlocksizeWebsocketMessage = (method: string, params: ProviderParams): unknown => {
return {
jsonrpc: '2.0',
method: method,
params: params,
}
}

export const buildBlocksizeWebsocketAuthMessage = (apiKey: string) =>
buildBlocksizeWebsocketMessage('authentication_logon', { api_key: apiKey })
export const buildBlocksizeWebsocketTickersMessage = (method: string, pair: string) =>
buildBlocksizeWebsocketMessage(method, { tickers: [pair] })

export const blocksizeDefaultUnsubscribeMessageBuilder = (
base: string,
quote: string,
method: string,
): unknown => {
const pair = `${base}${quote}`.toUpperCase()
return buildBlocksizeWebsocketTickersMessage(method, pair)
}

// use as open handler for standard WS connections
Expand All @@ -20,14 +58,48 @@ export const blocksizeDefaultWebsocketOpenHandler = (
logger.debug('Got logged in response, connection is ready')
resolve()
} else {
reject(new Error('Failed to make WS connection'))
reject(new Error(`Failed to make WS connection: ${JSON.stringify(parsed)}`))
}
})
const options = {
jsonrpc: '2.0',
method: 'authentication_logon',
params: { api_key: apiKey },
}
connection.send(JSON.stringify(options))
const message = buildBlocksizeWebsocketAuthMessage(apiKey)
connection.send(JSON.stringify(message))
})
}

export const handlePriceUpdates = (
updates: VwapUpdate[],
transport: WebsocketReverseMappingTransport<any, any>,
): ProviderResult<PriceWsTransportTypes | VwapWsTransportTypes>[] | undefined => {
const results = []
for (const update of updates) {
const params = transport.getReverseMapping(update.ticker)
if (!params) {
continue
}
if (!update.price) {
const errorMessage = `The data provider didn't return any value for ${params.base}/${params.quote}`
logger.info(errorMessage)
results.push({
params,
response: {
statusCode: 502,
errorMessage,
},
})
} else {
results.push({
params,
response: {
result: update.price,
data: {
result: update.price,
},
timestamps: {
providerIndicatedTimeUnixMs: update.ts,
},
},
})
}
}
return results
}
Loading

0 comments on commit 9a97711

Please sign in to comment.