Request a Signature
Many applications require users to authorize actions by providing a digital signature. This could be for signing a message, consenting to terms, or approving an on-chain transaction. DID Connect provides two distinct claims to handle these scenarios: signature and prepareTx.
- Use the
signatureclaim when you have the complete data you want the user to sign. - Use the
prepareTxclaim when your application creates a partial transaction and needs the user's wallet to provide the remaining inputs (like funds or assets) before signing.
This guide will walk you through how to use both.
The Signing Flow#
At a high level, requesting a signature involves your application defining the claim, the SDK presenting it to the user's wallet, and your application handling the signed response.
Use signature for General-Purpose Signing#
Use the signature claim when the data to be signed is fully known by your application. This is ideal for signing messages, login challenges, or fully-formed transactions that just need the user's signature.
Signing a Plain Text Message#
Here's how to ask a user to sign a simple welcome message. The origin field contains the data to be signed, which must be a Base58-encoded buffer.
const { WalletHandlers } = require('@arcblock/did-connect');
const { toBase58 } = require('@ocap/util');
// ... inside your Express route setup ...
handlers.attach({
app,
action: 'sign-message',
onAuth: (req, res) => {
// The wallet's response, including the signature, is in the claims object
console.log('Signature received:', req.did_connect.claims);
// You can now verify the signature and complete the user's action
res.json({ ok: 1, message: 'Signature received!' });
},
claims: {
signature: {
typeUrl: 'mime:text/plain', // Specify the data type
description: 'Please sign this welcome message to confirm your identity.',
origin: toBase58(Buffer.from('Welcome to our dApp! Please sign to continue.')),
},
}
});Signing a Pre-Encoded Transaction#
For on-chain operations, you can construct and encode a transaction in your backend, then pass it to the wallet for signing. This gives you full control over the transaction's contents.
You'll need a library like @ocap/client to encode the transaction according to the target chain's format. In this example, we set typeUrl to fg:t:transaction to tell the wallet it's handling a Forge-compatible transaction.
const { WalletHandlers } = require('@arcblock/did-connect');
const { toBase58 } = require('@ocap/util');
const Client = require('@ocap/client');
const { fromAddress } = require('@ocap/wallet');
// ...
const client = new Client('https://beta.abtnetwork.io/api');
handlers.attach({
app,
action: 'sign-tx',
onAuth: (req, res) => {
console.log('Transaction signed:', req.did_connect.claims);
// You can now broadcast the signed transaction
res.json({ ok: 1, message: 'Transaction signed!' });
},
claims: {
signature: async ({ userDid }) => {
// This function runs when the user connects their wallet
const { buffer: txBuffer } = await client.encodeTransferV2Tx({
tx: {
itx: {
to: 'zNKjDm4Xsoaffb19UE6QxVeevuaTaLCS1n1S', // Application's address
tokens: [
{
address: 'z35nB2SA6xxBuoaiuUXUw6Gah2SNU3UzqdgEt', // Token address
value: '1000000000000000000', // 1 ABT
},
],
},
},
wallet: fromAddress(userDid), // Set the sender from the connected user
});
return {
typeUrl: 'fg:t:transaction',
description: 'Please sign to confirm the 1 ABT transfer.',
origin: toBase58(txBuffer), // The base58-encoded transaction buffer
};
},
},
});signature Claim Parameters#
Parameter | Type | Description |
|---|---|---|
|
| Required. Specifies the type of data being signed. Common values: |
|
| The Base58-encoded data to be signed. Use this when you provide the full data. |
|
| The pre-calculated hash (digest) of the data. Use this if you want to sign a hash instead of the full data. |
|
| The hashing algorithm the wallet should apply to |
|
| A stringified JSON object to provide a rich display in the wallet (e.g., |
|
| A human-readable message shown to the user in the wallet prompt. |
|
| An optional object specifying tokens or assets the user must own to be able to sign. |
Use prepareTx for Collaborative Transactions#
Use the prepareTx claim when your application can only create a partial transaction and needs the user's wallet to supply the remaining inputs, such as payment tokens or assets. The wallet will complete the transaction, sign it, and return the result.
This is common in payment scenarios where the application knows the recipient and amount but doesn't know which specific tokens the user will pay with.
const { toBase58 } = require('@ocap/util');
// Assume partialTxBuffer is a partially encoded transaction buffer from ocap/client
// It might contain the recipient and memo, but not the inputs.
handlers.attach({
app,
action: 'purchase-item',
onAuth: (req, res) => {
console.log('Transaction prepared and signed:', req.did_connect.claims);
res.json({ ok: 1, message: 'Purchase complete!' });
},
claims: {
prepareTx: {
description: 'Please complete this payment to purchase the Awesome NFT.',
partialTx: toBase58(partialTxBuffer),
requirement: {
tokens: [
{
address: 'z35nB2SA6xxBuoaiuUXUw6Gah2SNU3UzqdgEt', // ABT token address
value: '10000000000000000000', // 10 ABT
},
],
},
display: JSON.stringify({ type: 'url', content: 'https://.../item-image.png' }),
},
},
});prepareTx Claim Parameters#
Parameter | Type | Description |
|---|---|---|
|
| Required. A Base58-encoded buffer of the partially-formed transaction. |
|
| Required. An object specifying what the user's wallet needs to provide to complete the transaction. |
|
| An array of token objects, each with |
|
| An object specifying digital assets (NFTs) the user must contribute. Can filter by |
|
| A stringified JSON object for rich display in the wallet. |
|
| A human-readable message explaining the action to the user. |
Now you know how to request signatures for both simple messages and complex transactions. Often, a signature is just one step in a larger user journey.
To learn how to combine multiple claims into a single, seamless flow, proceed to the next guide on Chaining Multiple Workflows.