@chainlink/external-adapter-framework 0.0.8 → 0.0.12
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.
- package/.c8rc.json +3 -0
- package/.eslintignore +9 -0
- package/.eslintrc.js +96 -0
- package/.github/README.MD +17 -0
- package/.github/actions/setup/action.yaml +13 -0
- package/.github/workflows/main.yaml +39 -0
- package/.github/workflows/publish.yaml +20 -0
- package/.prettierignore +13 -0
- package/.yarnrc +0 -0
- package/README.md +103 -0
- package/dist/src/adapter.d.ts +135 -0
- package/dist/src/adapter.js +145 -0
- package/{package → dist/src}/background-executor.d.ts +2 -2
- package/{background-executor.js → dist/src/background-executor.js} +0 -0
- package/{cache → dist/src/cache}/factory.d.ts +0 -0
- package/{package → dist/src}/cache/factory.js +0 -2
- package/{package → dist/src}/cache/index.d.ts +10 -6
- package/{package → dist/src}/cache/index.js +13 -9
- package/{cache → dist/src/cache}/local.d.ts +0 -0
- package/{cache → dist/src/cache}/local.js +0 -0
- package/{cache → dist/src/cache}/metrics.d.ts +0 -0
- package/{cache → dist/src/cache}/metrics.js +0 -0
- package/{cache → dist/src/cache}/redis.d.ts +0 -0
- package/{package → dist/src}/cache/redis.js +5 -5
- package/dist/src/chainlink-external-adapter-framework-0.0.6.tgz +0 -0
- package/{package → dist/src}/config/index.d.ts +20 -1
- package/{package → dist/src}/config/index.js +24 -9
- package/{config → dist/src/config}/provider-limits.d.ts +0 -0
- package/{config → dist/src/config}/provider-limits.js +0 -0
- package/dist/src/examples/bank-frick/accounts.d.ts +39 -0
- package/dist/src/examples/bank-frick/accounts.js +192 -0
- package/dist/src/examples/bank-frick/config/index.d.ts +4 -0
- package/dist/src/examples/bank-frick/config/index.js +54 -0
- package/dist/src/examples/bank-frick/index.d.ts +2 -0
- package/dist/src/examples/bank-frick/index.js +15 -0
- package/dist/src/examples/bank-frick/util.d.ts +4 -0
- package/dist/src/examples/bank-frick/util.js +39 -0
- package/dist/src/examples/coingecko/batch-warming.d.ts +7 -0
- package/{package → dist/src}/examples/coingecko/batch-warming.js +3 -2
- package/dist/src/examples/coingecko/index.d.ts +2 -0
- package/{package → dist/src}/examples/coingecko/index.js +3 -2
- package/dist/src/examples/coingecko/rest.d.ts +12 -0
- package/{package → dist/src}/examples/coingecko/rest.js +3 -2
- package/{examples → dist/src/examples}/ncfx/config/index.d.ts +0 -0
- package/{examples → dist/src/examples}/ncfx/config/index.js +0 -0
- package/dist/src/examples/ncfx/index.d.ts +13 -0
- package/{package → dist/src}/examples/ncfx/index.js +3 -2
- package/{package → dist/src}/examples/ncfx/websocket.d.ts +12 -1
- package/{package → dist/src}/examples/ncfx/websocket.js +3 -2
- package/{package → dist/src}/index.d.ts +2 -3
- package/{package → dist/src}/index.js +55 -19
- package/{metrics → dist/src/metrics}/constants.d.ts +0 -0
- package/{metrics → dist/src/metrics}/constants.js +0 -0
- package/{metrics → dist/src/metrics}/index.d.ts +0 -0
- package/{package → dist/src}/metrics/index.js +0 -1
- package/dist/src/metrics/util.d.ts +7 -0
- package/{package → dist/src}/metrics/util.js +2 -2
- package/{adapter.d.ts → dist/src/package/adapter.d.ts} +2 -2
- package/{adapter.js → dist/src/package/adapter.js} +0 -0
- package/{background-executor.d.ts → dist/src/package/background-executor.d.ts} +0 -0
- package/{package → dist/src/package}/background-executor.js +0 -0
- package/{package → dist/src/package}/cache/factory.d.ts +0 -0
- package/{cache → dist/src/package/cache}/factory.js +0 -0
- package/{cache → dist/src/package/cache}/index.d.ts +0 -0
- package/{cache → dist/src/package/cache}/index.js +0 -0
- package/{package → dist/src/package}/cache/local.d.ts +0 -0
- package/{package → dist/src/package}/cache/local.js +0 -0
- package/{package → dist/src/package}/cache/metrics.d.ts +0 -0
- package/{package → dist/src/package}/cache/metrics.js +0 -0
- package/{package → dist/src/package}/cache/redis.d.ts +0 -0
- package/{cache → dist/src/package/cache}/redis.js +0 -0
- package/{config → dist/src/package/config}/index.d.ts +0 -0
- package/{config → dist/src/package/config}/index.js +0 -0
- package/{package → dist/src/package}/config/provider-limits.d.ts +0 -0
- package/{package → dist/src/package}/config/provider-limits.js +2 -1
- package/{examples → dist/src/package/examples}/coingecko/batch-warming.d.ts +0 -0
- package/{examples → dist/src/package/examples}/coingecko/batch-warming.js +0 -0
- package/{examples → dist/src/package/examples}/coingecko/index.d.ts +0 -0
- package/{examples → dist/src/package/examples}/coingecko/index.js +0 -0
- package/{examples → dist/src/package/examples}/coingecko/rest.d.ts +0 -0
- package/{examples → dist/src/package/examples}/coingecko/rest.js +0 -0
- package/{package → dist/src/package}/examples/ncfx/config/index.d.ts +0 -0
- package/{package → dist/src/package}/examples/ncfx/config/index.js +0 -0
- package/{examples → dist/src/package/examples}/ncfx/index.d.ts +0 -0
- package/{examples → dist/src/package/examples}/ncfx/index.js +0 -0
- package/{examples → dist/src/package/examples}/ncfx/websocket.d.ts +0 -0
- package/{examples → dist/src/package/examples}/ncfx/websocket.js +0 -0
- package/{index.d.ts → dist/src/package/index.d.ts} +1 -1
- package/{index.js → dist/src/package/index.js} +0 -0
- package/{package → dist/src/package}/metrics/constants.d.ts +0 -0
- package/{package → dist/src/package}/metrics/constants.js +0 -0
- package/{package → dist/src/package}/metrics/index.d.ts +0 -0
- package/{metrics → dist/src/package/metrics}/index.js +0 -0
- package/{metrics → dist/src/package/metrics}/util.d.ts +0 -0
- package/{metrics → dist/src/package/metrics}/util.js +0 -0
- package/dist/src/package/package.json +72 -0
- package/{package → dist/src/package}/rate-limiting/background/fixed-frequency.d.ts +0 -0
- package/{package → dist/src/package}/rate-limiting/background/fixed-frequency.js +0 -0
- package/{package → dist/src/package}/rate-limiting/index.d.ts +2 -2
- package/{package → dist/src/package}/rate-limiting/index.js +0 -0
- package/{package → dist/src/package}/rate-limiting/metrics.d.ts +0 -0
- package/{package → dist/src/package}/rate-limiting/metrics.js +0 -0
- package/{package → dist/src/package}/rate-limiting/request/simple-counting.d.ts +0 -0
- package/{package → dist/src/package}/rate-limiting/request/simple-counting.js +0 -0
- package/{package → dist/src/package}/test.d.ts +0 -0
- package/{package → dist/src/package}/test.js +0 -0
- package/{package → dist/src/package}/transports/batch-warming.d.ts +0 -0
- package/{package → dist/src/package}/transports/batch-warming.js +0 -0
- package/{package → dist/src/package}/transports/index.d.ts +0 -0
- package/{package → dist/src/package}/transports/index.js +0 -0
- package/{package → dist/src/package}/transports/metrics.d.ts +1 -1
- package/{package → dist/src/package}/transports/metrics.js +0 -0
- package/{package → dist/src/package}/transports/rest.d.ts +0 -0
- package/{package → dist/src/package}/transports/rest.js +0 -0
- package/{package → dist/src/package}/transports/util.d.ts +0 -0
- package/{package → dist/src/package}/transports/util.js +0 -0
- package/{package → dist/src/package}/transports/websocket.d.ts +0 -0
- package/{package → dist/src/package}/transports/websocket.js +0 -0
- package/{package → dist/src/package}/util/expiring-sorted-set.d.ts +0 -0
- package/{package → dist/src/package}/util/expiring-sorted-set.js +0 -0
- package/{package → dist/src/package}/util/index.d.ts +0 -0
- package/{package → dist/src/package}/util/index.js +0 -0
- package/{package → dist/src/package}/util/logger.d.ts +0 -0
- package/{package → dist/src/package}/util/logger.js +0 -0
- package/{package → dist/src/package}/util/request.d.ts +0 -0
- package/{package → dist/src/package}/util/request.js +0 -0
- package/{package → dist/src/package}/validation/error.d.ts +0 -0
- package/{package → dist/src/package}/validation/error.js +0 -0
- package/{package → dist/src/package}/validation/index.d.ts +0 -0
- package/{package → dist/src/package}/validation/index.js +0 -0
- package/{package → dist/src/package}/validation/input-params.d.ts +0 -0
- package/{package → dist/src/package}/validation/input-params.js +0 -0
- package/{package → dist/src/package}/validation/override-functions.d.ts +0 -0
- package/{package → dist/src/package}/validation/override-functions.js +0 -0
- package/{package → dist/src/package}/validation/preset-tokens.json +0 -0
- package/{package → dist/src/package}/validation/validator.d.ts +0 -0
- package/{package → dist/src/package}/validation/validator.js +0 -0
- package/{package → dist/src}/package.json +5 -2
- package/{rate-limiting → dist/src/rate-limiting}/background/fixed-frequency.d.ts +2 -1
- package/{rate-limiting → dist/src/rate-limiting}/background/fixed-frequency.js +0 -2
- package/{rate-limiting → dist/src/rate-limiting}/index.d.ts +4 -3
- package/{rate-limiting → dist/src/rate-limiting}/index.js +0 -0
- package/{rate-limiting → dist/src/rate-limiting}/metrics.d.ts +0 -0
- package/{rate-limiting → dist/src/rate-limiting}/metrics.js +0 -0
- package/{rate-limiting → dist/src/rate-limiting}/request/simple-counting.d.ts +2 -1
- package/{rate-limiting → dist/src/rate-limiting}/request/simple-counting.js +0 -0
- package/{test.d.ts → dist/src/test.d.ts} +0 -0
- package/{test.js → dist/src/test.js} +2 -2
- package/{transports → dist/src/transports}/batch-warming.d.ts +4 -3
- package/{transports → dist/src/transports}/batch-warming.js +4 -4
- package/{transports → dist/src/transports}/index.d.ts +5 -22
- package/{transports → dist/src/transports}/index.js +3 -3
- package/{transports → dist/src/transports}/metrics.d.ts +4 -3
- package/{transports → dist/src/transports}/metrics.js +2 -2
- package/{transports → dist/src/transports}/rest.d.ts +2 -1
- package/{transports → dist/src/transports}/rest.js +3 -1
- package/{transports → dist/src/transports}/util.d.ts +0 -0
- package/{transports → dist/src/transports}/util.js +0 -0
- package/{transports → dist/src/transports}/websocket.d.ts +7 -7
- package/{transports → dist/src/transports}/websocket.js +8 -11
- package/{util → dist/src/util}/expiring-sorted-set.d.ts +0 -0
- package/{util → dist/src/util}/expiring-sorted-set.js +0 -0
- package/{util → dist/src/util}/index.d.ts +2 -1
- package/{util → dist/src/util}/index.js +1 -1
- package/{util → dist/src/util}/logger.d.ts +0 -0
- package/{util → dist/src/util}/logger.js +0 -0
- package/{util → dist/src/util}/request.d.ts +5 -3
- package/{util → dist/src/util}/request.js +0 -0
- package/dist/src/util/subscription-set/expiring-sorted-set.d.ts +22 -0
- package/dist/src/util/subscription-set/expiring-sorted-set.js +47 -0
- package/dist/src/util/subscription-set/subscription-set.d.ts +18 -0
- package/dist/src/util/subscription-set/subscription-set.js +19 -0
- package/dist/src/util/test-payload-loader.d.ts +25 -0
- package/dist/src/util/test-payload-loader.js +83 -0
- package/{validation → dist/src/validation}/error.d.ts +4 -4
- package/{validation → dist/src/validation}/error.js +1 -1
- package/{validation → dist/src/validation}/index.d.ts +0 -0
- package/{validation → dist/src/validation}/index.js +8 -3
- package/{validation → dist/src/validation}/input-params.d.ts +0 -0
- package/{validation → dist/src/validation}/input-params.js +0 -0
- package/dist/src/validation/override-functions.d.ts +3 -0
- package/{validation → dist/src/validation}/override-functions.js +0 -0
- package/{validation → dist/src/validation}/preset-tokens.json +0 -0
- package/{validation → dist/src/validation}/validator.d.ts +0 -0
- package/{validation → dist/src/validation}/validator.js +0 -0
- package/docker-compose.yaml +35 -0
- package/env.sh +54 -0
- package/env2.sh +55 -0
- package/package.json +5 -3
- package/publish.sh +0 -0
- package/src/adapter.ts +263 -0
- package/src/background-executor.ts +52 -0
- package/src/cache/factory.ts +26 -0
- package/src/cache/index.ts +258 -0
- package/src/cache/local.ts +73 -0
- package/src/cache/metrics.ts +112 -0
- package/src/cache/redis.ts +93 -0
- package/src/config/index.ts +517 -0
- package/src/config/provider-limits.ts +130 -0
- package/src/examples/bank-frick/README.MD +10 -0
- package/src/examples/bank-frick/accounts.ts +246 -0
- package/src/examples/bank-frick/config/index.ts +53 -0
- package/src/examples/bank-frick/index.ts +13 -0
- package/src/examples/bank-frick/types.d.ts +38 -0
- package/src/examples/bank-frick/util.ts +55 -0
- package/src/examples/coingecko/batch-warming.ts +78 -0
- package/src/examples/coingecko/index.ts +9 -0
- package/src/examples/coingecko/rest.ts +77 -0
- package/src/examples/ncfx/config/index.ts +12 -0
- package/src/examples/ncfx/index.ts +9 -0
- package/src/examples/ncfx/websocket.ts +99 -0
- package/src/index.ts +149 -0
- package/src/metrics/constants.ts +23 -0
- package/src/metrics/index.ts +115 -0
- package/src/metrics/util.ts +18 -0
- package/src/rate-limiting/background/fixed-frequency.ts +45 -0
- package/src/rate-limiting/index.ts +100 -0
- package/src/rate-limiting/metrics.ts +18 -0
- package/src/rate-limiting/request/simple-counting.ts +76 -0
- package/src/test.ts +5 -0
- package/src/transports/batch-warming.ts +122 -0
- package/src/transports/index.ts +152 -0
- package/src/transports/metrics.ts +95 -0
- package/src/transports/rest.ts +164 -0
- package/src/transports/util.ts +63 -0
- package/src/transports/websocket.ts +245 -0
- package/src/util/index.ts +22 -0
- package/src/util/logger.ts +69 -0
- package/src/util/request.ts +117 -0
- package/src/util/subscription-set/expiring-sorted-set.ts +54 -0
- package/src/util/subscription-set/subscription-set.ts +35 -0
- package/src/util/test-payload-loader.ts +87 -0
- package/src/validation/error.ts +116 -0
- package/src/validation/index.ts +110 -0
- package/src/validation/input-params.ts +45 -0
- package/src/validation/override-functions.ts +44 -0
- package/src/validation/preset-tokens.json +23 -0
- package/src/validation/validator.ts +384 -0
- package/test/adapter.test.ts +27 -0
- package/test/background-executor.test.ts +108 -0
- package/test/cache/cache-key.test.ts +114 -0
- package/test/cache/helper.ts +100 -0
- package/test/cache/local.test.ts +54 -0
- package/test/cache/redis.test.ts +89 -0
- package/test/correlation.test.ts +114 -0
- package/test/index.test.ts +37 -0
- package/test/metrics/feed-id.test.ts +38 -0
- package/test/metrics/helper.ts +14 -0
- package/test/metrics/labels.test.ts +36 -0
- package/test/metrics/metrics.test.ts +267 -0
- package/test/metrics/redis-metrics.test.ts +113 -0
- package/test/metrics/warmer-metrics.test.ts +192 -0
- package/test/metrics/ws-metrics.test.ts +225 -0
- package/test/rate-limit-config.test.ts +242 -0
- package/test/smoke.test.ts +166 -0
- package/test/transports/batch.test.ts +465 -0
- package/test/transports/rest.test.ts +242 -0
- package/test/transports/websocket.test.ts +183 -0
- package/test/tsconfig.json +5 -0
- package/test/util.ts +77 -0
- package/test/validation.test.ts +178 -0
- package/test-payload-fail.json +3 -0
- package/test-payload.js +22 -0
- package/test-payload.json +7 -0
- package/test.sh +20 -0
- package/test2.sh +2 -0
- package/tsconfig.json +25 -0
- package/typedoc.json +6 -0
- package/webpack.config.js +23 -0
- package/chainlink-external-adapter-framework-v0.0.8.tgz +0 -0
- package/package/adapter.d.ts +0 -88
- package/package/adapter.js +0 -112
- package/package/examples/coingecko/batch-warming.d.ts +0 -2
- package/package/examples/coingecko/index.d.ts +0 -2
- package/package/examples/coingecko/rest.d.ts +0 -2
- package/package/examples/ncfx/index.d.ts +0 -2
- package/package/metrics/util.d.ts +0 -3
- package/validation/override-functions.d.ts +0 -3
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import untypedTest, { TestFn } from 'ava'
|
|
2
|
+
import axios, { AxiosError } from 'axios'
|
|
3
|
+
import { AdapterDependencies, AdapterEndpoint } from '../../src/adapter'
|
|
4
|
+
import { Cache } from '../../src/cache'
|
|
5
|
+
import { AdapterRequest, AdapterResponse } from '../../src/util'
|
|
6
|
+
import { NopTransport } from '../util'
|
|
7
|
+
|
|
8
|
+
export const test = untypedTest as TestFn<{
|
|
9
|
+
serverAddress: string
|
|
10
|
+
cache: Cache
|
|
11
|
+
adapterEndpoint: AdapterEndpoint
|
|
12
|
+
}>
|
|
13
|
+
|
|
14
|
+
export class BasicCacheSetterTransport extends NopTransport {
|
|
15
|
+
cache!: Cache
|
|
16
|
+
|
|
17
|
+
override async initialize(dependencies: AdapterDependencies): Promise<void> {
|
|
18
|
+
this.cache = dependencies.cache
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
override async setup(req: AdapterRequest): Promise<void> {
|
|
22
|
+
const response: AdapterResponse = {
|
|
23
|
+
data: null,
|
|
24
|
+
statusCode: 200,
|
|
25
|
+
result: req.requestContext.data['factor'],
|
|
26
|
+
}
|
|
27
|
+
await this.cache.setMany(
|
|
28
|
+
[
|
|
29
|
+
{
|
|
30
|
+
key: req.requestContext.cacheKey,
|
|
31
|
+
value: response,
|
|
32
|
+
},
|
|
33
|
+
],
|
|
34
|
+
10000,
|
|
35
|
+
)
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export const cacheTests = () => {
|
|
40
|
+
test('returns value set in cache from setup', async (t) => {
|
|
41
|
+
const data = {
|
|
42
|
+
base: 'eth',
|
|
43
|
+
factor: 123,
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
const response = await axios.post(`${t.context.serverAddress}`, { data })
|
|
47
|
+
t.is(response.data.result, 123)
|
|
48
|
+
})
|
|
49
|
+
|
|
50
|
+
test('returns value already found in cache', async (t) => {
|
|
51
|
+
const data = {
|
|
52
|
+
base: 'qweqwe',
|
|
53
|
+
factor: 111,
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
const cacheKey = 'test-|base:qweqwe|factor:111'
|
|
57
|
+
|
|
58
|
+
// Inject values directly into the cache
|
|
59
|
+
const injectedEntry = {
|
|
60
|
+
data: null,
|
|
61
|
+
statusCode: 200,
|
|
62
|
+
result: 'injected',
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
t.context.cache.set(cacheKey, injectedEntry, 10000)
|
|
66
|
+
|
|
67
|
+
const response = await axios.post(`${t.context.serverAddress}`, { data })
|
|
68
|
+
t.is(response.data.result, 'injected')
|
|
69
|
+
})
|
|
70
|
+
|
|
71
|
+
test('skips expired cache entry and returns set up value', async (t) => {
|
|
72
|
+
const data = {
|
|
73
|
+
base: 'sdfghj',
|
|
74
|
+
factor: 24637,
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
const cacheKey = 'test-|base:sdfghj|factor:24637'
|
|
78
|
+
|
|
79
|
+
// Inject values directly into the cache
|
|
80
|
+
const injectedEntry = {
|
|
81
|
+
data: null,
|
|
82
|
+
statusCode: 200,
|
|
83
|
+
result: 'injected',
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
t.context.cache.set(cacheKey, injectedEntry, -10)
|
|
87
|
+
|
|
88
|
+
const response = await axios.post(`${t.context.serverAddress}`, { data })
|
|
89
|
+
t.is(response.data.result, 24637)
|
|
90
|
+
})
|
|
91
|
+
|
|
92
|
+
test('polls forever and returns timeout', async (t) => {
|
|
93
|
+
const makeRequest = () =>
|
|
94
|
+
axios.post(`${t.context.serverAddress}`, {
|
|
95
|
+
endpoint: 'nowork',
|
|
96
|
+
})
|
|
97
|
+
const error: AxiosError | undefined = await t.throwsAsync(makeRequest)
|
|
98
|
+
t.is(error?.response?.status, 504)
|
|
99
|
+
})
|
|
100
|
+
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { AddressInfo } from 'ws'
|
|
2
|
+
import { expose } from '../../src'
|
|
3
|
+
import { Adapter, AdapterDependencies } from '../../src/adapter'
|
|
4
|
+
import { LocalCache } from '../../src/cache'
|
|
5
|
+
import { SettingsMap } from '../../src/config'
|
|
6
|
+
import { Transport } from '../../src/transports'
|
|
7
|
+
import { NopTransport } from '../util'
|
|
8
|
+
import { BasicCacheSetterTransport, cacheTests, test } from './helper'
|
|
9
|
+
|
|
10
|
+
test.beforeEach(async (t) => {
|
|
11
|
+
const adapter: Adapter = {
|
|
12
|
+
name: 'test',
|
|
13
|
+
defaultEndpoint: 'test',
|
|
14
|
+
endpoints: [
|
|
15
|
+
{
|
|
16
|
+
name: 'test',
|
|
17
|
+
inputParameters: {
|
|
18
|
+
base: {
|
|
19
|
+
type: 'string',
|
|
20
|
+
required: true,
|
|
21
|
+
},
|
|
22
|
+
factor: {
|
|
23
|
+
type: 'number',
|
|
24
|
+
required: true,
|
|
25
|
+
},
|
|
26
|
+
},
|
|
27
|
+
transport: new BasicCacheSetterTransport() as Transport<unknown, unknown, SettingsMap>,
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
name: 'nowork',
|
|
31
|
+
inputParameters: {},
|
|
32
|
+
transport: new NopTransport(),
|
|
33
|
+
},
|
|
34
|
+
],
|
|
35
|
+
envDefaultOverrides: {
|
|
36
|
+
CACHE_POLLING_SLEEP_MS: 10,
|
|
37
|
+
CACHE_POLLING_MAX_RETRIES: 3,
|
|
38
|
+
},
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const cache = new LocalCache()
|
|
42
|
+
const dependencies: Partial<AdapterDependencies> = {
|
|
43
|
+
cache,
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
t.context.cache = cache
|
|
47
|
+
const server = await expose(adapter, dependencies)
|
|
48
|
+
if (!server) {
|
|
49
|
+
throw 'Server did not start'
|
|
50
|
+
}
|
|
51
|
+
t.context.serverAddress = `http://localhost:${(server.address() as AddressInfo).port}`
|
|
52
|
+
})
|
|
53
|
+
|
|
54
|
+
cacheTests()
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import Redis from 'ioredis'
|
|
2
|
+
import { AddressInfo } from 'ws'
|
|
3
|
+
import { expose } from '../../src'
|
|
4
|
+
import { Adapter, AdapterDependencies } from '../../src/adapter'
|
|
5
|
+
import { LocalCache, RedisCache } from '../../src/cache'
|
|
6
|
+
import { SettingsMap } from '../../src/config'
|
|
7
|
+
import { Transport } from '../../src/transports'
|
|
8
|
+
import { NopTransport } from '../util'
|
|
9
|
+
import { BasicCacheSetterTransport, cacheTests, test } from './helper'
|
|
10
|
+
|
|
11
|
+
class RedisMock {
|
|
12
|
+
store = new LocalCache<string>()
|
|
13
|
+
|
|
14
|
+
get(key: string) {
|
|
15
|
+
return this.store.get(key)
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
del(key: string) {
|
|
19
|
+
return this.store.delete(key)
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
set(key: string, value: string, px: 'PX', ttl: number) {
|
|
23
|
+
return this.store.set(key, value, ttl)
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
multi() {
|
|
27
|
+
return new CommandChainMock(this)
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
class CommandChainMock {
|
|
32
|
+
promises: Promise<unknown>[] = []
|
|
33
|
+
constructor(private redisMock: RedisMock) {}
|
|
34
|
+
|
|
35
|
+
set(key: string, value: string, px: 'PX', ttl: number) {
|
|
36
|
+
this.promises.push(this.redisMock.set(key, value, px, ttl))
|
|
37
|
+
return this
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
exec() {
|
|
41
|
+
return Promise.all(this.promises)
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
test.beforeEach(async (t) => {
|
|
46
|
+
const adapter: Adapter = {
|
|
47
|
+
name: 'test',
|
|
48
|
+
defaultEndpoint: 'test',
|
|
49
|
+
endpoints: [
|
|
50
|
+
{
|
|
51
|
+
name: 'test',
|
|
52
|
+
inputParameters: {
|
|
53
|
+
base: {
|
|
54
|
+
type: 'string',
|
|
55
|
+
required: true,
|
|
56
|
+
},
|
|
57
|
+
factor: {
|
|
58
|
+
type: 'number',
|
|
59
|
+
required: true,
|
|
60
|
+
},
|
|
61
|
+
},
|
|
62
|
+
transport: new BasicCacheSetterTransport() as Transport<unknown, unknown, SettingsMap>,
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
name: 'nowork',
|
|
66
|
+
inputParameters: {},
|
|
67
|
+
transport: new NopTransport(),
|
|
68
|
+
},
|
|
69
|
+
],
|
|
70
|
+
envDefaultOverrides: {
|
|
71
|
+
CACHE_POLLING_SLEEP_MS: 10,
|
|
72
|
+
CACHE_POLLING_MAX_RETRIES: 3,
|
|
73
|
+
},
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
const cache = new RedisCache(new RedisMock() as unknown as Redis) // Fake redis
|
|
77
|
+
const dependencies: Partial<AdapterDependencies> = {
|
|
78
|
+
cache,
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
t.context.cache = cache
|
|
82
|
+
const server = await expose(adapter, dependencies)
|
|
83
|
+
if (!server) {
|
|
84
|
+
throw 'Server did not start'
|
|
85
|
+
}
|
|
86
|
+
t.context.serverAddress = `http://localhost:${(server.address() as AddressInfo).port}`
|
|
87
|
+
})
|
|
88
|
+
|
|
89
|
+
cacheTests()
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import untypedTest, { TestFn } from 'ava'
|
|
2
|
+
import axios from 'axios'
|
|
3
|
+
import { AddressInfo } from 'net'
|
|
4
|
+
import { expose } from '../src'
|
|
5
|
+
import { Adapter, AdapterEndpoint } from '../src/adapter'
|
|
6
|
+
import { AdapterResponse, sleep } from '../src/util'
|
|
7
|
+
import { NopTransport } from './util'
|
|
8
|
+
import { asyncLocalStorage, Store } from '../src/util/logger'
|
|
9
|
+
|
|
10
|
+
const test = untypedTest as TestFn<{
|
|
11
|
+
serverAddress: string
|
|
12
|
+
adapterEndpoint: AdapterEndpoint
|
|
13
|
+
}>
|
|
14
|
+
|
|
15
|
+
const startAdapter = async (enabled: boolean) => {
|
|
16
|
+
process.env['CORRELATION_ID_ENABLED'] = enabled.toString()
|
|
17
|
+
|
|
18
|
+
const adapter: Adapter = {
|
|
19
|
+
name: 'test',
|
|
20
|
+
defaultEndpoint: 'test',
|
|
21
|
+
endpoints: [
|
|
22
|
+
{
|
|
23
|
+
name: 'test',
|
|
24
|
+
inputParameters: {},
|
|
25
|
+
transport: new (class extends NopTransport {
|
|
26
|
+
override async setup(): Promise<void | AdapterResponse<null>> {
|
|
27
|
+
const store = asyncLocalStorage.getStore() as Store
|
|
28
|
+
if (store !== undefined && store['correlationId'] === '1') {
|
|
29
|
+
await sleep(100)
|
|
30
|
+
}
|
|
31
|
+
return {
|
|
32
|
+
data: null,
|
|
33
|
+
statusCode: 200,
|
|
34
|
+
result: store as unknown as null,
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
})(),
|
|
38
|
+
},
|
|
39
|
+
],
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const server = await expose(adapter)
|
|
43
|
+
if (!server) {
|
|
44
|
+
throw 'Server did not start'
|
|
45
|
+
}
|
|
46
|
+
const serverAddress = `http://localhost:${(server.address() as AddressInfo).port}`
|
|
47
|
+
return serverAddress
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
test.serial('uses the correct correlation id when it is passed in a header', async (t) => {
|
|
51
|
+
const testId = 'test'
|
|
52
|
+
const serverAddress = await startAdapter(true)
|
|
53
|
+
const response = await axios.post(
|
|
54
|
+
serverAddress,
|
|
55
|
+
{
|
|
56
|
+
base: 'asd',
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
headers: {
|
|
60
|
+
'x-correlation-id': testId,
|
|
61
|
+
},
|
|
62
|
+
},
|
|
63
|
+
)
|
|
64
|
+
t.is(response.data.result.correlationId, testId)
|
|
65
|
+
})
|
|
66
|
+
|
|
67
|
+
test.serial('sets a correlation id when it is enabled as an env var', async (t) => {
|
|
68
|
+
const serverAddress = await startAdapter(true)
|
|
69
|
+
const response = await axios.post(serverAddress, {
|
|
70
|
+
base: 'asd',
|
|
71
|
+
})
|
|
72
|
+
t.is(typeof response.data.result.correlationId, 'string')
|
|
73
|
+
})
|
|
74
|
+
|
|
75
|
+
test.serial('correlation Id is not set when enabled is set to false', async (t) => {
|
|
76
|
+
const serverAddress = await startAdapter(false)
|
|
77
|
+
const response = await axios.post(serverAddress, {
|
|
78
|
+
base: 'asd',
|
|
79
|
+
})
|
|
80
|
+
t.is(response.data.result, undefined)
|
|
81
|
+
})
|
|
82
|
+
|
|
83
|
+
test.serial('preserves concurrency through subsequent calls', async (t) => {
|
|
84
|
+
const serverAddress = await startAdapter(true)
|
|
85
|
+
const request1 = await axios.post(
|
|
86
|
+
serverAddress,
|
|
87
|
+
{
|
|
88
|
+
base: 'asd',
|
|
89
|
+
},
|
|
90
|
+
{
|
|
91
|
+
headers: {
|
|
92
|
+
'x-correlation-id': '1',
|
|
93
|
+
},
|
|
94
|
+
},
|
|
95
|
+
)
|
|
96
|
+
// Send out second call normally
|
|
97
|
+
|
|
98
|
+
// Check that each call has the correct correlation Id
|
|
99
|
+
const request2 = axios.post(
|
|
100
|
+
serverAddress,
|
|
101
|
+
{
|
|
102
|
+
base: 'asd',
|
|
103
|
+
},
|
|
104
|
+
{
|
|
105
|
+
headers: {
|
|
106
|
+
'x-correlation-id': '2',
|
|
107
|
+
},
|
|
108
|
+
},
|
|
109
|
+
)
|
|
110
|
+
const response2 = await request2
|
|
111
|
+
const response1 = await request1
|
|
112
|
+
t.is(response1.data.result.correlationId === '1', true)
|
|
113
|
+
t.is(response2.data.result.correlationId === '2', true)
|
|
114
|
+
})
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import untypedTest, { TestFn } from 'ava'
|
|
2
|
+
import axios from 'axios'
|
|
3
|
+
import { AddressInfo } from 'net'
|
|
4
|
+
import { expose } from '../src'
|
|
5
|
+
import { Adapter } from '../src/adapter'
|
|
6
|
+
import { NopTransport } from './util'
|
|
7
|
+
|
|
8
|
+
const test = untypedTest as TestFn<{
|
|
9
|
+
serverAddress: string
|
|
10
|
+
}>
|
|
11
|
+
|
|
12
|
+
test.beforeEach(async (t) => {
|
|
13
|
+
const adapter: Adapter = {
|
|
14
|
+
name: 'test',
|
|
15
|
+
endpoints: [
|
|
16
|
+
{
|
|
17
|
+
name: 'test',
|
|
18
|
+
inputParameters: {},
|
|
19
|
+
transport: new NopTransport(),
|
|
20
|
+
},
|
|
21
|
+
],
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const server = await expose(adapter)
|
|
25
|
+
if (!server) {
|
|
26
|
+
throw 'Server did not start'
|
|
27
|
+
}
|
|
28
|
+
t.context.serverAddress = `http://localhost:${(server.address() as AddressInfo).port}`
|
|
29
|
+
})
|
|
30
|
+
|
|
31
|
+
test('health endpoint returns health OK', async (t) => {
|
|
32
|
+
const response = await axios.get(`${t.context.serverAddress}/health`)
|
|
33
|
+
t.deepEqual(response.data, {
|
|
34
|
+
message: 'OK',
|
|
35
|
+
version: process.env['npm_package_version'],
|
|
36
|
+
})
|
|
37
|
+
})
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import untypedTest, { TestFn } from 'ava'
|
|
2
|
+
import { AdapterEndpoint } from '../../src/adapter'
|
|
3
|
+
import { calculateFeedId } from '../../src/cache'
|
|
4
|
+
import { AdapterConfig, buildAdapterConfig } from '../../src/config'
|
|
5
|
+
import { NopTransport } from '../util'
|
|
6
|
+
|
|
7
|
+
const feedIdTest = untypedTest as TestFn<{
|
|
8
|
+
adapterEndpoint: AdapterEndpoint
|
|
9
|
+
adapterConfig: AdapterConfig
|
|
10
|
+
}>
|
|
11
|
+
|
|
12
|
+
feedIdTest.beforeEach(async (t) => {
|
|
13
|
+
t.context.adapterEndpoint = {
|
|
14
|
+
name: 'test',
|
|
15
|
+
inputParameters: {},
|
|
16
|
+
transport: new (class extends NopTransport {})(),
|
|
17
|
+
}
|
|
18
|
+
t.context.adapterConfig = buildAdapterConfig({})
|
|
19
|
+
})
|
|
20
|
+
|
|
21
|
+
feedIdTest.serial('no parameters returns N/A', async (t) => {
|
|
22
|
+
t.is(calculateFeedId(t.context, {}), 'N/A')
|
|
23
|
+
})
|
|
24
|
+
|
|
25
|
+
feedIdTest.serial('builds feed ID correctly from input params', async (t) => {
|
|
26
|
+
t.context.adapterEndpoint.inputParameters = {
|
|
27
|
+
base: {
|
|
28
|
+
type: 'string',
|
|
29
|
+
required: true,
|
|
30
|
+
},
|
|
31
|
+
quote: {
|
|
32
|
+
type: 'string',
|
|
33
|
+
required: true,
|
|
34
|
+
},
|
|
35
|
+
}
|
|
36
|
+
const data = { base: 'ETH', quote: 'BTC' }
|
|
37
|
+
t.is(calculateFeedId(t.context, data), '|base:eth|quote:btc')
|
|
38
|
+
})
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
// Parse metrics scrape into object to use for tests
|
|
2
|
+
export const parsePromMetrics = (data: string): Map<string, number> => {
|
|
3
|
+
const responseLines = data.split('\n')
|
|
4
|
+
const metricsMap = new Map<string, number>()
|
|
5
|
+
responseLines.forEach((line) => {
|
|
6
|
+
if (!line.startsWith('#') && line !== '') {
|
|
7
|
+
const metric = line.split(' ')
|
|
8
|
+
const nameLabel = metric[0]
|
|
9
|
+
const value = Number(metric[1])
|
|
10
|
+
metricsMap.set(nameLabel, value)
|
|
11
|
+
}
|
|
12
|
+
})
|
|
13
|
+
return metricsMap
|
|
14
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import test from 'ava'
|
|
2
|
+
import { cacheMetricsLabel } from '../../src/cache/metrics'
|
|
3
|
+
import { connectionErrorLabels, messageSubsLabels } from '../../src/transports/metrics'
|
|
4
|
+
|
|
5
|
+
test('Generate cache label test', (t) => {
|
|
6
|
+
const result = {
|
|
7
|
+
participant_id: 'test-|base:eth|quote:btc',
|
|
8
|
+
feed_id: '|base:eth|quote:btc',
|
|
9
|
+
cache_type: 'local',
|
|
10
|
+
}
|
|
11
|
+
t.deepEqual(cacheMetricsLabel('test-|base:eth|quote:btc', '|base:eth|quote:btc', 'local'), result)
|
|
12
|
+
})
|
|
13
|
+
|
|
14
|
+
test('Generate data provider metrics label test', (t) => {
|
|
15
|
+
const result = {
|
|
16
|
+
participant_id: 'test-|base:eth|quote:btc',
|
|
17
|
+
feed_id: '|base:eth|quote:btc',
|
|
18
|
+
cache_type: 'local',
|
|
19
|
+
}
|
|
20
|
+
t.deepEqual(cacheMetricsLabel('test-|base:eth|quote:btc', '|base:eth|quote:btc', 'local'), result)
|
|
21
|
+
})
|
|
22
|
+
|
|
23
|
+
test('Generate WS connection error label test', (t) => {
|
|
24
|
+
const result = {
|
|
25
|
+
message: 'error',
|
|
26
|
+
}
|
|
27
|
+
t.deepEqual(connectionErrorLabels('error'), result)
|
|
28
|
+
})
|
|
29
|
+
|
|
30
|
+
test('Generate WS message and subscription label test', (t) => {
|
|
31
|
+
const result = {
|
|
32
|
+
feed_id: '|base:eth|quote:btc',
|
|
33
|
+
subscription_key: 'test-|base:eth|quote:btc',
|
|
34
|
+
}
|
|
35
|
+
t.deepEqual(messageSubsLabels('|base:eth|quote:btc', 'test-|base:eth|quote:btc'), result)
|
|
36
|
+
})
|