IntersectMBO / IntersectMBO/cardano-api

cardano-wasm: gRPC-Web UTxO glue incompatible with shipped v1beta protobuf bundle

Open
#1,323 0 comments 0 reactions 0 assignees View on GitHub
bug WASM
Dominant language
Haskell
Stars
40
Forks
30
Avg merge
2d 5h
Merged PRs (30d)
30

Description

## Summary

The cardano-wasm JS glue is written against the obsolete `utxorpc.v1alpha` API, while the shipped browser bundle is generated from this repo's v1beta protos (`nix/proto-to-js.nix:17` uses `cardano-rpc-src = ../cardano-rpc`).
As a result the core UTxO-reading API of the browser SDK does not work against the in-repo proto and server.
Wallets depending on it cannot read balances.
It fails closed (exception or empty list), so there is no on-chain fund loss.

## Concrete breaks

### 1. `getUtxosForAddress` throws an unconditional `TypeError`

`GRPC.hs:51-54` references `proto.utxorpc.v1alpha.cardano.AddressArray` and calls `req.setCardanoAddresses()`.
Neither exists in v1beta: `ReadUtxosRequest` only has `keys` + `field_mask` (`query.proto:101-104`).
Every call throws before any network request is made.

### 2. `getAllUtxos` always returns empty

`js_readAllUtxos` sends a keyless `ReadUtxosRequest`.
The v1beta server deliberately returns an empty response for that (`Query.hs:95`: "Returns an empty response when no keys are provided").
This means a silent zero balance for every wallet built on the SDK.

### 3. `BigInt(utxo.cardano.coin)` type mismatch

The glue assumes a scalar `coin`, but the v1beta `TxOutput.coin` is a `BigInt` message `{int|bigUInt|bigNInt}` (`cardano.proto:36,256-262`).
It would throw a `BigInt(object)` `TypeError` if the UTxO list were ever non-empty.

Note: `js-test/basic-test.golden` never exercises the gRPC paths, so the breakage is untested in-repo.

## Reproduction

1. Inspect the JS emitted by `GRPC.hs:51-54`:
```js
let addresses = new proto.utxorpc.v1alpha.cardano.AddressArray();
addresses.addItems(btoa($2));
req.setCardanoAddresses(addresses);
```
2. Inspect the shipped bundle's schema (generated from v1beta): `ReadUtxosRequest` fields are only `keys` + `field_mask`. `utxorpc.v1alpha.cardano.AddressArray` does not exist in the bundle.
3. Server side: `Query.hs:95` - a keyless `ReadUtxosRequest` returns `defMessage` (empty).

Any wallet calling `getUtxosForAddress(addr)` throws `TypeError: proto.utxorpc.v1alpha.cardano.AddressArray is not a constructor`.
`getAllUtxos()` always resolves to `[]`.

## Suggested fix

Regenerate the JS glue against the v1beta protos.
Use `ReadUtxosRequest.keys` for address lookups.
Parse `coin` from the v1beta `BigInt` message fields (`int` as `Number`, `bigUInt` as base64 big-endian bytes converted to `BigInt`).

---

Originally reported by @Ranchhand87 as security advisory GHSA-6f73-hf45-g35g.
Converted to a public issue since it fails closed and has no security impact.

Contributor guide

Open the contributing guide

Research direction

Start with GRPC.hs:51-54 and compare its generated JS against the v1beta ReadUtxosRequest fields in query.proto:101-104 and the shipped bundle. Then read Query.hs:95 and cardano.proto:36,256-262 to trace keyless requests and coin representations. Done means getUtxosForAddress and getAllUtxos work with the v1beta server and non-empty coin values no longer cause a type error.

Written by the indexing model from the issue text.

Assessment

Tech stack
grpc, haskell, javascript
Domain
api, backend, blockchain
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Clearly specified
Newbie friendliness
48/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.