Skip to content

Commit d79038b

Browse files
committed
Re-add ComputePrice endpoint
1 parent e3e0b57 commit d79038b

File tree

10 files changed

+1051
-743
lines changed

10 files changed

+1051
-743
lines changed

packages/composites/implied-price/README.md

Lines changed: 107 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ The Computed Price adapter performs mathematical operations (divide or multiply)
99
- **High Reliability**: Built-in circuit breakers, retry logic, and timeout handling
1010
- **Flexible Input**: Supports both `from`/`to` and `base`/`quote` parameter formats
1111
- **High-Precision Math**: Uses `decimal.js` for accurate financial calculations
12-
- **Comprehensive Testing**: 52 unit and integration tests covering all scenarios
12+
- **Comprehensive Testing**: 51 unit and integration tests covering all scenarios
1313
- **Type Safety**: Full TypeScript support with proper interfaces
1414

1515
## Configuration
@@ -31,18 +31,34 @@ The adapter accepts the following environment variables for reliability and perf
3131

3232
## Input Parameters
3333

34-
Every request requires the following parameters:
34+
This adapter supports **both v2 endpoint parameter formats** for full backward compatibility:
35+
36+
### Format 1: operand1/operand2 (v2 computedPrice endpoint)
3537

3638
| Required? | Name | Description | Type | Options | Default | Depends On | Not Valid With |
3739
| :-------: | :------------------: | :------------------------------------------: | :--------: | :------------------: | :-----: | :--------: | :------------: |
38-
|| `dividendSources` | Array of source adapters for dividend values | `string[]` | | | | |
39-
| | `dividendMinAnswers` | Minimum required dividend responses | `number` | | `1` | | |
40-
|| `dividendInput` | JSON string payload for dividend sources | `string` | | | | |
41-
|| `divisorSources` | Array of source adapters for divisor values | `string[]` | | | | |
42-
| | `divisorMinAnswers` | Minimum required divisor responses | `number` | | `1` | | |
43-
|| `divisorInput` | JSON string payload for divisor sources | `string` | | | | |
40+
|| `operand1Sources` | Array of source adapters for operand1 values | `string[]` | | | | |
41+
| | `operand1MinAnswers` | Minimum required operand1 responses | `number` | | `1` | | |
42+
|| `operand1Input` | JSON string payload for operand1 sources | `string` | | | | |
43+
|| `operand2Sources` | Array of source adapters for operand2 values | `string[]` | | | | |
44+
| | `operand2MinAnswers` | Minimum required operand2 responses | `number` | | `1` | | |
45+
|| `operand2Input` | JSON string payload for operand2 sources | `string` | | | | |
4446
|| `operation` | Mathematical operation to perform | `string` | `divide`, `multiply` | | | |
4547

48+
### Format 2: dividend/divisor (v2 impliedPrice endpoint)
49+
50+
| Required? | Name | Description | Type | Options | Default | Depends On | Not Valid With |
51+
| :-------: | :------------------: | :------------------------------------------: | :--------: | :------------------: | :------: | :--------: | :------------: |
52+
|| `dividendSources` | Array of source adapters for dividend values | `string[]` | | | | |
53+
| | `dividendMinAnswers` | Minimum required dividend responses | `number` | | `1` | | |
54+
|| `dividendInput` | JSON string payload for dividend sources | `string` | | | | |
55+
|| `divisorSources` | Array of source adapters for divisor values | `string[]` | | | | |
56+
| | `divisorMinAnswers` | Minimum required divisor responses | `number` | | `1` | | |
57+
|| `divisorInput` | JSON string payload for divisor sources | `string` | | | | |
58+
| | `operation` | Mathematical operation to perform | `string` | `divide`, `multiply` | `divide` | | |
59+
60+
> **Note**: Use either Format 1 (operand1/operand2) OR Format 2 (dividend/divisor) - do not mix parameter names from different formats.
61+
4662
### Input Formats
4763

