---
# System prepended metadata

title: LIfecycle of a wallet API

---

# LIfecycle of a wallet API

### Keyring Builder

Every wallet must export a `keyringBuilder`. This function will be called and must return a `keyring`. Type of `keyringBuilder` is defined below:

```typescript!
export type keyringBuilder = {
  (): Keyring;
  uid: string;
};
```

`uid` is used as a global unique identifier for a `keyringBuilder`. For example a simple-account's `keyringBuilder` is described as:

```typescript!
export const SimpleAccountKeyringBuilder = () => {
  return new SimpleAccountKeyring();
};

SimpleAccountKeyringBuilder.uid = 'npm:@epf-wallet/simple-account';
```

You can use `keyringBuilder` to pass custom properties in the constructor of your `keyring` or call init functions if you want to.

### Deserialize

Once the `keyring` is returned from the `keyringBuilder`, we will next be calling the `deserialize` function with the data the last stored state of the keyring in local storage. We call the `serialize` function to get the latest state on `keyring` and store it in local storage. [Click here](#serialize) to know more about serialize funtion.

```typescript!
deserialize: (data: any) => Promise<void>;
```

### Serialize

`serialize` function is called whenever one of the below listed functions occcus:

1. New vault is created
2. New keyring is added
3. New account is added
4. An account is removed
5. keyring is removed
6. keyring-controller is unmounted or stopped

Everytime the function `serialise` is called, the keyring must return the latest state of keyring that must be stored in the localstorage so that keyring can be initialised with this state later in time using `deserialize` function.

```typescript!
serialize: () => Promise<any>;
```

### Add an account

A custom user field input might be needed whenever an account is added to a keyring. For this the keyring must expose the function `defineNewAccountView`. The input fields returned by this will be displayed to the user and user input will be passed on to the function `addAccount`.

```typescript!
type KeyringInputError = {
    error: boolean;
    message: string;
}

type KeyringViewInputField = {
    type: 'input' | 'QR' | 'number' | '...etc';
    name: string; // any unique name for this input
    displayName: string;
    displayDescription: string;
    placeholder: string;
    isValid: (value: any) => Promise<KeyringInputError>;
    defaultValue: () => Promise<value>;
}

type KeyringView = {
    title: string;
    description: string;
    inputs: Array<KeyringViewInputField>;
}

// defineNewAccountView defination
// No custom user input will be required if the function returns undefined.
defineNewAccountView: () => Promise<KeyringView | undefined>;
```

```typescript!
type KeyringViewUserInput = {
    // name key is KeyringViewInputField.name
    [name: string]: any;
}

addAccount: (userInputs: KeyringViewUserInput, chainId: number) => Promise<string> // public address
```

Wallet must store `KeyringViewUserInput` internally and may return it in serialised state, as this input will never be sent again to the `keyring`. When the function `getInitCode` will be called for a specific address, then the keyring must use the internally stored `userInputState` to generate a valid `initCode`.

### Get init code

The function `getInitCodeAndNonce` will always be called after `addAccount` has been called and it must return the deployment initcode with the default nonce value that must be sent in the user operation. No custom input will be sent to this function, keyring must store the custom input corresponding to an address in the `addAccount` function. This is becuase the wallet may not be deployed during the initiation phase and maybe deployed later with the first transaction.

```typescript!\
type InitCodeAndNonce = {
    initCode: Bytes | string;
    nonce: BigNumber | Bytes | bigint | string | number;
}

getInitCodeAndNonce: (publicAddress: string) => Promise<InitCodeAndNonce>;
```

### Get userOperation signature

A custom user field input might be needed whenever a signature is needed for a transaction. For this the keyring must expose the function `defineGetSignatureView`. The input fields returned by this will be displayed to the user and user input will be passed on to the function `signUserOperation`.

```typescript!
// defineGetSignatureView defination
// No custom user input will be required if the function returns undefined.
defineGetSignatureView: (partialUserOp: Partial<UserOperationStruct>) => Promise<KeyringView | undefined>;
```

We will be passing the `partialUserOp` to the function where the keyring can take a look at the `callData` and decide which inputs to take from the user.

The above entered values will then be passed to the `signUserOperation` function.

```typescript!
signUserOperation: (partialUserOp: Partial<UserOperationStruct>, userInputs: KeyringViewUserInput, chainId: number) => Promise<UserOperationStruct>
```