IntersectMBO / IntersectMBO/cardano-api
cardano-wasm: gRPC-Web UTxO glue incompatible with shipped v1beta protobuf bundle
- 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
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