The Koios provider drops native reference scripts. db-sync stores no CBOR for native scripts before the Dijkstra era (cardano-db-sync Era/Shelley/Generic/Tx/Alonzo.hs:318-322). Koios therefore returns reference_script.bytes: null for timelock and multisig scripts. toUTxO requires the bytes (packages/evolution/src/sdk/provider/internal/Koios.ts:199), so the UTxO comes back with no scriptRef and no error. The type can also be multisig, which the switch there does not handle.
Fix: for native scripts with null bytes, rebuild the script from reference_script.value and check it against reference_script.hash. Keep the bytes path for Dijkstra-era outputs.
A related question: /utxo_info also returns spent outputs (files/grest/rpc/transactions/utxo_info.sql, is_spent), so getUtxosByOutRef can return them. Kupmios asks Kupo for ?unspent only, while Blockfrost returns spent outputs too. The Provider interface does not say which behavior it expects.
The Koios provider drops native reference scripts. db-sync stores no CBOR for native scripts before the Dijkstra era (
cardano-db-syncEra/Shelley/Generic/Tx/Alonzo.hs:318-322). Koios therefore returnsreference_script.bytes: nullfor timelock and multisig scripts.toUTxOrequires the bytes (packages/evolution/src/sdk/provider/internal/Koios.ts:199), so the UTxO comes back with noscriptRefand no error. The type can also bemultisig, which the switch there does not handle.Fix: for native scripts with null bytes, rebuild the script from
reference_script.valueand check it againstreference_script.hash. Keep the bytes path for Dijkstra-era outputs.A related question:
/utxo_infoalso returns spent outputs (files/grest/rpc/transactions/utxo_info.sql,is_spent), sogetUtxosByOutRefcan return them. Kupmios asks Kupo for?unspentonly, while Blockfrost returns spent outputs too. TheProviderinterface does not say which behavior it expects.