Skip to content

Conversation

paul-chain
Copy link
Contributor

@paul-chain paul-chain commented Sep 26, 2025

Description

Adds a new Coinpaprika State external adapter that streams state_price via Server-Sent Events (SSE).
See package README for full details

Changes

  • New package: @chainlink/coinpaprika-state-adapter
  • Endpoint: coinpaprika-state (alias: state)
  • Transport: single-connection SSE with:
    • pair batching & dynamic reconnect on pair-set change
    • JSON parsing with malformed-event tolerance
    • graceful shutdown & reconnection backoff with jitter

Sample Input and Output

Sample Input

{
  "data": {
    "base": "LUSD",
    "quote": "USD",
    "endpoint": "coinpaprika-state"
  }
}

Using the alias state

{
  "data": {
    "base": "LUSD", 
    "quote": "USD",
    "endpoint": "state"
  }
}

Without endpoint (uses default)

{
  "data": {
    "base": "LUSD",
    "quote": "USD"
  }
}

Sample Output

{
  "data": {
    "result": 1.000979,
    "timestamp": 1758888503
  },
  "statusCode": 200,
  "result": 1.000979,
  "timestamps": {
    "providerDataRequestedUnixMs": 1758888508939,
    "providerDataReceivedUnixMs": 1758888508939,
    "providerIndicatedTimeUnixMs": 1758888503000
  },
  "meta": {
    "adapterName": "COINPAPRIKA_STATE",
    "metrics": {
      "feedId": "{\"base\":\"lusd\",\"quote\":\"usd\"}"
    }
  }
}

Example cURL Requests

Using the primary endpoint coinpaprika-state

curl -X POST http://localhost:8080 \
  -H "Content-Type: application/json" \
  -d '{"data":{"base":"LUSD","quote":"USD","endpoint":"coinpaprika-state"}}'

Using the alias state

curl -X POST http://localhost:8080 \
    -H "Content-Type: application/json" \
    -d '{"data": {"base": "LUSD", "quote": "USD", "endpoint": "state"}}'

Without endpoint (uses default)

curl -X POST http://localhost:8080 \
  -H "Content-Type: application/json" \
  -d '{"data": {"base": "LUSD", "quote": "USD"}}'

Steps to Test

  1. Navigate to the root of the external-adapters-js repo
  2. Build the adapter: yarn workspace @chainlink/coinpaprika-state-adapter build
  3. Run tests:
  • Integration test: yarn test packages/sources/coinpaprika-state/test/integration/adapter.test.ts
  • Unit test: yarn test packages/sources/coinpaprika-state/test/unit/sse.test.ts

Quality Assurance

  • If a new adapter was made, or an existing one was modified so that its environment variables have changed, update the relevant infra-k8s configuration file.
  • If a new adapter was made, or an existing one was modified so that its environment variables have changed, update the relevant adapter-secrets configuration file or update the soak testing blacklist.
  • If a new adapter was made, or a new endpoint was added, update the test-payload.json file with relevant requests.
  • The branch naming follows git flow (feature/x, chore/x, release/x, hotfix/x, fix/x) or is created from Jira.
  • This is related to a maximum of one Jira story or GitHub issue.
  • Types are safe (avoid TypeScript/TSLint features like any and disable, instead use more specific types).
  • All code changes have 100% unit and integration test coverage. If testing is not applicable or too difficult to justify doing, the reasoning should be documented explicitly in the PR.

@changeset-bot
Copy link

changeset-bot bot commented Sep 26, 2025

🦋 Changeset detected

Latest commit: 83913f6

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
@chainlink/coinpaprika-state-adapter Major

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@paul-chain paul-chain force-pushed the feat/add-coinpaprika-state-adapter branch from 9e8c109 to 76c20cb Compare September 26, 2025 18:46
@karen-stepanyan
Copy link
Contributor

any reason why this is not a new endpoint on existing coinpaprika EA ?

@paul-chain paul-chain changed the title Add Coinpaprika State adapter OPDATA-4082 Add Coinpaprika State adapter Sep 29, 2025
@paul-chain paul-chain changed the title OPDATA-4082 Add Coinpaprika State adapter [OPDATA-4082] Add Coinpaprika State adapter Sep 29, 2025
@paul-chain paul-chain force-pushed the feat/add-coinpaprika-state-adapter branch 3 times, most recently from 1156b6b to 14c598a Compare September 30, 2025 17:49
@paul-chain
Copy link
Contributor Author

Updated to use existing EA with new endpoint

@alejoberardino
Copy link
Collaborator

saw this pr randomly, there's an sse transport in the framework, what's the particular reason this adapter needs a custom one?

@paul-chain
Copy link
Contributor Author

@alejoberardino I investigated SseTransport but found it's designed around the usual EventSource/GET model (and optional separate sub/unsub/keepalive calls). The current design of Coinpaprika State API instead opens a single SSE connection via POST with a JSON body containing all pairs and expects reconnects when the pair set changes. Given that shape, SubscriptionTransport is a cleaner fit for batching pairs and managing one shared connection + reconnection logic.

@paul-chain paul-chain force-pushed the feat/add-coinpaprika-state-adapter branch 2 times, most recently from 7a62e70 to 2842eb9 Compare October 6, 2025 16:39
@paul-chain paul-chain force-pushed the feat/add-coinpaprika-state-adapter branch 3 times, most recently from e4b859a to f2aa694 Compare October 21, 2025 21:25
@paul-chain paul-chain force-pushed the feat/add-coinpaprika-state-adapter branch from 004f903 to 5e12ffb Compare October 21, 2025 22:22
- Remove complex stream parsing for HTTP error responses
- Use simple HTTP status-based error messages like other EAs
- Clean up 20+ lines of manual buffer concatenation
- Improve maintainability and reduce error-prone code
- Fix API_ENDPOINT default to avoid /stream/stream
- Remove unused RECONNECT_DELAY_MS
paul-chain and others added 3 commits October 22, 2025 22:56
- Fix API error type separation (stream vs connection errors)
- Optimize subscription lookup with O(1) Map.get() instead of O(n) Array.find()
- Improve async error handling with proper Promise rejection handling
- Remove unnecessary complexity and duplicate code
@mmcallister-cll
Copy link
Contributor

Just noting an assumption on this SSE transport: We assume each valid streamed message will contain 1 event and 1 data field. Changes to the data provider API message schema (multi-responses or otherwise) are not expected to work out of the box and would require further code changes.

@paul-chain paul-chain merged commit 503aeee into main Oct 23, 2025
17 checks passed
@paul-chain paul-chain deleted the feat/add-coinpaprika-state-adapter branch October 23, 2025 20:31
@github-actions github-actions bot mentioned this pull request Oct 23, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants