Used to check for browser translation.
用于检测浏览器翻译。
ブラウザの翻訳を検出する
Guides

Chaining Workflows


For complex user interactions that require multiple steps, such as a phased registration process or a sequential transaction approval, DID Connect allows you to chain multiple sessions together. This creates a continuous, multi-step workflow for the user, all within their wallet, providing a smooth and uninterrupted experience.

The mechanism for chaining is controlled from the onAuth callback of a DID Connect session. By returning a specific object from this function, you can direct the user's wallet to immediately start a new session.

How It Works#

When a user successfully completes a DID Connect session, the onAuth callback on your server is executed. To initiate the next step in a workflow, this callback should return an object containing the nextWorkflow property.

Property

Type

Description

nextWorkflow

string

The full DID Connect URL for the next session. The wallet will automatically navigate to this URL.

nextToken

string

Optional. The session token for the next workflow. Useful if you want to manage the token on the client side.

nextWorkflowData

object

Optional. A JSON object containing data you want to pass from the current session to the next one.

This process is illustrated below:


Basic Chaining Example#

In this example, after a user provides their profile, the application immediately initiates a second workflow to have them receive a token. The onAuth handler fetches the URL for the next session and returns it.

const axios = require('axios');
const env = require('../../libs/env');

module.exports = {
action: 'claim_multiple_workflow',
claims: {
profile: () => ({
description: 'Please provide your full profile',
fields: ['email'],
}),
},

onAuth: async ({ extraParams: { locale } }) => {
// After the profile is submitted, get the URL for the next step
const { data } = await axios.get(
`${env.appUrl}/api/did/receive_token/token?locale=${locale}&chain=local&amount=random`
);

// Return the URL to the wallet to start the next workflow
return { nextWorkflow: data.url };
},
};

When the wallet receives this response, it will seamlessly start the new session defined by data.url without requiring further user action.

Passing State Between Workflows#

Often, you need to pass context or state from one step to the next, such as carrying over a user ID or an order confirmation. This is achieved using the nextWorkflowData property.

Data passed in nextWorkflowData from Session A will be available in the callbacks of Session B inside the extraParams.previousWorkflowData object. If Session B then chains to Session C, the previousWorkflowData from A is merged with the new nextWorkflowData from B, making all accumulated data available to C.

Example: Multi-Step Registration#

Step 1: Collect Profile

In the first step, we collect the user's profile and pass their DID to the next step.

handlers.attach({
action: 'registration-step-1',
claims: {
profile: () => ({
fields: ['fullName', 'email'],
description: 'Please provide your name and email to start registration.',
}),
},
onAuth: async ({ userDid, claims }) => {
const profile = claims.find((x) => x.type === 'profile');
// Save the user profile to the database
await db.users.create({ did: userDid, ...profile });

// Get URL for the next step
const { data } = await axios.get(`${server.url}/api/did/registration-step-2/token`);

return {
nextWorkflow: data.url,
// Pass the user's DID to the next workflow
nextWorkflowData: { userDid: userDid, step: 1 },
};
},
});

Step 2: Agree to Terms

In the second step, we use the userDid from the previous step to link the agreement to the correct user. The extraParams.previousWorkflowData object contains the data from the first step.

handlers.attach({
action: 'registration-step-2',
// The onConnect callback receives data from the previous step
onConnect: ({ userDid, extraParams }) => {
const previousData = extraParams.previousWorkflowData;
// previousData is { userDid: '...', step: 1 }

if (userDid !== previousData.userDid) {
throw new Error('Please use the same DID you registered with.');
}

// Return the agreement claim for the user to sign
return {
agreement: () => ({
uri: 'https://example.com/terms-of-service.txt',
description: 'Please agree to our Terms of Service.',
}),
};
},
onAuth: async ({ userDid, claims }) => {
// ... Save the agreement confirmation for the user ...
return { successMessage: 'Registration complete!' };
},
});

This pattern allows you to build complex, stateful workflows that feel like a single, cohesive process to the end-user.


Now that you understand how to chain workflows, you can explore more advanced connection patterns. Continue to the next guide to learn about Delegated Connect.