From 4d12c52b493d126d84cd7b9ed5b1f8a733bd9809 Mon Sep 17 00:00:00 2001 From: David de Kloet Date: Mon, 18 May 2026 15:51:22 +0200 Subject: [PATCH] Fix ripcord bug in generic-api --- .changeset/petite-parents-win.md | 5 ++ .../generic-api/src/transport/utils.ts | 3 +- .../__snapshots__/adapter.test.ts.snap | 2 - .../test/integration/adapter.test.ts | 1 - .../generic-api/test/unit/http.test.ts | 84 +++++++++++++++++-- 5 files changed, 83 insertions(+), 12 deletions(-) create mode 100644 .changeset/petite-parents-win.md diff --git a/.changeset/petite-parents-win.md b/.changeset/petite-parents-win.md new file mode 100644 index 00000000000..3bada7a11bf --- /dev/null +++ b/.changeset/petite-parents-win.md @@ -0,0 +1,5 @@ +--- +'@chainlink/generic-api-adapter': patch +--- + +Require ripcord field to be present when configured diff --git a/packages/sources/generic-api/src/transport/utils.ts b/packages/sources/generic-api/src/transport/utils.ts index 07d05d0e70a..95e0011e667 100644 --- a/packages/sources/generic-api/src/transport/utils.ts +++ b/packages/sources/generic-api/src/transport/utils.ts @@ -60,8 +60,7 @@ const createMultiResponse = ( // Check ripcord if ( param.ripcordPath !== undefined && - objectPath.has(response.data, param.ripcordPath) && - objectPath.get(response.data, param.ripcordPath).toString() !== param.ripcordDisabledValue + String(objectPath.get(response.data, param.ripcordPath)) !== param.ripcordDisabledValue ) { // Look for ripcordDetails as sibling field const ripcordDetailsPath = `${param.ripcordPath}Details` diff --git a/packages/sources/generic-api/test/integration/__snapshots__/adapter.test.ts.snap b/packages/sources/generic-api/test/integration/__snapshots__/adapter.test.ts.snap index 09d883da50a..7df3de5398f 100644 --- a/packages/sources/generic-api/test/integration/__snapshots__/adapter.test.ts.snap +++ b/packages/sources/generic-api/test/integration/__snapshots__/adapter.test.ts.snap @@ -4,8 +4,6 @@ exports[`execute http endpoint should return success 1`] = ` { "data": { "result": "123000", - "ripcord": false, - "ripcordAsInt": 0, }, "result": "123000", "statusCode": 200, diff --git a/packages/sources/generic-api/test/integration/adapter.test.ts b/packages/sources/generic-api/test/integration/adapter.test.ts index c45445b9269..3280cdb1049 100644 --- a/packages/sources/generic-api/test/integration/adapter.test.ts +++ b/packages/sources/generic-api/test/integration/adapter.test.ts @@ -53,7 +53,6 @@ describe('execute', () => { endpoint: 'http', apiName: 'test', dataPath: 'PoR', - ripcordPath: 'ripcord', } mockResponseSuccess() const response = await testAdapter.request(data) diff --git a/packages/sources/generic-api/test/unit/http.test.ts b/packages/sources/generic-api/test/unit/http.test.ts index 1f38f90e4e9..1ea52884a28 100644 --- a/packages/sources/generic-api/test/unit/http.test.ts +++ b/packages/sources/generic-api/test/unit/http.test.ts @@ -179,7 +179,7 @@ describe('GenericApiHttpTransport', () => { const params = makeStub('params', { apiName, dataPath, - ripcordPath, + ripcordPath: undefined, ripcordDisabledValue: 'false', providerIndicatedTimePath: undefined, }) @@ -199,8 +199,6 @@ describe('GenericApiHttpTransport', () => { const expectedResponse = { data: { result: expectedValue, - ripcord: false, - ripcordAsInt: 0, }, result: expectedValue, timestamps: { @@ -333,7 +331,7 @@ describe('GenericApiHttpTransport', () => { const params = makeStub('params', { apiName, dataPath, - ripcordPath, + ripcordPath: undefined, ripcordDisabledValue: 'false', providerIndicatedTimePath: undefined, }) @@ -353,8 +351,6 @@ describe('GenericApiHttpTransport', () => { const expectedResponse = { data: { result: expectedValue, - ripcord: false, - ripcordAsInt: 0, }, result: expectedValue, timestamps: { @@ -380,7 +376,7 @@ describe('GenericApiHttpTransport', () => { const params = makeStub('params', { apiName, dataPath, - ripcordPath, + ripcordPath: undefined, ripcordDisabledValue: 'false', providerIndicatedTimePath: undefined, }) @@ -736,6 +732,44 @@ describe('GenericApiHttpTransport', () => { }) }) + it('should treat missing ripcord as success with undefined disabledValue', async () => { + process.env.TEST_API_URL = apiUrl + + const params = { + apiName, + dataPath: 'net_asset_value', + ripcordPath: 'ripcord', + ripcordDisabledValue: 'undefined', + } + + const response = { + response: { + data: { + net_asset_value: 1.004373, + }, + cost: undefined, + }, + timestamps: {}, + } + + const expectedResponse = { + data: { + result: '1.004373', + ripcord: false, + ripcordAsInt: 0, + }, + result: '1.004373', + timestamps: { providerIndicatedTimeUnixMs: undefined }, + } + + await doTransportTest({ + params, + expectedRequestConfig: requestConfigWithoutAuthHeader, + response, + expectedResponse, + }) + }) + it('should not include ripcord status when ripcord path is absent', async () => { process.env.TEST_API_URL = apiUrl @@ -771,4 +805,40 @@ describe('GenericApiHttpTransport', () => { expectedResponse, }) }) + + it('should treat ripcord as enabled if ripcord field is expected but missing', async () => { + process.env.TEST_API_URL = apiUrl + + const params = { + apiName, + dataPath: 'net_asset_value', + ripcordPath, + ripcordDisabledValue: 'false', + } + + const response = { + response: { + data: { + net_asset_value: 1.004373, + }, + cost: undefined, + }, + timestamps: {}, + } + + const expectedResponse = { + errorMessage: `Ripcord activated for 'test'`, + ripcord: true, + ripcordAsInt: 1, + statusCode: 503, + timestamps: {}, + } + + await doTransportTest({ + params, + expectedRequestConfig: requestConfigWithoutAuthHeader, + response, + expectedResponse, + }) + }) })