-
-
Notifications
You must be signed in to change notification settings - Fork 227
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
Allow TypedDataUtils
to be called unbound
#152
Allow TypedDataUtils
to be called unbound
#152
Conversation
9ede8b9
to
910deeb
Compare
function hashStruct( | ||
primaryType: string, | ||
data: Record<string, unknown>, | ||
types: Record<string, MessageTypeProperty[]>, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here is the parameter type adjustment that was required to eliminate type errors. Clearly this is required because it's passed straight to encodeData
, which itself required the types
parameter to be of this type.
field.type, | ||
// TODO: Add validation to ensure this is a string-indexed | ||
// object, so that this type cast can be removed | ||
value as Record<string, unknown>, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here's the first type assertion that was required. This should be guaranteed to be a Record<string, any>
for any properly formatted message, but we don't have sufficient type information at this point to guarantee that. We can add that later.
sanitizedData.domain, | ||
hashStruct( | ||
// TODO: Validate that this is a string, so this type cast can be removed. | ||
sanitizedData.primaryType as string, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here's the second type assertion that was required. At first it looked like this was already guaranteed to be a string, because primaryType
is a keyof the MessageTypes
object, and that's string-indexed. But apparently TypeScript is screwy when it comes to index types, and it happily allows using a number
index as well (I tested it to be sure), despite this attempt at preventing that. So technically this could be a number. But that's clearly against the spec, and it's clearly what we were trying to prevent with that type.
We can shore this up later with runtime validation. Or better types. Or both.
test/index.ts
Outdated
@@ -1389,3 +1389,122 @@ test('signedTypeMessage V4 with recursive types', (t) => { | |||
'0xf2ec61e636ff7bb3ac8bc2a4cc2c8b8f635dd1b2ec8094c963128b358e79c85c5ca6dd637ed7e80f0436fe8fce39c0e5f2082c9517fe677cc2917dcd6c84ba881c', | |||
); | |||
}); | |||
|
|||
test('unbound sign typed data utility functions', (t) => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I tested that these all failed on the main
branch.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
will need to be converted to jest
style to go along with this PR: #161
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done!
I'd strongly recommend hiding whitespace when looking at this diff. It's a mess when whitespace is shown because everything was de-indented. |
useV4 = true, | ||
): Buffer { | ||
const encodedTypes = ['bytes32']; | ||
const encodedValues: unknown[] = [hashType(primaryType, types)]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This was another type change that was required. TypeScript assumed that this was supposed to be a Buffer
array because the first entry was a Buffer
. But it looks like it's just an array of unknown data, not just of buffers.
*/ | ||
function hashType( | ||
primaryType: string, | ||
types: Record<string, MessageTypeProperty[]>, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This parameter type changed for the same reason as hashStruct
* @returns {Buffer} - keccak hash of the resulting signed message | ||
*/ | ||
function eip712Hash<T extends MessageTypes>( | ||
typedData: TypedData | TypedMessage<T>, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This was never actually passed in Partial<>
data. Also sanitizeData
requires that the typed data be complete.
910deeb
to
982c020
Compare
Just rebased this onto |
982c020
to
3343934
Compare
Havent touched this repo yet, but the changes to typings look good, +1 for removal of |
c8ee6a8
to
d1b3605
Compare
Thanks for the review @shanejonas! Just had to rebase this to resolve conflicts. The diff should be identical now except for the tests, which now need "V4" specified explicitly in a few places due to the consolidation PR that was merged. |
d1b3605
to
cf0663c
Compare
Previously the functions exposed as `TypedDataUtils` could only be called from the `TypedDataUtils` object. If they were called unbound, they would throw errors because of the use of `this`. They have all been updated to no longer rely upon `this`, so they now work the same way regardless how they are bound when called. They are still exported as the `TypedDataUtils` object, so this should not change the API. This was done to simplify the code, specifically to make it easier for functions outside of `TypedDataUtils` to reuse code inside of `TypedDataUtils`. Some types required adjustments, as type mistakes were brought to light that TypeScript for some reason wasn't aware of when these were declared as properties of the `TypedDataUtils` object. These were fixed by adding two type assertions, making the `types` parameter to `hashStruct` and `hashType` more strict, and by making the `typedData` parameter to `eip712Hash` more strict. The type assertions (warranted or not) preserve the types used previously. We can replace them later with validation.
00a876d
to
807aeae
Compare
Previously the functions exposed as
TypedDataUtils
could only be called from theTypedDataUtils
object. If they were called unbound, they would throw errors because of the use ofthis
.They have all been updated to no longer rely upon
this
, so they now work the same way regardless how they are bound when called.They are still exported as the
TypedDataUtils
object, so this should not change the API. This was done to simplify the code, specifically to make it easier for functions outside ofTypedDataUtils
to reuse code inside ofTypedDataUtils
.Some types required adjustments, as type mistakes were brought to light that TypeScript for some reason wasn't aware of when these were declared as properties of the
TypedDataUtils
object. These were fixed by adding two type assertions, making thetypes
parameter tohashStruct
andhashType
more strict, and by making thetypedData
parameter toeip712Hash
more strict. The type assertions (warranted or not) preserve the types used previously. We can replace them later with validation.