fix(provider): correct datum endpoint, delegation pool id, and UTxO mapping in Koios, Kupmios, Blockfrost#200
Conversation
…apping in Koios, Kupmios, Blockfrost
There was a problem hiding this comment.
Pull request overview
Fixes multiple provider correctness issues (Koios/Kupmios/Blockfrost) and adds a lightweight provider conformance test harness (opt-in via local env) to prevent future regressions.
Changes:
- Fix provider mappings/endpoints: Koios delegation pool-id decoding + UTxO datum/scriptRef mapping; Kupmios/Ogmios delegation schema + pool-id decoding; Blockfrost datum endpoint corrected to
/cbor. - Add provider integration/conformance tests with preprod fixtures and
.env.test.local-based configuration. - Add docs for retry-safe transaction patterns and wire it into the docs sidebar.
Reviewed changes
Copilot reviewed 14 out of 16 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| vitest.config.ts | Loads .env* files into Vitest test.env to support opt-in integration tests. |
| package.json | Adds vite devDependency to support loadEnv usage in Vitest config. |
| pnpm-lock.yaml | Locks new vite dependency and adjusts Vitest/Vite peer resolution accordingly. |
| packages/evolution/test/provider/providers.test.ts | New provider integration test entrypoint with env-based skipping and provider instantiation. |
| packages/evolution/test/provider/fixtures/constants.ts | Stable preprod fixtures (addresses, tx hash, datum hash, unit) used by conformance tests. |
| packages/evolution/test/provider/conformance.ts | New shared conformance test suite for the Provider interface across providers. |
| packages/evolution/src/sdk/provider/internal/Ogmios.ts | Updates Ogmios delegation response schema to match v6 array shape. |
| packages/evolution/src/sdk/provider/internal/KupmiosEffects.ts | Fixes delegation parsing and decodes pool id to PoolKeyHash. |
| packages/evolution/src/sdk/provider/internal/KoiosEffect.ts | Fixes Koios pool-id decoding from bech32. |
| packages/evolution/src/sdk/provider/internal/Koios.ts | Implements Koios UTxO mapping for inline datums, datum hashes, and reference scripts. |
| packages/evolution/src/sdk/provider/internal/BlockfrostEffect.ts | Fixes datum fetch endpoint/schema to retrieve CBOR datum content. |
| docs/content/docs/transactions/retry-safe.mdx | New documentation page explaining retry-safe transaction pipelines. |
| docs/content/docs/transactions/meta.json | Adds retry-safe to transactions docs navigation. |
| .gitignore | Ignores local env override files (including .env.test.local). |
| .env.test.local.example | Adds a documented template for provider integration test configuration. |
| .changeset/fix-provider-conformance.md | Changeset documenting provider fixes as a patch release. |
Files not reviewed (1)
- pnpm-lock.yaml: Language not supported
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| /** | ||
| * Provider integration tests — all 4 providers in one place. | ||
| * | ||
| * Koios: always opt-in via `describe.skip` (public endpoint, no key needed). |
There was a problem hiding this comment.
The header comment says Koios is opt-in via describe.skip, but the code uses describe.skipIf(!process.env.KOIOS_ENABLED). Update the comment to reflect the actual opt-in mechanism (env var + skipIf) to avoid misleading contributors configuring the integration tests.
| * Koios: always opt-in via `describe.skip` (public endpoint, no key needed). | |
| * Koios: opt-in via `KOIOS_ENABLED` env var (public endpoint, no key needed). |
|
|
||
| const parseHeaderJson = (value: string | undefined) => { | ||
| if (!value || value.trim() === "") return undefined | ||
| return JSON.parse(value) as Record<string, string> |
There was a problem hiding this comment.
parseHeaderJson calls JSON.parse at module import time. If a user sets KUPMIOS_*_HEADER_JSON to invalid JSON, the entire test file will throw before describe.skipIf can skip anything. Consider wrapping the parse in a try/catch and either return undefined or throw a clearer error only when the Kupmios suite is actually enabled.
| return JSON.parse(value) as Record<string, string> | |
| try { | |
| return JSON.parse(value) as Record<string, string> | |
| } catch { | |
| return undefined | |
| } |
| expect(datum).toBeDefined() | ||
| }) | ||
|
|
||
| it("awaitTx", { timeout: 0 }, async () => { |
There was a problem hiding this comment.
This test sets timeout: 0, which disables Vitest's timeout entirely. If any provider's awaitTx implementation hangs due to an upstream outage/bug, the test run can block indefinitely. Prefer a large but finite timeout (or rely on the provider's own timeout) so enabled integration runs fail fast instead of hanging.
| it("awaitTx", { timeout: 0 }, async () => { | |
| it("awaitTx", { timeout: 120_000 }, async () => { |
…on pool id decode
Three providers were returning incorrect or missing data due to stale field paths, wrong endpoint URLs, and missing mapping logic that was never caught without a conformance test harness.
Koios:getDelegationdecoded pool IDs withFromHexinstead ofFromBech32, causing a decode error on every delegated account.getUtxosalways returneddatumOption: nullandscriptRef: null— inline datums, datum hashes, and script references were never populated.Kupmios:getDelegationusedObject.values(result)[0]on an Ogmios v6 array response and readdelegate.idinstead ofstakePool.id, so pool ID was always wrong; the value was also a raw bech32 string rather than a decodedPoolKeyHash.Blockfrost:getDatumcalled/scripts/datum/{hash}which returns only the hash — the correct endpoint is/scripts/datum/{hash}/cbor.