# Add a Social Account as a Recovery Method using Magic

[Magic](https://magic.link) is a popular hosted wallet provider for EOAs, enabling users to log in using authentication methods like Social Logins and Email OTP.

Leverage the full potential of Account Abstraction by combining Magic with AbstractionKit to enable email/social recovery experiences while using a Smart Account to sponsor gas, batch transactions, and more.

Below are some relevant links that provide additional information and resources which you might find helpful as you go through this guide.

* [How on-chain guardian recovery works](https://docs.candide.dev/wallet/plugins/recovery-with-guardians/)
* [Guardian Recovery SDK Reference](https://docs.candide.dev/blog/making-accounts-recoverable/)
* [Simple code example on GitHub](https://github.com/candidelabs/abstractionkit-examples/blob/main/recovery/recovery.ts)
* [Magic Documentation Website](https://magic.link/docs)

## Installation[​](#installation "Direct link to Installation")

### Install required dependencies[​](#install-required-dependencies "Direct link to Install required dependencies")

* ethers
* viem

```
npm i abstractionkit && magic-sdk
```

```
npm i abstractionkit && magic-sdk && viem
```

### Create a Magic account[​](#create-a-magic-account "Direct link to Create a Magic account")

Create an account and get the API key on [Magic's Dashboard](https://dashboard.magic.link). You will need the PUBLISHABLE API KEY.

### Configure .env file[​](#configure-env-file "Direct link to Configure .env file")

Configure the values you created from Magic dashboard in an .env file

```
// magic
PUBLISHABLE_API_KEY=
    
// candide  
BUNDLER_URL=
JSON_RPC_NODE_PROVIDER=
OWNER_PUBLIC_ADDRESS=
NEW_OWNER_PUBLIC_ADDRESS=
```

## Setup Guardian[​](#setup-guardian "Direct link to Setup Guardian")

* ethers
* viem

```
import { 
    SafeAccountV0_3_0 as SafeAccount, 
    SocialRecoveryModule,
} from "abstractionkit";
import { Magic } from "magic-sdk";
import { BrowserProvider } from 'ethers';

const magic = new Magic(process.env.PUBLISHABLE_API_KEY);
const provider = new BrowserProvider(magic.rpcProvider);
const guardianSigner = await provider.getSigner();

const smartAccount = SafeAccount.initializeNewAccount([process.env.OWNER_PUBLIC_ADDRESS]);
    
const srm = new SocialRecoveryModule();
const enableModuleTx = srm.createEnableModuleMetaTransaction(
    smartAccount.accountAddress
);
const addGuardianTx = srm.createAddGuardianWithThresholdMetaTransaction(
    smartAccount.accountAddress, 
    guardianSigner.address, // Magic Guardian Address
    1n //threshold
);

let userOperation = await smartAccount.createUserOperation(
    [enableModuleTx, addGuardianTx],
    process.env.JSON_RPC_NODE_PROVIDER,
    process.env.BUNDLER_URL,
);
```

```
import { SafeAccountV0_3_0 as SafeAccount } from "abstractionkit";
import { Magic } from "magic-sdk";
import { createWalletClient, custom } from "viem";

const magic = new Magic(process.env.PUBLISHABLE_API_KEY);
const guardianSigner = createWalletClient({
  transport: custom(magic.rpcProvider),
});
const guardianAddresses = await signer.getAddresses();
    
const srm = new SocialRecoveryModule();
const enableModuleTx = srm.createEnableModuleMetaTransaction(
    smartAccount.accountAddress
);
const addGuardianTx = srm.createAddGuardianWithThresholdMetaTransaction(
    smartAccount.accountAddress, 
    guardianAddresses[0], // Magic Guardian Address
    1n //threshold
);

let userOperation = await smartAccount.createUserOperation(
    [enableModuleTx, addGuardianTx],
    process.env.JSON_RPC_NODE_PROVIDER,
    process.env.BUNDLER_URL,
);
```

info

To use MagicSigner in your app's client, you must ensure the `window` object is defined. For example, use magic in webapps and not node scripts.

## Initiate Recovery[​](#initiate-recovery "Direct link to Initiate Recovery")

* ethers
* viem

```
import { SafeAccountV0_2_0 as SafeAccount } from "abstractionkit";

const initiateRecoveryMetaTx = createConfirmRecoveryMetaTransaction(
    smartAccount.address, 
    [process.env.NEW_OWNER_PUBLIC_ADDRESS],
    1, // new threshold
    true, // whether to auto-start execution of recovery
);

// make sure to fund the guardian address on magic
// otherwise, you can make the guardian a smart account from the start 
// so you are able to sponsor the gas!
const sendTx1 = guardianSigner.sendTransaction({
    to: initiateRecoveryMetaTx.to,
    data: initiateRecoveryMetaTx.data,
    value: 0,
});
```

```
import { SafeAccountV0_2_0 as SafeAccount } from "abstractionkit";
import { createWalletClient, http } from "viem";

const initiateRecoveryMetaTx = createConfirmRecoveryMetaTransaction(
    smartAccount.address, 
    [process.env.NEW_ONWER_PUBLIC_ADDRESS],
    1, // new threshold
    true, // whether to auto-start execution of recovery
)

// make sure to fund the guardian address on magic
const sendTx1 = await guardianSigner.sendTransaction({
    to: initiateRecoveryMetaTx.to,
    data: initiateRecoveryMetaTx.data,
});
```

## Finilize Recovery[​](#finilize-recovery "Direct link to Finilize Recovery")

Wait for recovery period to pass before finilizing

* ethers
* viem

```
const finalizeRecoveryMetaTx = createFinalizeRecoveryMetaTransaction(smartAccount.accountAddress)
    
// Anyone can call the finilize function after the grace period is over
const sendTx2 = await guardianSigner.sendTransaction({
    to: finalizeRecoveryMetaTx.to,
    data: finalizeRecoveryMetaTx.data,
})
```

```
const finalizeRecoveryMetaTx = createFinalizeRecoveryMetaTransaction(smartAccount.accountAddress)

// Anyone can call the finilize function after the grace period is over
const sendTx2 = await guardianSigner.sendTransaction({
    to: finalizeRecoveryMetaTx.to,
    data: finalizeRecoveryMetaTx.data,
})
```
