Closed cliffoo closed 1 year ago
Hey @haltman-at could you grab this branch and find all the TODO
s and figure out which ones warrant addressing before an initial release?
Hey @haltman-at could you grab this branch and find all the
TODO
s and figure out which ones warrant addressing before an initial release?
Sure thing! There appear to be only 48 of them, so that sounds doable. :)
- Should we limit the exposed interfaces more?
Yeah I think we should only expose what is clearly useful externally (at least to start)
Hey @haltman-at could you grab this branch and find all the
TODO
s and figure out which ones warrant addressing before an initial release?
OK, I took a look. There's one big problem that runs throughout these, which is that the errors typically don't say what errors they are.
If we ignore that problem, most of these seem fine for an initial release. There's only one I think that definitely needs filling in, one more that maybe needs filling in but possibly doesn't, and ten more that maybe need filling in but likely don't. The rest I'm pretty sure can wait.
The one I think definitely needs some changes is the StorageNotSuppliedError
. This one comes up all the time in the debugger -- it's what we use for storage that the debugger doesn't know about because it hasn't been accessed so far during the transaction. In the CLI debugger, we display it as a gray question mark. This is common, people will see it, it should have some sort of appropriate display. Note it doesn't necessarily need to make use of the actual information in the error! Like I said, in the CLI it's just a gray question mark. But something that indicates to the user, there is a value here, we just don't know it.
Then we have the storage read error; this one I wouldn't say definitely needs to be fill in, but I'd say it should likely be filled in. It strikes me as moderately likely to come up; if there's a second one of these you should fix, beyond the StorageNotSuppliedError
, it's this one. The information that's displayed for this one is basically meaningless. I was going to suggest making use of the slotAddressPrintout
function in Format.Utils.Exception
to present more useful information, except, oops, it turns out that function isn't exported. So, uh, I suggest making that function exported and then using it. :)
The rest of these are ones that potentially need filling in, but are likely skippable; idk, I'll let you figure that out. First, the ones that affect both MetaMask and the debugger:
format.values.contract-value-info-known.tsx:7: // TODO
format.values.function-external-value-info-invalid.tsx:8: // TODO
format.values.function-external-value-info-known.tsx:8: // TODO
format.values.function-external-value-info-unknown.tsx:8: // TODO
The first one stood out to me because, hey, even though we know the name of the contract, we're not displaying that, only it's address. But maybe that's OK for an initial release. (I don't think any of these are doing anything with interpretations
either, after all... it's an initial release.)
The other three stood out to me because they show the selector but not the address. (Also other info, but previous paragraph applies to that.) That's distinctly losing information! They should include the address as well as the selector. Of course, if your stance is that external function pointers are unlikely to come up, then maybe you can skip it in the initial release on the basis of it just not being a common case.
Now the ones that can affect the debugger only and not MetaMask:
format.errors.function-external-stack-padding-error.tsx:8: // TODO
format.values.function-internal-value-info-known.tsx:8: // TODO
format.values.function-internal-value-info-exception.tsx:8: // todo
format.values.function-internal-value-info-unknown.tsx:8: // todo
format.errors.deployed-function-in-constructor-error.tsx:8: // todo
format.errors.no-such-internal-function-error.tsx:8: // todo
Here, the first one is for the same reasons I said above regarding external functions. Of course, since this is an error rather than a value, it may be even less likely to come up, and so even less in need of filling in.
The next two apply to internal functions but it's similar; for the known case, rather than just displaying the name, the class name should also be there somewhere, while for the exception case, you probably don't want to show the PC value but rather some sort of message about how this pointer is uninitialized. But once again, if your stance is that internal function pointers probably won't show up, then likely this is skippable.
The next three of these also relate to internal functions, and they oddly just display the constructor PC? Makes more sense to display both PCs, I think. Except that really these are even less likely to come up than the previous two so most likely these are skippable.
Everything else seems definitely skippable for an initial release.
Change of plans we'll leave docs to do later.
Prelease
Map
@truffle/codec
types to react components.Try it
CodeSandbox
A simple e2e (nextjs) project using fetch and compile, decoder, and codec components to show some WETH stuff.
Usage
The docs don't make a lot of sense yet and I'm in the process of improving it. Will link here when ready.
Files
src/react
src/react/
index.ts
@truffle/codec-components/react
.utils/
createCodecComponent
andcreateCommonComponent
.components/codec/
@truffle/codec
.Coverage: All of
Codec.Format.Values
,Codec.Format.Errors
, every top-level decoding interface and type.File names: Codec type (kebab-case), joined by
"."
with namespace(s), if any.components/common/
components/codec/
.components/providers/
CodecComponentsProvider
for external use (to customize descendant components).contexts/
scss.d.ts
.scss
files.More details
- **Internal contexts and providers.** The individual components often need additional information to know how to display data correctly, and context turns out to be a suitable solution. E.g. `src/utils
src/utils/
index.ts
custom-errors.ts
ComponentDataTypeIsNeverError
class, thrown by codec components whose corresponding type resolves tonever
.codec.ts
@truffle/codec
.type-guards
More details
- **Copied code from @truffle/codec** `import { Format } from "@truffle/codec"; Format.Types.typeStringWithoutLocation(...)` and `import { stringValueInfoToStringLossy } from "@truffle/codec/**"` both cause errors require polyfills (looks like it tries to resolve `util.inspect`, among other things), which we don't want to deal with. Implementation for `typeStringWithoutLocation` and `typeString` are copied over from `@truffle/codec`. `stringValueInfoToStringLossy` uses `Buffer`, so we just display bytes for `StringValueInfoMalformed` instead of utf-8. - **Type-guards** Type-guards are used by components to resolve types that are often a union of many other types/interfaces (like `Codec.Format.Result`), which allows components whose corresponding types are complex to depend on the implementation of components of "simpler" types. This of course also ensures type safety. For each category of type-guards there is a helper function that, by similar rationale as above, help to make type-guards of complex types using the output of type-guards of simpler types. - **Utils not packaged** We might want to [move type-guards](https://github.com/trufflesuite/truffle/pull/5945) in the future, since their implementation does not exactly belong in a ui component library. For now everything inside `src/utils/` is for internal use only to avoid semver complications.src/docs
src/docs/
data/
content.tsx
data/
index.tsx
assets/
index.html
styles.module.scss
More details
- **Storybook**? Storybook looked like a fine solution and was used for a while, but as I wrote more stories I found: - It was way too much boilerplate. - It's hard to bend it your way, which means that it would only be good as a dev server, and not for generating docs (not without a lot of tweaking) as I initially wanted. This implies a separate solution for docs. I also experimented with astro, but the I had problems with it hydrating data that involves `bn.js` (possibly related to using react 16?), tried it with different `client:*` directives to no avail. In the end I landed on simple SPA solution with vite. It's used as a dev server and for generating docs. The sample data itself is in a format portable enough that we can move it to some other solution in the future if we wish.scripts
and misc.scripts/api-extractor.json
scripts/build.js
src/react
.react.d.ts
vite.config.js
.gitignore
tsconfig.json
package.json
More details
- **Api extractor** `tsc` outputs declaration files mirroring the structure of the source files, separate and in directories at different levels. It works, but without rolling them up into a single file, it brings up a number of issues, which I didn't want to overlook when considered as a whole: - Encapsulation: It would be possible to import types from a subpath (deeper than `@truffle/codec-components/*`) that may break in the future. - Slower type-checking if `skipLibCheck` is off. - Increased build size. Unfortunately I had trouble with different plugins that are meant to integrate with vite, and had to resort to an external tool like api extractor, which has excess functionalities. I had hoped that I can avoid having a config file, but it is [discouraged by ms](https://api-extractor.com/pages/setup/invoking/#reusing-settings-across-projects), and creating configs programmatically requires working with interfaces that exist but are undocumented.React 16
MM is still using react 16 so we need to support that. Fortunately this doesn't have a lot of implications besides having a seemingly unused
import React from "react"
in every.tsx
file, since thereact/jsx-runtime
and its automatic import is only available in >=17.Open questions:
Type-guards can still be useful to users who want more control to customize complex components. This is probably something we should provide, but this package isn't the right place.
In line with the intent behind not exposing type-guards to end-users for semver reasons, we might also want to keep some things internal, namely utility functions that create components,
and maybe internal contexts and providers. Internal contexts and providers should be public since they are very useful for customization, though that likely involves breaking changes from time to time, but I guess we just have to try and stabilize it < 1.0.Before release
Codec.Format.Values
types, namely function types.Soon after release
string[]
,mapping(int32 => address)
)Later