Structured data message signing
Structured data signing is slightly different from simple message signing, in that rather than passing an arbitrary message string, you are passing some kind of Clarity value to be signed, likely to also be used in the context of a Clarity smart contract.
Usage
@micro-stacks/react
exports a hook to use, useOpenSignStructuredMessage
. The hook returns a
callback, openSignStructuredMessage
which takes a message
of type string
or ClarityValue
value. This method will accept a hex encoded clarity value, or a ClarityValue
. Check out the page
on Clarity Values to learn more about them.
isRequestPending
is also returned, a boolean value to denote if there is a current request open
(meaning the user has already requested a signature). The pending state is handled all internally for
every wallet request, so you don't need to manually handle any loading logic.
As with all of the hooks that interact with the wallet, you can also pass an onFinish
and
onCancel
callback.
import { useOpenSignStructuredMessage } from '@micro-stacks/react';
Example
Below you will find a component that renders an input and a button. The input is captured in a useState
hook, and
converted into a Clarity tuple
, with the input value being converted to a stringAscii
clarity value. This message
is
then piped into the openSignStructuredMessage
callback, wrapped in a useCallback
hook.
import * as React from 'react';
import { stringAsciiCV, tupleCV } from 'micro-stacks/clarity';
import { useOpenSignStructuredMessage } from '@micro-stacks/react';
const SignMessageComponent = () => {
const { openSignStructuredMessage, isRequestPending } = useOpenSignStructuredMessage();
const [payload, setPayload] = React.useState(null);
const [value, setValue] = React.useState('');
const message = tupleCV({
message: stringAsciiCV(value),
});
const onClick = React.useCallback(async () => {
await openSignStructuredMessage({
message,
onFinish: walletResponse => {
setPayload(walletResponse);
},
});
}, [message]);
return (
<div
style={{
display: 'grid',
gap: '20px',
}}
>
<h5>Sign a message!</h5>
<input
style={{ display: 'block' }}
onChange={e => setMessage(e.currentTarget.value)}
/>
<button onClick={onClick}>{isRequestPending ? 'Loading...' : 'Sign message'}</button>
<code>
<pre>{JSON.stringify(payload, null, 2)}</pre>
</code>
</div>
);
};
Verification
To verify a signed structured message, you can import verifyStructuredMessageSignature
from
micro-stacks/connect
.
Example
import { stringAsciiCV, tupleCV } from 'micro-stacks/clarity';
import { verifyStructuredMessageSignature } from 'micro-stacks/connect';
// original message
const message = tupleCV({
message: stringAsciiCV('hi there'),
});
// from the wallet
const payload = {
signature: '0c956388e3bf84a2873b2fdd...c3fbefdbd48cecf2e01',
publicKey: '035b08fd4d14786187f51a33...4665fa437a9ad22bbdf7ae716d4599f26943a7',
};
const isValid = verifyStructuredMessageSignature({
message,
signature: payload.signature,
publicKey: payload.publicKey,
});