From 4d7722c550efbe0921b21bf3d7e9aa63d4274755 Mon Sep 17 00:00:00 2001 From: Karim Date: Fri, 19 Jun 2026 19:41:51 +0400 Subject: [PATCH 1/2] add support for min/max operations --- .changeset/sweet-clubs-decide.md | 5 ++ .../src/endpoint/computedPrice.ts | 2 +- .../src/transport/computePrice.ts | 25 +++++--- .../__snapshots__/adapter.test.ts.snap | 32 ++++++++++ .../test/integration/adapter.test.ts | 64 +++++++++++++++++++ 5 files changed, 119 insertions(+), 9 deletions(-) create mode 100644 .changeset/sweet-clubs-decide.md diff --git a/.changeset/sweet-clubs-decide.md b/.changeset/sweet-clubs-decide.md new file mode 100644 index 00000000000..b93c7f5e2af --- /dev/null +++ b/.changeset/sweet-clubs-decide.md @@ -0,0 +1,5 @@ +--- +'@chainlink/calculated-price-adapter': minor +--- + +Added support for min/max operations diff --git a/packages/composites/calculated-price/src/endpoint/computedPrice.ts b/packages/composites/calculated-price/src/endpoint/computedPrice.ts index 284373b2058..983e09e3227 100644 --- a/packages/composites/calculated-price/src/endpoint/computedPrice.ts +++ b/packages/composites/calculated-price/src/endpoint/computedPrice.ts @@ -64,7 +64,7 @@ export const inputParameters = new InputParameters( default: 'divide', type: 'string', description: 'The operation to perform on the operands', - options: ['divide', 'multiply'], + options: ['divide', 'multiply', 'min', 'max'], }, outputDecimals: { required: false, diff --git a/packages/composites/calculated-price/src/transport/computePrice.ts b/packages/composites/calculated-price/src/transport/computePrice.ts index f8a7ce14909..5d9c2f55ef9 100644 --- a/packages/composites/calculated-price/src/transport/computePrice.ts +++ b/packages/composites/calculated-price/src/transport/computePrice.ts @@ -156,14 +156,23 @@ export class ComputedPriceTransport extends SubscriptionTransport { nock.cleanAll() }) + it('should return success for min', async () => { + const data = { + operand1Sources: ['ncfx'], + operand1Input: JSON.stringify({ + from: 'LINK', + to: 'USD12', + overrides: { + coingecko: { + LINK: 'chainlink', + }, + }, + }), + operand2Sources: ['tiingo'], + operand2Input: JSON.stringify({ + from: 'ETH', + to: 'USD12', + overrides: { + coingecko: { + ETH: 'ethereum', + }, + }, + }), + operation: 'min', + } + mockDPResponseSuccess('ncfx', 20) + mockDPResponseSuccess('tiingo', 10) + const response = await testAdapter.request(data) + expect(response.statusCode).toBe(200) + expect(response.json()).toMatchSnapshot() + nock.cleanAll() + }) + + it('should return success for max', async () => { + const data = { + operand1Sources: ['ncfx'], + operand1Input: JSON.stringify({ + from: 'LINK', + to: 'USD13', + overrides: { + coingecko: { + LINK: 'chainlink', + }, + }, + }), + operand2Sources: ['tiingo'], + operand2Input: JSON.stringify({ + from: 'ETH', + to: 'USD13', + overrides: { + coingecko: { + ETH: 'ethereum', + }, + }, + }), + operation: 'max', + } + mockDPResponseSuccess('ncfx', 5) + mockDPResponseSuccess('tiingo', 20) + const response = await testAdapter.request(data) + expect(response.statusCode).toBe(200) + expect(response.json()).toMatchSnapshot() + nock.cleanAll() + }) + it('returns failure with mismatched operand1Decimals', async () => { const data = { operand1Sources: ['ncfx', 'elwood'], From 108e282c1d379f4afb51ebf5aa80531d3e9f5ded Mon Sep 17 00:00:00 2001 From: Karim Date: Fri, 19 Jun 2026 19:55:10 +0400 Subject: [PATCH 2/2] update README --- .../composites/calculated-price/README.md | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/packages/composites/calculated-price/README.md b/packages/composites/calculated-price/README.md index 6bc895e58da..a4ecef0ad33 100644 --- a/packages/composites/calculated-price/README.md +++ b/packages/composites/calculated-price/README.md @@ -38,18 +38,18 @@ Supported names for this endpoint are: `computedprice`, `impliedprice`. ### Input Params -| Required? | Name | Aliases | Description | Type | Options | Default | Depends On | Not Valid With | -| :-------: | :-------------------: | :------------------: | :----------------------------------------------------------------------------: | :------: | :------------------: | :------: | :--------: | :------------: | -| ✅ | operand1Sources | `dividendSources` | An array of source adapters to query for the operand1 value | string[] | | | | | -| ✅ | operand1Input | `dividendInput` | The JSON payload to send to the operand1 sources | string | | | | | -| | operand1MinAnswers | `dividendMinAnswers` | The minimum number of answers needed to return a value for the operand1 | number | | `1` | | | -| | operand1DecimalsField | | The field path in operand1 response data containing the decimal scaling factor | string | | | | | -| ✅ | operand2Sources | `divisorSources` | An array of source adapters to query for the operand2 value | string[] | | | | | -| ✅ | operand2Input | `divisorInput` | The JSON payload to send to the operand2 sources | string | | | | | -| | operand2MinAnswers | `divisorMinAnswers` | The minimum number of answers needed to return a value for the operand2 | number | | `1` | | | -| | operand2DecimalsField | | The field path in operand2 response data containing the decimal scaling factor | string | | | | | -| | operation | | The operation to perform on the operands | string | `divide`, `multiply` | `divide` | | | -| | outputDecimals | | Decimal scaling of the result | number | | | | | +| Required? | Name | Aliases | Description | Type | Options | Default | Depends On | Not Valid With | +| :-------: | :-------------------: | :------------------: | :----------------------------------------------------------------------------: | :------: | :--------------------------------: | :------: | :--------: | :------------: | +| ✅ | operand1Sources | `dividendSources` | An array of source adapters to query for the operand1 value | string[] | | | | | +| ✅ | operand1Input | `dividendInput` | The JSON payload to send to the operand1 sources | string | | | | | +| | operand1MinAnswers | `dividendMinAnswers` | The minimum number of answers needed to return a value for the operand1 | number | | `1` | | | +| | operand1DecimalsField | | The field path in operand1 response data containing the decimal scaling factor | string | | | | | +| ✅ | operand2Sources | `divisorSources` | An array of source adapters to query for the operand2 value | string[] | | | | | +| ✅ | operand2Input | `divisorInput` | The JSON payload to send to the operand2 sources | string | | | | | +| | operand2MinAnswers | `divisorMinAnswers` | The minimum number of answers needed to return a value for the operand2 | number | | `1` | | | +| | operand2DecimalsField | | The field path in operand2 response data containing the decimal scaling factor | string | | | | | +| | operation | | The operation to perform on the operands | string | `divide`, `max`, `min`, `multiply` | `divide` | | | +| | outputDecimals | | Decimal scaling of the result | number | | | | | ### Example