Conversation
There was a problem hiding this comment.
Issues
Medium — Missing error boundary on decodePreparedTransaction
clearSigning.ts — no guard against calling this with topology bytes. utils.extractCantonCommandInfo will throw if proto parsing fails, and the caller gets an unhandled exception. The JSDoc says "Only meaningful when detectCantonSigningPayloadType() returns CANTON_SIGN_TRANSACTION" but that is documentation, not enforcement. Should either:
- Throw a descriptive error:
throw new Error("Not a PreparedTransaction — call detectCantonSigningPayloadType first") - Or add a test for the invalid-input path so the failure mode is documented
Medium — Duplicate getSignablePayload implementation
cantonSignTransactionMessage.ts and cantonSignTopologyMessage.ts have byte-for-byte identical getSignablePayload() bodies:
this.signablePayload = Buffer.from(this.payload, "base64");
return this.signablePayload;The only difference between the two classes is the type passed to super(). Consider extracting to a shared CantonBaseMessage extends BaseMessage to avoid future drift.
Low — @ts-ignore → prefer @ts-expect-error
clearSigning.ts:3:
// @ts-ignore – JS resource with hand-written .d.ts@ts-expect-error will error if the suppression becomes unnecessary (e.g. when the .d.ts is replaced with proper types), making the tech debt visible.
Low — Redundant test
In canton.ts, the test "tcanton should also return true" fetches tcanton again, but before() already sets basecoin = bitgo.coin("tcanton"). Two tests asserting the same inherited method on the same coin instance.
Positives
- Clean factory pattern —
getMessageBuilderswitch + clear error on unsupported type - Payload-type detection via try/catch on proto parse is the right approach (nodes-length check is correct discriminator since proto is permissive)
- JSDoc on
clearSigning.tsis genuinely useful — explains the HSM format split clearly - Good edge case test coverage (empty bytes, random bytes, proto parse failure)
There was a problem hiding this comment.
Remaining Nits
Nit — Double proto parse in decodePreparedTransaction happy path
clearSigning.ts — the guard calls detectCantonSigningPayloadType() (which parses the proto via PreparedTransaction.fromBinary), then utils.extractCantonCommandInfo() parses the same bytes a second time. For invalid input the guard throws early so no waste, but valid input pays two full proto decodes. Not a correctness issue, but worth noting if Canton transactions are large. Could be addressed by combining into a single parse-and-decode function if perf ever matters.
Nit — Unnecessary constructor in CantonBaseMessage
cantonBaseMessage.ts:15-17 — the constructor only calls super(options) with no other logic. TypeScript synthesizes this automatically; the explicit constructor is dead weight and can be removed.
Summary
Both are nits, not blockers. The core logic is solid — error guard, base class extraction, and test coverage for invalid input are all well done. LGTM otherwise.
Ticket: CHALO-545
There was a problem hiding this comment.
LGTM
Two minor observations (not blocking):
-
MessageBuilderFactorypass-through constructor — same pattern that was cleaned up inCantonBaseMessage;constructor(coinConfig) { super(coinConfig); }can be removed since TypeScript synthesizes it. -
Misleading test name —
cantonSignTopologyMessage.ts:"should produce same byte structure as CANTON_SIGN_TRANSACTION for equivalent hash"only instantiatesCantonSignTopologyMessage; never creates aCantonSignTransactionMessageto compare against. The assertion is correct but the name implies a cross-type comparison that does not happen.
Approving.
Ticket: CHALO-545