Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: improve string type safety #145

Merged
merged 21 commits into from
Nov 30, 2021
Merged

refactor: improve string type safety #145

merged 21 commits into from
Nov 30, 2021

Conversation

mkazlauskas
Copy link
Member

@mkazlauskas mkazlauskas commented Nov 23, 2021

Context

Currently all string types are simple aliases of string. We have a lot of different types of strings for keys and hashes and we should utilize TypeScript to ensure that the string we get is the correct type that is not ambiguous.

Proposed Solution

Convert all string type aliases to more restricted types and validate them when creating. (BREAKING)

Important Changes Introduced

  • Add dependency to bech32 package
  • Add ProviderFailure.InvalidResponse
  • Rename certificate fields from address to rewardAccount where appropriate (BREAKING)
  • Convert transaction witness, Assets and TokenMap to Map (BREAKING)

Follow-up work

  • Address type doesn't accept base58-encoded Byron addresses and Address.util.isAddress does consider it valid. We need to decide whether we want to support it. If we do, there will be more code changes with CSL usage.
  • Might be a good idea to write more e2e tests with Blockfrost to ensure hash types are aligned. If we do that, we should dig up testnet transactions with certificates. What is the easiest way to do that?
  • There might still some type aliases from Ogmios used implicitly via nested types. I did not check every single type imported from Ogmios, but this PR converted the important string type aliases that we use and I suggest to convert the remainder (if there are any) as we go.

Copy link
Member

@rhyslbw rhyslbw left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm wondering if we'll have a cleaner model by removing the types/Strings/ path withing src/Cardano, and just have say src/Cardano/StakePool.ts, since this module contains more than type definitions, and using the primitive type to categorise is a bit redundant for a domain layer. Not a blocker, but just wanted to mention it before proceeding with the others.

image

@mkazlauskas
Copy link
Member Author

I'm wondering if we'll have a cleaner model by removing the types/Strings/ path withing src/Cardano, and just have say src/Cardano/StakePool.ts, since this module contains more than type definitions, and using the primitive type to categorise is a bit redundant for a domain layer. Not a blocker, but just wanted to mention it before proceeding with the others.

Sure, let's do that

rhyslbw
rhyslbw previously approved these changes Nov 24, 2021
@mkazlauskas mkazlauskas force-pushed the refactor/type-safety branch 2 times, most recently from 10c34ec to d326a17 Compare November 24, 2021 17:22
@mkazlauskas mkazlauskas marked this pull request as ready for review November 25, 2021 14:47
// TODO: need to find an example of this to verify type and length
// This is the type we use for witness object keys too, which kinda
// makes sense to have as bech32, because you might want to display
// it to the user to show who signed the tx

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(Hello! I’m new to Cardano. I want to start contributing in one way or another! The future of global finances etc etc)

What about making an issue instead of a TODO comment? The issue could be linked to this PR (as a comment on this line) and anybody looking to collaborate could try to pick it up later.

I also think that bech32 sounds good for the reasons stated in this comment, so I wonder: why not just making it bech32?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @sadasant, thanks for the contribution 👍

We find annotating the code keeps it fresh in mind during this early development phase, with the todos reflected in our internal project management system. We're currently reserving Github issues for external submissions, but we'll move to a more traditional OS model with contributor guidelines once things stabilise. As it stands, code contributions would be considered, but we're just not actively seeking them right now.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @sadasant, thank you for a review! It is currently validated as bech32 with ed25519_pk prefix.

@rhyslbw some extra context for this TODO: Blockfrost doesn't seem to support requiredExtraSignatures field and I don't see it in cardano-graphql docs. This field is from Ogmios types and it's a Hash16 in there.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This Ogmios test vector has b5ae663aaea8e500157bdf4baafd6f5ba0ce5759f7cd4101fc132f54 (56 chars):

https://raw.githubusercontent.com/CardanoSolutions/ogmios/master/server/test/vectors/ChainSync/Response/RequestNext/135.json

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would you prefer our type to be hex as in ogmios instead of bech32?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, no as you were. In general we should be using the bech32 version if a prefix has been defined in the CIP

Copy link
Member Author

@mkazlauskas mkazlauskas Nov 29, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Prefix ed25519_pk that it currently uses is not listed in cip5 and CSL's PublicKey.to_bech32() does not accept a prefix argument. I think what we want is addr_vk and stake_vk prefixes. I already added a dependency to bech32 npm package so we can create the appropriate string from PublicKey.as_bytes()

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(Thank you for your answers, @rhyslbw and @mkazlauskas 🙏)

@sadasant
Copy link

This PR looks really good! Makes the project way more robust in multiple fronts. I also appreciate the tests!

packages/blockfrost/src/blockfrostWalletProvider.ts Outdated Show resolved Hide resolved
packages/blockfrost/test/blockfrostWalletProvider.test.ts Outdated Show resolved Hide resolved
packages/core/src/Cardano/types/AuxiliaryData.ts Outdated Show resolved Hide resolved
packages/core/src/Cardano/types/StakePool/StakePool.ts Outdated Show resolved Hide resolved
// TODO: need to find an example of this to verify type and length
// This is the type we use for witness object keys too, which kinda
// makes sense to have as bech32, because you might want to display
// it to the user to show who signed the tx
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This Ogmios test vector has b5ae663aaea8e500157bdf4baafd6f5ba0ce5759f7cd4101fc132f54 (56 chars):

https://raw.githubusercontent.com/CardanoSolutions/ogmios/master/server/test/vectors/ChainSync/Response/RequestNext/135.json

@rhyslbw
Copy link
Member

rhyslbw commented Nov 29, 2021

Address type doesn't accept base58-encoded Byron addresses and Address.util.isAddress does consider it valid. We need to decide whether we want to support it. If we do, there will be more code changes with CSL usage.

All wallets need capability to send to legacy addresses, as they are still considered valid addresses just with limited utility.

Copy link
Member

@rhyslbw rhyslbw left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Awesome work here @mkazlauskas 🎉

Please note the conventional commits standard for representing breaking changes:

image

The reason I've not rejected the commits here is that we're not maintaining a stable API yet and pre-production minor versioning is not based on breaking changes, but moving forward it will be good to get into the habit so these details are second nature post-1.0. standard-version interprets this to decide the next version, so it's imperative for automating the release process, in addition to the benefits the standard brings to developers.

@@ -1,16 +1,57 @@
import { AssetFingerprint, AssetId, AssetName, PolicyId } from '../../../src/Cardano';
import { AssetFingerprint, AssetId, AssetName, PolicyId, util } from '../../../src/Cardano';
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice tests, very expressive.

@rhyslbw rhyslbw merged commit 365e7a6 into master Nov 30, 2021
@rhyslbw rhyslbw deleted the refactor/type-safety branch November 30, 2021 03:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants