npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

safe-recovery-service-sdk

v0.0.4

Published

Safe Recovery Service SDK by Candidelabs

Readme

Safe Recovery Service SDK

TypeScript SDK by Candidelabs for interacting with the Safe Social Recovery Module. Enables guardian-based account recovery, custodial guardian services via email/SMS, and alert subscriptions for recovery events.

Looking for runnable code? Jump to the examples →

Installation

npm install safe-recovery-service-sdk
# or
yarn add safe-recovery-service-sdk

Overview

The SDK exposes three main classes:

| Class | Purpose | |---|---| | RecoveryByGuardian | Manage recovery requests with your own guardian keys | | RecoveryByCustodialGuardian | Register email/SMS channels with Candide's guardian service | | Alerts | Subscribe to email/SMS notifications for recovery events |


RecoveryByGuardian

Use this when you control your own guardian wallets. Guardians sign recovery requests off-chain; the service handles on-chain execution.

import { RecoveryByGuardian } from "safe-recovery-service-sdk";
import { SocialRecoveryModuleGracePeriodSelector } from "abstractionkit";

const recoveryService = new RecoveryByGuardian(
    "https://recovery.candide.dev",
    84532n, // Base Sepolia
    SocialRecoveryModuleGracePeriodSelector.After7Days
);

// Create a recovery request with the first guardian signature
const request = await recoveryService.createRecoveryRequest(
    safeAddress,
    [newOwnerAddress],
    1,               // new threshold
    guardian1Address,
    guardian1Signature
);
// request.emoji — share with other guardians to verify request authenticity

// Collect additional guardian signatures until threshold is met
await recoveryService.submitGuardianSignatureForRecoveryRequest(
    request.id,
    guardian2Address,
    guardian2Signature
);

// Execute, wait grace period, then finalize
await recoveryService.executeRecoveryRequest(request.id);
// ... wait grace period ...
await recoveryService.finalizeRecoveryRequest(request.id);

Recovery requests follow the lifecycle: PENDINGEXECUTEDFINALIZED


RecoveryByCustodialGuardian

Use this to register email and/or SMS channels with Candide's guardian service. Candide acts as the guardian and signs recovery requests after you verify your identity via OTP.

import { RecoveryByCustodialGuardian } from "safe-recovery-service-sdk";
import {
    getSafeMessageEip712Data,
    SAFE_MESSAGE_PRIMARY_TYPE,
    SafeAccountV0_3_0,
} from "abstractionkit";

const guardian = new RecoveryByCustodialGuardian(
    "https://recovery.candide.dev",
    84532n
);

// 1. Generate and sign the registration SIWE message (EIP-1271 Safe message format)
const siweMessage = guardian.createRegistrationToEmailRecoverySiweStatementToSign(
    safeAddress,
    "[email protected]"
);
const typedData = getSafeMessageEip712Data(safeAddress, chainId, siweMessage);
const ownerSig = await ownerAccount.signTypedData({
    ...typedData,
    primaryType: SAFE_MESSAGE_PRIMARY_TYPE
});
const signature = SafeAccountV0_3_0.buildSignaturesFromSingerSignaturePairs([
    { signer: ownerAccount.address, signature: ownerSig }
]);

// 2. Register and verify via OTP
const challengeId = await guardian.createRegistrationToEmailRecovery(
    safeAddress, "[email protected]", siweMessage, signature
);
await guardian.submitRegistrationChallenge(challengeId, otpCode);

// 3. Trigger recovery — verify identity via OTP on each registered channel
const signatureRequest = await guardian.requestCustodialGuardianSignatureChallenge(
    safeAddress, [newOwnerAddress], 1
);
const result = await guardian.submitCustodialGuardianSignatureChallenge(
    signatureRequest.requestId,
    signatureRequest.auths[0].challengeId,
    otpCode
);

// 4. Execute recovery with the guardian signature
await guardian.createAndExecuteRecoveryRequest(
    safeAddress,
    [newOwnerAddress],
    1,
    result.custodianGuardianAddress,
    result.custodianGuardianSignature
);

Alerts

Subscribe to email or SMS notifications when recovery events occur on a Safe.

import { Alerts } from "safe-recovery-service-sdk";

const alerts = new Alerts("https://recovery.candide.dev", 84532n);

// 1. Sign a SIWE message with a plain EOA signMessage (no EIP-712 needed)
const siweMessage = alerts.createEmailSubscriptionSiweStatementToSign(
    safeAddress, ownerAddress, "[email protected]"
);
const signature = await ownerAccount.signMessage({ message: siweMessage });

// 2. Create and activate the subscription
const subscriptionId = await alerts.createEmailSubscription(
    safeAddress, ownerAddress, "[email protected]", siweMessage, signature
);
await alerts.activateSubscription(subscriptionId, otpCode);

// 3. List active subscriptions
const authMessage = alerts.getSubscriptionsSiweStatementToSign(ownerAddress);
const authSig = await ownerAccount.signMessage({ message: authMessage });
const active = await alerts.getActiveSubscriptions(
    safeAddress, ownerAddress, authMessage, authSig
);

Alerts are triggered when a recovery request is initiated, executed, or finalized.


Grace Periods

Choose a grace period when deploying the Social Recovery Module. The grace period is the window during which the original owner can cancel an unauthorized recovery before it finalizes.

| Selector | Grace Period | Use | |---|---|---| | SocialRecoveryModuleGracePeriodSelector.After3Minutes | 3 minutes | Testing only | | SocialRecoveryModuleGracePeriodSelector.After3Days | 3 days | Production | | SocialRecoveryModuleGracePeriodSelector.After7Days | 7 days | Production | | SocialRecoveryModuleGracePeriodSelector.After14Days | 14 days | Production |


Error Handling

All methods throw SafeRecoveryServiceSdkError on failure:

import { SafeRecoveryServiceSdkError } from "safe-recovery-service-sdk";

try {
    await recoveryService.createRecoveryRequest(/* ... */);
} catch (error) {
    if (error instanceof SafeRecoveryServiceSdkError) {
        console.error(error.stringify()); // structured output with code and context
    }
}

Error codes: SIWE_ERROR, HTTP_ERROR, BAD_DATA, TIMEOUT, UNKNOWN_ERROR


Examples

The examples/ directory contains three runnable examples that walk through the full flow in order:

| # | Example | What it does | |---|---|---| | 01 | 01-enable-email-sms-recovery | Deploy a Safe, register email/SMS with Candide Guardian, add guardian on-chain | | 02 | 02-alerts-setup | Subscribe to email/SMS recovery event notifications | | 03 | 03-recovery-flow | Trigger a recovery via OTP, wait grace period, finalize |

cd examples
yarn install
cp .env.example .env
# Fill in .env, then run in order:
yarn dev:enable-email-sms-recovery   # prints OWNER_PRIVATE_KEY + SAFE_ACCOUNT_ADDRESS — copy into .env
yarn dev:alerts-setup
yarn dev:recovery-flow

See examples/README.md for full setup instructions.


Development

yarn install
yarn build    # compile to dist/
yarn test     # run tests
yarn clean    # remove dist/

Links

License

MIT