Documentation Index
Fetch the complete documentation index at: https://www.dynamic.xyz/docs/llms.txt
Use this file to discover all available pages before exploring further.
getGoogleDriveBackupReadiness is a pre-flight check that tells you whether the user’s linked Google account has the OAuth scopes required to back up MPC key shares to Google Drive. Use it to detect — and recover from — missing-scope situations before triggering an MPC reshare ceremony, so you don’t burn a ceremony on an upload that will fail.
It pairs with the Google Drive backup setup as the first layer of a two-layer defense: pre-flight readiness (this function) catches the common cases; post-flight error inspection (via isInsufficientGoogleDriveScopesError) handles legacy tokens captured before scope tracking was introduced.
Usage
import { getGoogleDriveBackupReadiness } from '@dynamic-labs-sdk/client';
const result = await getGoogleDriveBackupReadiness();
if (result.status === 'ready') {
// Safe to trigger the Google Drive backup flow
}
Parameters
| Parameter | Type | Description |
|---|
client | DynamicClient (optional) | The Dynamic client instance. Only required when using multiple clients. |
Returns
Promise<GoogleDriveBackupReadiness> — resolves to the readiness result.
Failures of the underlying access-token fetch propagate as Promise rejections — the caller is expected to surface or retry them.
GoogleDriveBackupReadiness
type GoogleDriveBackupReadinessStatus = 'ready' | 'needs-access';
type GoogleDriveBackupReadiness = {
status: GoogleDriveBackupReadinessStatus;
missingScopes: readonly string[];
accessToken?: string;
};
| Field | Description |
|---|
status | 'ready' when stored scopes include both required Drive scopes; 'needs-access' when backup is unlikely to succeed without user intervention. |
missingScopes | Scopes the user still needs to grant. See the sub-case table below for how to interpret this in conjunction with status. |
accessToken | The user’s current Google OAuth access token, if one was successfully fetched. Absent when no Google account is linked. |
The 'needs-access' status covers three distinct sub-cases, distinguishable by missingScopes:
| Sub-case | missingScopes | Description |
|---|
| No Google account linked | Full required set (GOOGLE_DRIVE_BACKUP_REQUIRED_SCOPES) | The user hasn’t linked Google yet. Render copy directly without checking the empty case. |
| Some scopes missing | Subset of required scopes | The user linked Google but didn’t grant every required Drive scope on the consent screen. |
| Legacy tokens (unknown scopes) | Empty array | Token was captured before scope tracking shipped. Force a fresh consent to populate the scopes column for subsequent calls. |
Recovering from 'needs-access'
Recovery is the caller’s responsibility — re-link the user’s Google account so the required Drive scopes are granted, then call getGoogleDriveBackupReadiness again before retrying the backup. Use signInWithSocialRedirect with the google provider:
import { signInWithSocialRedirect } from '@dynamic-labs-sdk/client';
await signInWithSocialRedirect({
provider: 'google',
redirectUrl: window.location.href,
});
Examples
Pre-flight check before backup
import {
getGoogleDriveBackupReadiness,
signInWithSocialRedirect,
} from '@dynamic-labs-sdk/client';
const ensureDriveBackupReady = async () => {
const readiness = await getGoogleDriveBackupReadiness();
if (readiness.status === 'ready') {
return true;
}
// 'needs-access' — re-link Google to grant the missing scopes.
// The redirect navigates away; resume the backup flow when the user returns.
await signInWithSocialRedirect({
provider: 'google',
redirectUrl: window.location.href,
});
return false;
};
import {
getGoogleDriveBackupReadiness,
signInWithSocialRedirect,
type GoogleDriveBackupReadiness,
} from '@dynamic-labs-sdk/client';
import { useMutation } from '@tanstack/react-query';
function BackupButton() {
const { mutate, data: readiness, isPending } = useMutation({
mutationFn: () => getGoogleDriveBackupReadiness(),
});
const handleRelink = async () => {
await signInWithSocialRedirect({
provider: 'google',
redirectUrl: window.location.href,
});
};
return (
<>
<button onClick={() => mutate()} disabled={isPending}>
{isPending ? 'Checking…' : 'Check Drive readiness'}
</button>
{readiness?.status === 'needs-access' && (
<button onClick={handleRelink}>Re-link Google account</button>
)}
</>
);
}
Post-flight scope-error recovery
For legacy tokens where pre-flight cannot prove the upload will fail (missingScopes is empty under 'needs-access', or stored scopes were never recorded), wrap the backup attempt in a try/catch and use isInsufficientGoogleDriveScopesError to detect the scope-denied failure mode.
import {
isInsufficientGoogleDriveScopesError,
signInWithSocialRedirect,
} from '@dynamic-labs-sdk/client';
try {
// ...trigger your Google Drive backup flow here
} catch (error) {
if (isInsufficientGoogleDriveScopesError(error)) {
// Re-link Google and retry the backup once the user returns.
await signInWithSocialRedirect({
provider: 'google',
redirectUrl: window.location.href,
});
return;
}
throw error;
}
The same module also exports a few primitives for callers who want to build their own checks:
| Export | Description |
|---|
GOOGLE_DRIVE_BACKUP_REQUIRED_SCOPES | Readonly tuple of the OAuth scopes required for Google Drive backup. |
findMissingGoogleDriveBackupScopes(granted) | Returns the subset of GOOGLE_DRIVE_BACKUP_REQUIRED_SCOPES that are not present in granted. |
hasAllGoogleDriveBackupScopes(granted) | Convenience boolean — true when every required scope is present in granted. |
isInsufficientGoogleDriveScopesError(err) | Type guard for Errors thrown by the backup flow when access was denied due to missing/insufficient scopes. |
import {
GOOGLE_DRIVE_BACKUP_REQUIRED_SCOPES,
findMissingGoogleDriveBackupScopes,
hasAllGoogleDriveBackupScopes,
isInsufficientGoogleDriveScopesError,
} from '@dynamic-labs-sdk/client';
Types
type GoogleDriveBackupReadinessStatus = 'ready' | 'needs-access';
type GoogleDriveBackupReadiness = {
status: GoogleDriveBackupReadinessStatus;
missingScopes: readonly string[];
accessToken?: string;
};