# Asset deposits and withdrawals

## Asset deposits and withdrawals

Applications may want to enable users to:

* Deposit assets on L1 to L2 (note these <mark style="color:blue;">pre-requisites</mark>)
* Withdraw assets from L2 to L1

For more information and use cases, see our explanatory article, <mark style="color:blue;">Deep dive into deposits and withdrawals</mark>.

**Deposit pre-requisites:**[**​**](https://docs.x.immutable.com/docs/x/how-to-enable-deposits-withdrawals#deposit-pre-requisites)

* The user depositing the asset must be <mark style="color:blue;">registered with</mark> XpansionChain
* The user must own the asset on L1
* The L1 smart contract holding the asset must be <mark style="color:blue;">registered as a collection</mark>

📝GUIDES

* <mark style="color:blue;">Core SDK</mark>
* <mark style="color:blue;">API</mark>
* Link SDK:
  * <mark style="color:blue;">Deposits</mark>
  * <mark style="color:blue;">Prepare withdrawal and complete withdrawal</mark>

### Core SDK[​](https://docs.x.immutable.com/docs/x/how-to-enable-deposits-withdrawals#core-sdk) <a href="#core-sdk" id="core-sdk"></a>

#### 1. Initialize the Core SDK[​](https://docs.x.immutable.com/docs/x/how-to-enable-deposits-withdrawals#1-initialize-the-core-sdk) <a href="#id-1-initialize-the-core-sdk" id="id-1-initialize-the-core-sdk"></a>

In order to use the Core SDK, you need to <mark style="color:blue;">initialize it</mark>.

#### 2. Generate signers[​](https://docs.x.immutable.com/docs/x/how-to-enable-deposits-withdrawals#2-generate-signers) <a href="#id-2-generate-signers" id="id-2-generate-signers"></a>

Enabling users to transfer assets requires a user's signature, so your application will need to create signers. See the guide on <mark style="color:blue;">how to generate signers</mark>.

#### 3. Deposit assets onto L2 <a href="#id-3-deposit-assets-onto-l2" id="id-3-deposit-assets-onto-l2"></a>

* Typescript Core SDK

📚SDK REFERENCE

* <mark style="color:blue;">deposit</mark>

The function below will deposit ETH from L1 to L2. If you wish to deposit a different asset, you can change `type` to either `ERC20` or `ERC721` and specify the asset address as an additional parameter.

```
(async (): Promise<void> => {
  // Create deposit
  const deposit = await client.deposit(ethSigner, {
    // ethSigner obtained from generating signer

    type: 'ETH', // There are three avaible types: ETH, ERC20, ERC721
    amount: '50000000000000000', // Amount in wei, this currently is 0.05 ETH
  });
  // console.log(deposit); // Uncomment to see the deposit object
})().catch((e) => {
  log.error(component, e);
});
```

#### Example response[​](https://docs.x.immutable.com/docs/x/how-to-enable-deposits-withdrawals#example-response) <a href="#example-response" id="example-response"></a>

```
{
  type: 2, // Transaction type, currently 2 means EIP-1559
  chainId: 5, // The Chain ID of the network, 5 is the Chain ID for Goerli.
  nonce: 5, // The nonce of the transaction used
  maxPriorityFeePerGas: BigNumber { _hex: '0x59682f00', _isBigNumber: true }, // Maximum fee to bribe miners into giving this transaction priority
  maxFeePerGas: BigNumber { _hex: '0x5968cf94', _isBigNumber: true }, // The maximum fee per gas that the sender is willing to pay
  gasPrice: null, // The gas price of the transaction determined by the network
  gasLimit: BigNumber { _hex: '0x013617', _isBigNumber: true }, // The maximum amount of gas that the transaction can use
  to: '0x7917eDb51ecD6CdB3F9854c3cc593F33de10c623', // The address of the recipient
  value: BigNumber { _hex: '0xb1a2bc2ec50000', _isBigNumber: true }, // The amount of ETH to send in wei
  data: '0x00aeef8a02f9a87a2eae83e024312ea33e2bec5df10cdef1470f6aaf5d5adb23f735a60002705737cd248ac819034b5de474c8f0368224f72a0fda9e031499d519992d9e000000000000000000000000000000000000000000000000000000000001ed7a', // Data included in this log
  accessList: [], // Optional list of addresses and storage keys the transaction can access
  hash: '0x357d6e1c09cf09b5746279bb77377b2353deb1c538eb18c8c9fa9e2363aa3d58', // The hash of the transaction
  v: 0, // The recovery ID of the ECDSA signature
  r: '0xc02c07ff0f80405f34917c9e300abff5da7dda319828fe1843a06f041cd3cbf5', // The first 32 bytes of the ECDSA signature
  s: '0x5c08b76a9ab9f766b82e6f273a1503d064d1604b8e071d7267a6735c5900bb1c', // The second 32 bytes of the ECDSA signature
  from: '0xF656956cA54778056f1191791876db54Aa6eb61B', // The address of the sender
  confirmations: 0, // The number of confirmations that the transaction has received
  wait: [Function (anonymous)] // A function that returns a promise that resolves when the transaction is mined
}
```

* Kotlin (JVM) Core SDK

📚SDK REFERENCE

* <mark style="color:blue;">Deposits API</mark>

* Swift Core SDK

📚SDK REFERENCE

* <mark style="color:blue;">Deposits API</mark>

* Golang Core SDK

📚SDK REFERENCE

* ETH deposit:
  * <mark style="color:blue;">NewETHDeposit</mark>
  * <mark style="color:blue;">(\*ETHDeposit) Deposit</mark>
* ERC20 deposit:
  * <mark style="color:blue;">NewERC20Deposit</mark>
  * <mark style="color:blue;">(\*ERC20Deposit) Deposit</mark>
* ERC721 deposit:
  * <mark style="color:blue;">NewERC721Deposit</mark>
  * <mark style="color:blue;">(\*ERC721Deposit) Deposit</mark>

#### 4. Withdraw assets to L1[​](https://docs.x.immutable.com/docs/x/how-to-enable-deposits-withdrawals#4-withdraw-assets-to-l1) <a href="#id-4-withdraw-assets-to-l1" id="id-4-withdraw-assets-to-l1"></a>

* Typescript Core SDK

📚SDK REFERENCE

* <mark style="color:blue;">prepareWithdrawal</mark>

* <mark style="color:blue;">completeWithdrawal</mark>

* Kotlin (JVM) Core SDK

📚SDK REFERENCE

* <mark style="color:blue;">createWithdrawal</mark>

* <mark style="color:blue;">getSignableWithdrawal</mark>

* Swift Core SDK

📚SDK REFERENCE

* <mark style="color:blue;">getSignableWithdrawal</mark>

* <mark style="color:blue;">createwithdrawal</mark>

* Golang Core SDK

📚SDK REFERENCE

* <mark style="color:blue;">PrepareWithdrawal</mark>
* Complete withdrawal for token types:
  * <mark style="color:blue;">(\*EthWithdrawal) CompleteWithdrawal</mark>
  * <mark style="color:blue;">(\*ERC20Withdrawal) CompleteWithdrawal</mark>
  * <mark style="color:blue;">(\*ERC721Withdrawal) CompleteWithdrawal</mark>

💻EXAMPLE

* <mark style="color:blue;">Withdrawal</mark>

### API[​](https://docs.x.immutable.com/docs/x/how-to-enable-deposits-withdrawals#api) <a href="#api" id="api"></a>

* <mark style="color:blue;">Deposit</mark>
* <mark style="color:blue;">Withdrawal</mark>

#### Deposit[​](https://docs.x.immutable.com/docs/x/how-to-enable-deposits-withdrawals#deposit) <a href="#deposit" id="deposit"></a>

To understand what is going on under the hood with asset deposits, please see <mark style="color:blue;">this explainer</mark>.

**Steps:**[**​**](https://docs.x.immutable.com/docs/x/how-to-enable-deposits-withdrawals#steps)

1. <mark style="color:blue;">Get details of the deposit</mark>
2. <mark style="color:blue;">Generate signers</mark>
3. <mark style="color:blue;">Call contract method to deposit tokens</mark>

**1. Get details of the deposit**[**​**](https://docs.x.immutable.com/docs/x/how-to-enable-deposits-withdrawals#1-get-details-of-the-deposit)

💡ENDPOINT:

* <mark style="color:blue;">getSignableDeposit</mark>

***Javascript example of depositing ETH from L1 to L2:***

```
import fetch from 'node-fetch';

const depositDetails = {
  amount: '0.001',
  token: {
    type: 'ETH',
    data: {
      decimals: 18,
    },
  },
  user: '0x..', // Public L1 Ethereum address
};

fetch('https://api.sandbox.x.XpansionChain.com/v1/signable-deposit-details', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
  },
  body: JSON.stringify(depositDetails),
})
  .then((response) => {
    console.log(response);
  })
  .catch((err) => {
    console.error(err);
  });
```

**Example response:**

```
{
    "amount": "string", // Amount this user is depositing
    "asset_id": "string", // ID of the asset this user is depositing (applicable only to depositing ERC721)
    "nonce": 0, // Random number generated of this transaction to verify that specific values are not reused
    "stark_key": "string", // Public stark key of the depositing user
    "vault_id": 0 // ID of the vault this user is depositing to
}
```

The following response params are used in the <mark style="color:blue;">depositEth</mark> contract method (see <mark style="color:blue;">Step 3</mark>):

* `stark_key`
* `vault_id`

**2. Generate signers**[**​**](https://docs.x.immutable.com/docs/x/how-to-enable-deposits-withdrawals#2-generate-signers-1)

Enabling users to deposit assets requires a user's signature, so your application will need to create signers. See the guide on <mark style="color:blue;">how to generate signers</mark>.

**3. Call contract method to deposit tokens**[**​**](https://docs.x.immutable.com/docs/x/how-to-enable-deposits-withdrawals#3-call-contract-method-to-deposit-tokens)

```
import { Contracts, Config } from '@imtbl/core-sdk';

const config = Config.SANDBOX;

// Get instance of core contract
const contract = Contracts.Core.connect(
  config.ethConfiguration.coreContractAddress,
  ethSigner
);

// Populate and send transaction
const populatedTransaction = await contract.populateTransaction.depositEth(
  starkPublicKey, // Use `stark_key` obtained in previous step
  assetType, // "ETH", "ERC20" or "ERC721"
  vaultId // Use `vault_id` obtained in previous step
);

const transactionResponse = await ethSigner.sendTransaction(
  populatedTransaction
);
```

#### Withdrawal[​](https://docs.x.immutable.com/docs/x/how-to-enable-deposits-withdrawals#withdrawal) <a href="#withdrawal" id="withdrawal"></a>

To understand what is going on under the hood with asset withdrawals, please see <mark style="color:blue;">this explainer</mark>.

**Steps:**[**​**](https://docs.x.immutable.com/docs/x/how-to-enable-deposits-withdrawals#steps-1)

1. <mark style="color:blue;">Get details of the withdrawal</mark>
2. <mark style="color:blue;">Generate signers</mark>
3. <mark style="color:blue;">Create withdrawal</mark>
4. Call contract to complete withdrawal

**1. Get details of the withdrawal**[**​**](https://docs.x.immutable.com/docs/x/how-to-enable-deposits-withdrawals#1-get-details-of-the-withdrawal)

💡ENDPOINT:

* <mark style="color:blue;">getSignableWithdrawal</mark>

***Javascript example of withdrawing ETH from L2 to L1:***

```
import fetch from 'node-fetch';

const withdrawalDetails = {
  amount: '0.001',
  token: {
    type: 'ETH',
    data: {
      decimals: 18,
    },
  },
  user: '0x..', // Public L1 Ethereum address
};

fetch('https://api.sandbox.x.XpansionChain.com/v1/signable-withdrawal-details', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
  },
  body: JSON.stringify(withdrawalDetails),
})
  .then((response) => {
    console.log(response);
  })
  .catch((err) => {
    console.error(err);
  });
```

**Example response:**

```
{
    "amount": "string",
    "asset_id": "string",
    "nonce": 0,
    "payload_hash": "string",
    "signable_message": "string",
    "stark_key": "string",
    "vault_id": 0
}
```

Explanation:

<table data-header-hidden><thead><tr><th width="216.33333333333331"></th><th></th><th></th></tr></thead><tbody><tr><td>Response param</td><td>Description</td><td>How is it used in the <mark style="color:blue;">createWithdrawal</mark> request?<br>(See <mark style="color:blue;">Step 3)</mark></td></tr><tr><td><code>amount</code></td><td>Amount of token to be withdrawn to L1</td><td>As <code>amount</code> in the request body</td></tr><tr><td><code>asset_id</code></td><td>ID of the asset this user is withdrawing (applicable only to <code>ERC721</code> asset type)</td><td>As <code>asset_id</code> in the request body</td></tr><tr><td><code>nonce</code></td><td>Random number generated of this transaction to verify that specific values are not reused</td><td>As <code>nonce</code> in the request body</td></tr><tr><td><code>payload_hash</code></td><td>Encoded payload hash</td><td>Used to generate the <code>stark_signature</code> in the request body by using the Stark (L2) signer to sign the <code>payload_hash</code>.</td></tr><tr><td><code>signable_message</code></td><td>Message to sign with L1 wallet to verity withdrawal request</td><td>Used to generate the <code>x-imx-eth-signature</code> header by using the Ethereum (L1) signer to sign the <code>signable_message</code></td></tr><tr><td><code>stark_key</code></td><td>Public stark key of the withdrawing user</td><td>As <code>stark_key</code> in the request body</td></tr><tr><td><code>vault_id</code></td><td>The ID of the vault the asset belong to</td><td>As <code>vault_id</code> in the request body</td></tr></tbody></table>

**2. Generate signers**[**​**](https://docs.x.immutable.com/docs/x/how-to-enable-deposits-withdrawals#2-generate-signers-2)

Enabling users to withdraw assets requires a user's signature, so your application will need to create signers. See the guide on <mark style="color:blue;">how to generate signers</mark>.

**3. Create withdrawal**[**​**](https://docs.x.immutable.com/docs/x/how-to-enable-deposits-withdrawals#3-create-withdrawal)

💡ENDPOINT:

* <mark style="color:blue;">createWithdrawal</mark>

***Javascript example of withdrawing ETH from L2 to L1:***

```
import fetch from 'node-fetch';

// See previous step for how to generate signers
const ethSignature = ethSigner.sign(signable_message);
const starkSignature = starkSigner.sign(payload_hash);

const withdrawalBody = {
  amount: 'string',
  asset_id: 'string',
  nonce: 'string',
  stark_key: 'string',
  stark_signature: starkSignature,
  vauld_id: 'string',
};

fetch('https://api.sandbox.x.XpansionChain.com/v1/withdrawals', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'x-imx-eth-address': '0x..', // Public Ethereum address of the withdrawing user
    'x-imx-eth-signature': ethSignature,
  },
  body: JSON.stringify(withdrawalBody),
})
  .then((response) => {
    console.log(response);
  })
  .catch((err) => {
    console.error(err);
  });
```

**4. Get the `assetType` value**[**​**](https://docs.x.immutable.com/docs/x/how-to-enable-deposits-withdrawals#4-get-the-assettype-value)

This value is required in the next step to complete the withdrawal.

```
import fetch from 'node-fetch';

const assetType = 'asset'; // "mintable-asset" if you are withdrawing an ERC721 token that was minted on L2 to L1 for the first time

const encodeAssetBody = {
  token: {
    data: {
      blueprint: 'string',
      id: 'string',
      token_address: 'string',
      token_id: 'string',
    },
    type: 'ETH', // Or "ERC20" or "ERC721"
  },
};

fetch(`https://api.sandbox.x.XpansionChain.com/v1/encode/${assetType}`, {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'x-imx-eth-address': '0x..', // Public Ethereum address of the withdrawing user
    'x-imx-eth-signature': ethSignature,
  },
  body: JSON.stringify(encodeAssetBody),
})
  .then((response) => {
    console.log(response);

    // Example response
    // {
    //     "asset_id": "string",
    //     "asset_type": "string"
    // }
  })
  .catch((err) => {
    console.error(err);
  });
```

**5. Call contract to complete withdrawal**[**​**](https://docs.x.immutable.com/docs/x/how-to-enable-deposits-withdrawals#5-call-contract-to-complete-withdrawal)

```
import { Contracts, Config } from '@imtbl/core-sdk';

const config = Config.SANDBOX;

// Get instance of core contract
const contract = Contracts.Core.connect(
  config.ethConfiguration.coreContractAddress,
  ethSigner
);

// Populate and send transaction
const populatedTransaction = await contract.populateTransaction.withdraw(
  starkPublicKey, // Use `stark_key` obtained in previous step
  assetType // Use the `asset_type` value returned in the response object in step 4
);

const transactionResponse = await ethSigner.sendTransaction(
  populatedTransaction
);
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://xpansionchain-1.gitbook.io/xpansionchain/guides/basic-guides/asset-deposits-and-withdrawals.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
