# Wallet

## Overview

Base layer assets are often used in Cartesi applications.
Cartesi supports bridging ETH from the base layer to your application as well as 3 additional token standards: ERC-20, ERC-721 and ERC-1155.

Bridging works by interacting with portal smart contracts developed by Cartesi and deployed to all supported networks.
Those contracts lock the assets on the base layer, assigning their ownership to the application smart contract, and sending an input to the InputBox contract notifying the application about the transfer.
This notification includes what asset was transferred and who transferred it, allowing the application to credit the user's internal application balance accordingly.

## Deposit

The `@deroll/wallet` module provides an in-memory implementation of a wallet management that automatically takes care of receiving asset notification from portals, and providing a simple API for querying, transferring inside the application, and creating vouchers to withdraw back to the base layer.

:::code-group
```bash [pnpm]
$ pnpm add @deroll/wallet
```

```bash [npm]
npm install @deroll/wallet
```

```bash [bun]
bun add @deroll/wallet
```
:::

You start by creating a wallet object using the `createWallet` function, and then adding the wallet handler to the application.

```ts twoslash
/// <reference types="node" />
// ---cut---
import { Rollup } from "@cartesi/rollup";
import { createWallet } from "@deroll/wallet"; // [!code ++]

// open the rollup device
const rollup = new Rollup();

// create wallet // [!code ++]
const wallet = createWallet(); // [!code ++]

rollup.run({
    advance: wallet.handler, // [!code ++]
});
```

The `wallet.handler` will take care of intercepting the inputs sent from the Cartesi portals, decoding the information, and storing users assets information in an in-memory data structure.

You can then, as an example, query the CTSI balance in an inspect handler:

```ts twoslash
/// <reference types="node" />
// ---cut---
import { Rollup } from "@cartesi/rollup";
import { createWallet } from "@deroll/wallet";
import { numberToHex, toHex } from "viem"; // [!code ++]

// open the rollup device
const rollup = new Rollup();

// create wallet
const wallet = createWallet();

rollup.run({
    advance: wallet.handler,
    inspect: (request, rollup) => { // [!code ++]
        const address = toHex(request.payload); // [!code ++]
        const balance = wallet.erc20BalanceOf( // [!code ++]
            "0x491604c0FDF08347Dd1fa4Ee062a822A5DD06B5D", // [!code ++]
            address, // [!code ++]
        ); // [!code ++]
        rollup.emitReport(numberToHex(balance)); // [!code ++]
    }, // [!code ++]
});
```

A complete API documentation is available in the [reference section](/app/wallet/overview).

## Withdraw

Assets deposited to an application through a portal are owned on the base layer by the application smart contract.
Users can withdraw their deposited assets by creating vouchers that can be executed on the base layer, after the voucher proofs are generated (usually once a week).

The `wallet` object provides several `withdraw` methods that creates vouchers that can be generated as output.
The following example creates a voucher to withdraw 1 CTSI to the user that sent the input.
If the user doesn't have enough balance an exception is raised, which rejects the input and emits the error as a report.

```ts twoslash
/// <reference types="node" />
// ---cut---
import { Rollup, chain } from "@cartesi/rollup"; // [!code ++]
import { createWallet } from "@deroll/wallet";
import { hexToBigInt, numberToHex, toHex } from "viem"; // [!code ++]

// open the rollup device
const rollup = new Rollup();

// create wallet
const wallet = createWallet();

rollup.run({
    // the wallet claims portal deposits; anything else falls through // [!code ++]
    advance: chain(wallet.handler, (request, rollup) => { // [!code ++]
        const amount = hexToBigInt(toHex(request.payload)); // [!code ++]
        const voucher = wallet.withdrawERC20( // [!code ++]
            "0x491604c0FDF08347Dd1fa4Ee062a822A5DD06B5D", // [!code ++]
            request.msgSender, // [!code ++]
            amount, // [!code ++]
        ); // [!code ++]
        rollup.emitVoucher(voucher); // [!code ++]
        return true; // [!code ++]
    }), // [!code ++]

    inspect: (request, rollup) => {
        const address = toHex(request.payload);
        const balance = wallet.erc20BalanceOf(
            "0x491604c0FDF08347Dd1fa4Ee062a822A5DD06B5D",
            address,
        );
        rollup.emitReport(numberToHex(balance));
    },
});
```

## Utility functions

Instead of using the wallet module handler, and the wallet in-memory data structure, you can also decode deposits yourself with the [`@cartesi/codec`](https://cartesi.github.io/rollups-ts/codec) package and take care of managing balances or creating vouchers, using the voucher utility functions provided by the `@deroll/wallet` module.

The following code snippet handles ERC-20 deposits manually, and just creates a voucher to return the deposited amount.

```ts twoslash
/// <reference types="node" />
// ---cut---
import { decodeDeposit } from "@cartesi/codec";
import { Rollup } from "@cartesi/rollup";
import { createERC20TransferVoucher } from "@deroll/wallet";

// open the rollup device
const rollup = new Rollup();

rollup.run({
    advance: (request, rollup) => { // [!code focus]
        const deposit = decodeDeposit({ // [!code focus]
            msgSender: request.msgSender, // [!code focus]
            payload: request.payload, // [!code focus]
        }); // [!code focus]
        if (deposit?.type === "Erc20Deposit") { // [!code focus]
            const voucher = createERC20TransferVoucher( // [!code focus]
                deposit.token, // [!code focus]
                deposit.sender, // [!code focus]
                deposit.value, // [!code focus]
            ); // [!code focus]
            rollup.emitVoucher(voucher); // [!code focus]
        } // [!code focus]
        return true; // [!code focus]
    }, // [!code focus]
});
```
