Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/late-queens-check.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@chainlink/deutsche-boerse-adapter': minor
---

Split the endpoints and added support for tradegate
1 change: 1 addition & 0 deletions packages/sources/deutsche-boerse/src/endpoint/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
export { endpoint as lwba } from './lwba'
export { endpoint as price } from './price'
17 changes: 8 additions & 9 deletions packages/sources/deutsche-boerse/src/endpoint/lwba.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { AdapterEndpoint } from '@chainlink/external-adapter-framework/adapter'
import { AdapterEndpoint } from '@chainlink/external-adapter-framework/adapter/endpoint'
import { InputParameters } from '@chainlink/external-adapter-framework/validation'
import { config } from '../config'
import { wsTransport } from '../transport/lwba'
import { lwbaProtobufWsTransport } from '../transport/lwba'

export const MARKETS = ['md-xetraetfetp'] as const
export const MARKETS = ['md-xetraetfetp', 'md-tradegate'] as const
export type Market = (typeof MARKETS)[number]

export const inputParameters = new InputParameters(
Expand All @@ -30,27 +30,26 @@ export const inputParameters = new InputParameters(
],
)

interface LwbaLatestPriceResponse {
interface LwbaResponse {
Result: number | null
Data: {
mid: number
bid: number
ask: number
latestPrice: number
quoteProviderIndicatedTimeUnixMs: number
tradeProviderIndicatedTimeUnixMs: number
bidSize: number
askSize: number
}
}

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

export const endpoint = new AdapterEndpoint({
name: 'lwba',
aliases: [],
transport: wsTransport,
transport: lwbaProtobufWsTransport,
inputParameters,
})
24 changes: 24 additions & 0 deletions packages/sources/deutsche-boerse/src/endpoint/price.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { AdapterEndpoint } from '@chainlink/external-adapter-framework/adapter'
import { config } from '../config'
import { priceProtobufWsTransport } from '../transport/price'
import { inputParameters } from './lwba'

export interface PriceResponse {
Result: number | null
Data: {
latestPrice: number
}
}

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

export const endpoint = new AdapterEndpoint({
name: 'price',
aliases: [],
transport: priceProtobufWsTransport,
inputParameters,
})
4 changes: 2 additions & 2 deletions packages/sources/deutsche-boerse/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import { expose, ServerInstance } from '@chainlink/external-adapter-framework'
import { Adapter } from '@chainlink/external-adapter-framework/adapter'
import { config } from './config'
import { lwba } from './endpoint'
import { lwba, price } from './endpoint'

export const adapter = new Adapter({
defaultEndpoint: lwba.name,
name: 'DEUTSCHE_BOERSE',
config,
endpoints: [lwba],
endpoints: [lwba, price],
})

export const server = (): Promise<ServerInstance | undefined> => expose(adapter)
Original file line number Diff line number Diff line change
Expand Up @@ -4,71 +4,112 @@ export type Quote = {
bid?: number
ask?: number
mid?: number
bidSize?: number
askSize?: number
latestPrice?: number
quoteProviderTimeUnixMs?: number
tradeProviderTimeUnixMs?: number
}

export class InstrumentQuoteCache {
private readonly map = new Map<string, Quote>()
private readonly map = new Map<string, Map<string, Quote>>()

activate(isin: string) {
if (!this.map.has(isin)) this.map.set(isin, {})
isEmpty(): boolean {
return this.map.size === 0
}

hasMarket(market: string): boolean {
const marketMap = this.map.get(market)
return !!marketMap && marketMap.size > 0
}

getMarkets(): string[] {
return [...this.map].flatMap(([market, bucket]) => (bucket.size ? [market] : []))
}
deactivate(isin: string) {
this.map.delete(isin)

activate(market: string, isin: string) {
let marketMap = this.map.get(market)
if (!marketMap) {
marketMap = new Map<string, Quote>()
this.map.set(market, marketMap)
}
if (!marketMap.has(isin)) marketMap.set(isin, {})
}

deactivate(market: string, isin: string) {
const marketMap = this.map.get(market)
if (!marketMap) {
return
}
marketMap.delete(isin)
if (marketMap.size === 0) {
this.map.delete(market)
}
}
has(isin: string): boolean {
return this.map.has(isin)

has(market: string, isin: string): boolean {
return this.map.get(market)?.has(isin) ?? false
}
get(isin: string): Quote | undefined {
return this.map.get(isin)

get(market: string, isin: string): Quote | undefined {
return this.map.get(market)?.get(isin)
}
addQuote(isin: string, bid: number, ask: number, providerTime: number) {
const quote = this.get(isin)

addQuote(
market: string,
isin: string,
bid: number,
ask: number,
providerTime: number,
bidSz: number,
askSz: number,
) {
const quote = this.get(market, isin)
if (!quote) {
throw new Error(`Cannot add quote for inactive ISIN ${isin}`)
throw new Error(`Cannot add quote for inactive instrument ${market}-${isin}`)
}
const mid = new Decimal(bid).plus(ask).div(2)
quote.bid = bid
quote.ask = ask
quote.mid = mid.toNumber()
quote.quoteProviderTimeUnixMs = providerTime
quote.bidSize = bidSz
quote.askSize = askSz
}
addBid(isin: string, bid: number, providerTime: number) {
const quote = this.get(isin)

addBid(market: string, isin: string, bid: number, providerTime: number, bidSz?: number) {
const quote = this.get(market, isin)
if (!quote) {
throw new Error(`Cannot add quote for inactive ISIN ${isin}`)
}
if (quote.ask !== undefined) {
const mid = new Decimal(bid).plus(quote.ask).div(2)
quote.mid = mid.toNumber()
quote.mid = new Decimal(bid).plus(quote.ask).div(2).toNumber()
}
quote.bid = bid
quote.quoteProviderTimeUnixMs = providerTime
quote.bidSize = bidSz
}
addAsk(isin: string, ask: number, providerTime: number) {
const quote = this.get(isin)

addAsk(market: string, isin: string, ask: number, providerTime: number, askSz?: number) {
const quote = this.get(market, isin)
if (!quote) {
throw new Error(`Cannot add quote for inactive ISIN ${isin}`)
}

if (quote.bid !== undefined) {
const mid = new Decimal(quote.bid).plus(ask).div(2)
quote.mid = mid.toNumber()
quote.mid = new Decimal(quote.bid).plus(ask).div(2).toNumber()
}
quote.ask = ask
quote.quoteProviderTimeUnixMs = providerTime
quote.askSize = askSz
}
addTrade(isin: string, lastPrice: number, providerTime: number) {
const quote = this.get(isin)

addTrade(market: string, isin: string, lastPrice: number, providerTime: number) {
const quote = this.get(market, isin)
if (!quote) {
throw new Error(`Cannot add trade for inactive ISIN ${isin}`)
throw new Error(`Cannot add trade for inactive instrument ${market}-${isin}`)
}
quote.latestPrice = lastPrice
quote.tradeProviderTimeUnixMs = providerTime
}
isEmpty(): boolean {
return this.map.size === 0
}
}
Loading
Loading