fix(provider): tolerate Koios Haskell show string in asset_list and add awaitTx timeout#203
Merged
solidsnakedev merged 4 commits intomainfrom Mar 14, 2026
Merged
Conversation
…dd awaitTx timeout option
…w regression test
Contributor
There was a problem hiding this comment.
Pull request overview
This PR improves awaitTx reliability across providers by making timeouts configurable and hardening Koios response parsing when asset_list is returned as a Haskell show-formatted string (instead of JSON).
Changes:
- Extend
awaitTxacross Koios/Blockfrost/Maestro/Kupmios to accept an optionaltimeout. - Make Koios
InputOutputSchema.asset_listtolerant of string values by decoding them tonull. - Add/extend integration tests (including an opt-in Koios preview test and a conformance timeout/rejection check).
Reviewed changes
Copilot reviewed 14 out of 14 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| packages/evolution/test/provider/providers.test.ts | Adds opt-in Koios Preview integration test for the asset_list string decoding case. |
| packages/evolution/test/provider/fixtures/constants.ts | Introduces a preview-only tx hash fixture used by new tests. |
| packages/evolution/test/provider/conformance.ts | Extends conformance tests with longer awaitTx timeout and a rejection test for a preview-only tx. |
| packages/evolution/src/sdk/provider/internal/MaestroEffect.ts | Adds timeout parameter and applies Effect.timeout to stop infinite polling. |
| packages/evolution/src/sdk/provider/internal/KupmiosEffects.ts | Adds timeout parameter and uses it in Effect.timeout. |
| packages/evolution/src/sdk/provider/internal/KoiosEffect.ts | Adds timeout parameter and uses it in Effect.timeout. |
| packages/evolution/src/sdk/provider/internal/Koios.ts | Updates Koios schema to tolerate string asset_list by decoding to null. |
| packages/evolution/src/sdk/provider/internal/BlockfrostEffect.ts | Adds timeout parameter and changes polling behavior to rely on Effect.timeout. |
| packages/evolution/src/sdk/provider/Provider.ts | Extends Provider awaitTx signature to include optional timeout. |
| packages/evolution/src/sdk/provider/Maestro.ts | Threads optional timeout through the public provider wrapper. |
| packages/evolution/src/sdk/provider/Kupmios.ts | Threads optional timeout through the public provider wrapper. |
| packages/evolution/src/sdk/provider/Koios.ts | Threads optional timeout through the public provider wrapper. |
| packages/evolution/src/sdk/provider/Blockfrost.ts | Threads optional timeout through the public provider wrapper. |
| .changeset/fix-koios-asset-list-timeout.md | Documents the patch-level changes for Koios parsing and configurable awaitTx timeouts. |
Comments suppressed due to low confidence (1)
packages/evolution/src/sdk/provider/internal/BlockfrostEffect.ts:1
awaitTxis typed/used as returning a boolean (e.g., conformance expectstrue), but this implementation returns whatevercheckTxreturns on success (currentlySchema.Anyfrom the/txs/{hash}response). Consider mapping the successful HTTP response totrue(e.g., viaEffect.as(true)or equivalent) so the function consistently returnsboolean.
/**
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comment on lines
+595
to
601
| return Effect.retry(checkTx, Schedule.fixed(`${checkInterval} millis`)).pipe( | ||
| Effect.timeout(timeout), | ||
| Effect.catchAllCause( | ||
| (cause) => new ProviderError({ cause, message: "Failed to await transaction confirmation" }) | ||
| ) | ||
| ) | ||
| } |
Comment on lines
+595
to
600
| return Effect.retry(checkTx, Schedule.fixed(`${checkInterval} millis`)).pipe( | ||
| Effect.timeout(timeout), | ||
| Effect.catchAllCause( | ||
| (cause) => new ProviderError({ cause, message: "Failed to await transaction confirmation" }) | ||
| ) | ||
| ) |
| // outputs with many assets). Treat any string as null to avoid a parse failure in those cases. | ||
| asset_list: Schema.Union( | ||
| Schema.NullOr(Schema.Array(AssetSchema)), | ||
| Schema.transform(Schema.String, Schema.Null, { decode: () => null, encode: () => "" }) |
| }) | ||
|
|
||
| it("awaitTx rejects for preview-only tx on preprod", { timeout: 10_000 }, async () => { | ||
| await expect(provider.awaitTx(previewTxHash(), 1000, 5000)).rejects.toThrow() |
| "23f94840ca94f7bb0a5a2b28e5b6a77e61d0414c7427e03d6c4d57b13d5e49b4" | ||
|
|
||
| /** Preview-only tx whose collateral output has a Haskell show string asset_list. | ||
| * Does NOT exist on preprod — used to test awaitTx timeout behavior. */ |
- Assert ProviderError (not just any throw) in the awaitTx rejection test - Update PREVIEW_TX_HASH_HEX comment to document both timeout and Koios asset_list string decoding purposes
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Koios can return
collateral_output.asset_listas a Haskell show-formatted string instead of a JSON array when a collateral output carries many native assets. This causedawaitTxto throw aParseErrorwrapped inProviderErrorfor any transaction with a large collateral output.InputOutputSchema.asset_listnow tolerates strings by converting them tonullviaSchema.Union. All four providers (Koios, Blockfrost, Maestro, Kupmios) now accept an optionaltimeoutparameter onawaitTx, replacing hardcoded internal timeouts. Maestro previously had no timeout at all — itswhile(true)poll loop could spin indefinitely.