4864
**Sources**: Array of adapter names
@@ -72,7 +88,39 @@ JSON.stringify({
7288

7389
## Sample Input
7490

75-
### Division Example (Implied Price)
91+
### Format 1: operand1/operand2 (v2 computedPrice endpoint)
92+
93+
**Division Example:**
94+
95+
```json
96+
{
97+
"data": {
98+
"operand1Sources": ["coingecko", "coinpaprika"],
99+
"operand2Sources": ["coingecko", "coinpaprika"],
100+
"operand1Input": "{\"base\":\"ETH\",\"quote\":\"USD\"}",
101+
"operand2Input": "{\"base\":\"BTC\",\"quote\":\"USD\"}",
102+
"operation": "divide"
103+
}
104+
}
105+
```
106+
107+
**Multiplication Example:**
108+
109+
```json
110+
{
111+
"data": {
112+
"operand1Sources": ["coingecko"],
113+
"operand2Sources": ["coingecko"],
114+
"operand1Input": "{\"from\":\"LINK\",\"to\":\"USD\",\"overrides\":{\"coingecko\":{\"LINK\":\"chainlink\"}}}",
115+
"operand2Input": "{\"from\":\"ETH\",\"to\":\"USD\",\"overrides\":{\"coingecko\":{\"ETH\":\"ethereum\"}}}",
116+
"operation": "multiply"
117+
}
118+
}
119+
```
120+
121+
### Format 2: dividend/divisor (v2 impliedPrice endpoint)
122+
123+
**Division Example (Implied Price):**
76124

77125
```json
78126
{
@@ -86,7 +134,7 @@ JSON.stringify({
86134
}
87135
```
88136

89-
### Multiplication Example
137+
**Multiplication Example:**
90138

91139
```json
92140
{
@@ -100,6 +148,34 @@ JSON.stringify({
100148
}
101149
```
102150

151+
**Division with Default Operation (operation omitted):**
152+
153+
```json
154+
{
155+
"data": {
156+
"dividendSources": ["coingecko"],
157+
"divisorSources": ["coingecko"],
158+
"dividendInput": "{\"from\":\"LINK\",\"to\":\"USD\"}",
159+
"divisorInput": "{\"from\":\"ETH\",\"to\":\"USD\"}"
160+
}
161+
}
162+
```
163+
164+
**Default Endpoint (no endpoint specified - v2 behavior):**
165+
166+
```json
167+
{
168+
"data": {
169+
"dividendSources": ["coingecko"],
170+
"divisorSources": ["coingecko"],
171+
"dividendInput": "{\"from\":\"LINK\",\"to\":\"USD\"}",
172+
"divisorInput": "{\"from\":\"ETH\",\"to\":\"USD\"}"
173+
}
174+
}
175+
```
176+
177+
> When using Format 2 (dividend/divisor), the `operation` parameter is optional and defaults to `"divide"`. When no endpoint is specified, it defaults to `impliedPrice` for full v2 backward compatibility.
178+
103179
## Sample Output
104180

105181
```json
@@ -114,14 +190,23 @@ JSON.stringify({
114190

115191
## Calculation
116192

117-
The adapter:
193+
The adapter performs the following steps regardless of parameter format:
194+
195+
1. **Data Fetching**: Fetches price data from the first set of sources using the first input payload
196+
197+
- Format 1: `operand1Sources` with `operand1Input`
198+
- Format 2: `dividendSources` with `dividendInput`
199+
200+
2. **Data Fetching**: Fetches price data from the second set of sources using the second input payload
201+
202+
- Format 1: `operand2Sources` with `operand2Input`
203+
- Format 2: `divisorSources` with `divisorInput`
204+
205+
3. **Median Calculation**: Calculates the median of each set of responses
118206

119-
1. Fetches price data from dividend sources using the `dividendInput` payload
120-
2. Fetches price data from divisor sources using the `divisorInput` payload
121-
3. Calculates the median of each set of responses
122-
4. Performs the specified operation:
123-
- **Divide**: `dividend_median / divisor_median`
124-
- **Multiply**: `dividend_median * divisor_median`
207+
4. **Mathematical Operation**: Performs the specified operation:
208+
- **Divide**: `first_median / second_median` (or `dividend_median / divisor_median`)
209+
- **Multiply**: `first_median * second_median` (or `dividend_median * divisor_median`)
125210

126211
## Reliability Features
127212

@@ -143,7 +228,7 @@ The adapter supports both `from`/`to` and `base`/`quote` parameter formats for m
143228

144229
## Testing
145230

146-
The adapter includes comprehensive test coverage with 52 tests (39 unit tests and 13 integration tests):
231+
The adapter includes comprehensive test coverage with 51 tests (37 unit tests and 14 integration tests):
147232

148233
### Unit Tests
149234

@@ -153,6 +238,7 @@ The adapter includes comprehensive test coverage with 52 tests (39 unit tests an
153238

154239
### Integration Tests
155240

241+
- **Backward Compatibility**: Full tests for both v2 parameter formats (`operand1`/`operand2` and `dividend`/`divisor`)
156242
- **Full Request Cycle**: Tests complete adapter functionality with mocked HTTP transport
157243
- **Operation Support**: Tests both `divide` and `multiply` operations with various data combinations
158244
- **Input Format Compatibility**: Tests both `base`/`quote` and `from`/`to` formats
@@ -163,13 +249,13 @@ The adapter includes comprehensive test coverage with 52 tests (39 unit tests an
163249
### Running Tests
164250

165251
```bash
166-
# All tests
252+
# All tests (51 total)
167253
yarn test packages/composites/implied-price
168254

169-
# Unit tests only (39 tests)
255+
# Unit tests only (37 tests)
170256
yarn test packages/composites/implied-price/test/unit
171257

172-
# Integration tests only (13 tests)
258+
# Integration tests only (14 tests)
173259
yarn test packages/composites/implied-price/test/integration
174260

175261
# Specific test pattern

packages/composites/implied-price/src/config/index.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
import { AdapterConfig } from '@chainlink/external-adapter-framework/config'
22

3+
export const NAME = 'IMPLIED_PRICE'
4+
export const DEFAULT_ENDPOINT = 'impliedPrice'
5+
36
export const config = new AdapterConfig(
47
{
58
SOURCE_TIMEOUT: {
Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
import { AdapterEndpoint } from '@chainlink/external-adapter-framework/adapter'
2+
import { SingleNumberResultResponse } from '@chainlink/external-adapter-framework/util'
3+
import { InputParameters } from '@chainlink/external-adapter-framework/validation'
4+
import { config } from '../config'
5+
import { transport } from '../transport/computedPrice'
6+
7+
export const inputParameters = new InputParameters(
8+
{
9+
operand1Sources: {
10+
required: true,
11+
type: 'string',
12+
array: true,
13+
description:
14+
'An array (string[]) or comma delimited list (string) of source adapters to query for the operand1 value',
15+
},
16+
operand1MinAnswers: {
17+
required: false,
18+
type: 'number',
19+
description: 'The minimum number of answers needed to return a value for the operand1',
20+
default: 1,
21+
},
22+
operand1Input: {
23+
required: true,
24+
type: 'string',
25+
description: 'The payload to send to the operand1 sources',
26+
},
27+
operand2Sources: {
28+
required: true,
29+
type: 'string',
30+
array: true,
31+
description:
32+
'An array (string[]) or comma delimited list (string) of source adapters to query for the operand2 value',
33+
},
34+
operand2MinAnswers: {
35+
required: false,
36+
type: 'number',
37+
description: 'The minimum number of answers needed to return a value for the operand2',
38+
default: 1,
39+
},
40+
operand2Input: {
41+
required: true,
42+
type: 'string',
43+
description: 'The payload to send to the operand2 sources',
44+
},
45+
operation: {
46+
required: true,
47+
type: 'string',
48+
description: 'The operation to perform on the operands',
49+
options: ['divide', 'multiply'],
50+
},
51+
},
52+
[
53+
// Example using operand1/operand2 format - division
54+
{
55+
operand1Sources: ['coingecko'],
56+
operand1MinAnswers: 1,
57+
operand1Input: JSON.stringify({
58+
from: 'LINK',
59+
to: 'USD',
60+
overrides: {
61+
coingecko: {
62+
LINK: 'chainlink',
63+
},
64+
},
65+
}),
66+
operand2Sources: ['coingecko'],
67+
operand2MinAnswers: 1,
68+
operand2Input: JSON.stringify({
69+
from: 'ETH',
70+
to: 'USD',
71+
overrides: {
72+
coingecko: {
73+
ETH: 'ethereum',
74+
},
75+
},
76+
}),
77+
operation: 'divide',
78+
} as any,
79+
// Example using operand1/operand2 format - multiplication
80+
{
81+
operand1Sources: ['coinbase', 'coingecko'],
82+
operand1MinAnswers: 1,
83+
operand1Input: JSON.stringify({
84+
base: 'ETH',
85+
quote: 'USD',
86+
overrides: {
87+
coingecko: {
88+
ETH: 'ethereum',
89+
},
90+
},
91+
}),
92+
operand2Sources: ['coinbase', 'coingecko'],
93+
operand2MinAnswers: 1,
94+
operand2Input: JSON.stringify({
95+
base: 'BTC',
96+
quote: 'USD',
97+
overrides: {
98+
coingecko: {
99+
BTC: 'bitcoin',
100+
},
101+
},
102+
}),
103+
operation: 'multiply',
104+
} as any,
105+
] as any,
106+
)
107+
108+
export type BaseEndpointTypes = {
109+
Parameters: typeof inputParameters.definition
110+
Response: SingleNumberResultResponse
111+
Settings: typeof config.settings
112+
}
113+
114+
export const endpoint = new AdapterEndpoint({
115+
name: 'computedPrice',
116+
aliases: ['computed'],
117+
transport,
118+
inputParameters,
119+
})

0 commit comments

Comments
 (0)