# Introduction

Getting started with Blocto and Blocto SDK

Blocto is built with two goals in mind:

1. **Make it simple for average users to use dApps**
2. **Make it simple for developers to build good dApps**

For these goals we have built:

1. [Blocto app](broken://pages/-MFKhMIOycoIaVk-pfYY) to reduce entry barrier and improve dApp experience
2. [Blocto SDK](/blocto-sdk/overview) to help developers build awesome dApps with minimal effort

![](/files/OdSwMcaFfRLkluh7bUk8)

<figure><img src="/files/SadV7LFtiFChmI0BQMGF" alt=""><figcaption></figcaption></figure>

#### Account Abstraction

Blocto wallets are built with chain-agnostic account abstraction. On chains with native account abstraction, such as [Flow](https://flow.com/), Blocto utilizes the native account system to provide account abstraction functionalities; This gives Blocto wallets a lot of advantages over regular private-key wallets.

{% hint style="warning" %}
Blocto is under heavy development. New features come every week. [Subscribe to our mailing list](https://blocto.typeform.com/to/nJTnwcjv) so you don't miss out on our news.
{% endhint %}


# Blocto Environment

Blocto is a AA wallet and uses email as login. There are two environments in Blocto: *prod* and *dev* which is corresponding to different blockchain networks. The same environment means the same account system.

<table><thead><tr><th>Chain \ Environment</th><th>prod</th><th>dev</th><th data-hidden>prod</th></tr></thead><tbody><tr><td>Flow</td><td>Mainnet</td><td>Testnet</td><td></td></tr></tbody></table>

### JavaScript SDK

Blocto JavaScript SDK uses different environments according to different blockchain networks. The key properties are as below:

* Flow: `challenge.handshake` from config

### Android App

*prod*: [Google Play](https://play.google.com/store/apps/details?id=com.portto.blocto)

### iOS App

*prod*: [App Store](https://apps.apple.com/tw/app/blocto/id1481181682)


# Give Feedback

Let us know if you have found bugs or you would like to request for features.

Blocto is built for developers to optimize their dApp experience and maximize growth. We value your inputs a lot!

For **bug reports** and **feature requests**, please go to our Canny page at <https://blocto.canny.io/>


# Overview

Use Blocto SDK in your dApp to provide excellent user experience

### Blocto SDK

> The best blockchain experience is that user doesn't even realize it's a blockchain experience.

Blocto team has an OCD for user experience.

Although we have built Blocto app that provides top-tier user experience among wallet apps and browser extensions, it's still not the ideal experience we want to create: **It still requires a download process**.

That's why we're building Blocto SDK so dApp developers can embed the wallet service tightly into their dApps and improve user experience, especially for those who are not crypto-fluent.

<figure><img src="/files/oTSRmuRIV7yzq31OAJzq" alt=""><figcaption><p>Integrate Blocto wallet service tightly with your dApp</p></figcaption></figure>

### Advantages

#### Compared to stand-alone wallets

1. **No downloads needed**\
   Users stay in your dApp the entire time. They never have to download additional apps or browser extensions for your dApp to work.
2. **Seamless on boarding**\
   User don't have to go through the painful wallet creation process, where they get intimidated by new ideas like seed phrases, private keys, addresses, ... etc. They can learn later, as they accumulate more assets in their wallets. ([See how our mixed custodial model works](/technical-documents/key-management))

#### Compared to other wallet SDKs

1. **Freemium model made possible**\
   You can pay transaction fees for your users to provide a freemium experience. They don't have to buy crypto to pay for fees before they try out your dApp. ([See how meta-transaction works](broken://pages/-MFJNFNEGjoC0EYqJNJ7#meta-transaction))
2. **Integrated payment**\
   Get paid easily with our payment APIs. Users can pay easily with credit cards or other crypto currencies like Bitcoin, Ethereum, Tron, USDT, ... etc.
3. **Connected to Blocto App**\
   Once you've integrated with Blocto SDK, your users can manage their assets easily and securely through Blocto App. Your dApp can tap into the vast blockchain ecosystem instantly.
4. **Supports multiple blockchains**\
   Blocto SDK supports Flow. Blocto also helps users convert their assets across different chains.


# JavaScript SDK

Blocto JavaScript SDK is open source and available at [GitHub](https://github.com/blocto/blocto-sdk).


# Flow

Using Blocto SDK in Flow dApps

![](/files/-MFJptS9I9Du2jx3VpQW)

### Flow

[Flow](https://onflow.org), built by [Dapper Labs](https://www.dapperlabs.com/), is a decentralized platform built to support the next generation of games, apps, and the digital assets that power them.

Flow has a few unique designs that make it particularly suitable for consumer facing dApps, such as an account system with built-in multi-sig mechanism, built-in fee subsidization and resource-oriented smart contract language [Cadence](https://docs.onflow.org/docs/getting-started-1). It also provides much better scalability than Ethereum, which is necessary for mass market adoption.

### Flow JavaScript SDK

Flow ships with a bundle JavaScript libraries including [Flow SDK](https://github.com/onflow/flow-js-sdk/tree/master/packages/sdk) and [Flow Client Library (FCL)](https://github.com/onflow/flow-js-sdk/tree/master/packages/fcl). With these libraries, web-based dApps can interact with Flow blockchain easily. If you're familiar with dApp development on Ethereum, they're basically the web3.js for Flow.

Flow Client Library, or FCL, defines how web-based dApps can interact with wallet providers like Blocto SDK. In the following sections, we will show you how to use Blocto wallet service in your Flow dApp.


# Tutorial

Run a simple dApp that uses Blocto wallet service

## Hello World

Let's build a simple project that sends a simple transaction on Flow testnet with Blocto FCL wallet.

{% hint style="warning" %}
You need to have [Node.js](https://nodejs.org/zh-tw/download/package-manager/) and [yarn](https://classic.yarnpkg.com/en/docs/install/) installed for the rest of the tutorial.
{% endhint %}

### Step 1 - Create app and setup dependencies

```bash
$ npx create-react-app hello-world
```

In the `hello-world` folder you've just created, install dependencies necessary for this project.

<pre><code>$ yarn add @blocto/fcl@^1.4.0
<strong>$ yarn add styled-components
</strong></code></pre>

{% hint style="danger" %}
FCL is under heavy developments and the versions are not always backward compatible. We recommend that you use `@blocto/fcl@^1.4.0` for now.
{% endhint %}

You can start the app and see it running on `http://localhost:3000`

```bash
$ yarn start
```

### Step 2 - Read from Flow

1. Create `src/GetLatestBlock.js`
2. Add the component to `src/App.js`
3. Add config for FCL in `src/index.js` so FCL knows which access node to read data from

{% tabs %}
{% tab title="src/GetLatestBlock.js" %}

```jsx
import React, {useState} from "react"
import * as fcl from "@blocto/fcl"
import styled from 'styled-components'

const Card = styled.div`
  margin: 10px 5px;
  padding: 10px;
  border: 1px solid #c0c0c0;
  border-radius: 5px;
`

const Code = styled.pre`
  background: #f0f0f0;
  border-radius: 5px;
  max-height: 150px;
  overflow-y: auto;
  padding: 5px;
`

const GetLatestBlock = () => {
  const [data, setData] = useState(null)

  const runGetLatestBlock = async (event) => {
    event.preventDefault()

    const response = await fcl.send([
      fcl.getBlock(true)
    ])
    
    setData(await fcl.decode(response))
  }

  return (
    <Card>
      <button onClick={runGetLatestBlock}>
        Get Latest Block
      </button>
      
      {data && <Code>{JSON.stringify(data, null, 2)}</Code>}
    </Card>
  )
}

export default GetLatestBlock
```

{% endtab %}

{% tab title="src/App.js" %}

```jsx
import React from 'react';
import styled from 'styled-components'

import GetLatestBlock from './GetLatestBlock'

const Wrapper = styled.div`
  font-size: 13px;
  font-family: Arial, Helvetica, sans-serif;
`;

function App() {
  return (
    <Wrapper>
      <GetLatestBlock />
    </Wrapper>
  );
}

export default App
```

{% endtab %}

{% tab title="src/index.js" %}

```jsx
import React from 'react'
import ReactDOM from 'react-dom'
import * as fcl from "@blocto/fcl"
import './index.css'
import App from './App'
import * as serviceWorker from './serviceWorker'

fcl.config({
  "accessNode.api": "https://rest-testnet.onflow.org" // connect to Flow testnet
});

ReactDOM.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>,
  document.getElementById('root')
)

// If you want your app to work offline and load faster, you can change
// unregister() to register() below. Note this comes with some pitfalls.
// Learn more about service workers: https://bit.ly/CRA-PWA
serviceWorker.unregister()
```

{% endtab %}
{% endtabs %}

When user clicks the button, `runGetLatestBlock` sends a request to get information for the latest block on Flow and display the result in `<Code>` block.

### Step 3 - Connect to Blocto wallet

Now, let's add login functionality to your dApp.

1. Create `src/Authenticate.js`
2. Add the component to `src/App.js`
3. Add config for FCL in `src/index.js` so FCL knows which wallet to use

{% tabs %}
{% tab title="src/Authenticate.js" %}

```jsx
import React, {useState, useEffect} from "react"
import styled from "styled-components"
import * as fcl from "@blocto/fcl"

const Card = styled.div`
  margin: 10px 5px;
  padding: 10px;
  border: 1px solid #c0c0c0;
  border-radius: 5px;
`

const SignInOutButton = ({ user: { loggedIn } }) => {
  const signInOrOut = async (event) => {
    event.preventDefault()

    if (loggedIn) {
      fcl.unauthenticate()
    } else {
      fcl.authenticate()
    }
  }

  return (
    <button onClick={signInOrOut}>
      {loggedIn ? 'Sign Out' : 'Sign In/Up'}
    </button>
  )
}

const CurrentUser = () => {
  const [user, setUser] = useState({})

  useEffect(() =>
    fcl
      .currentUser()
      .subscribe(user => setUser({...user}))
  , [])

  return (
    <Card>
      <SignInOutButton user={user} />
    </Card>
  )
}

export default CurrentUser
```

{% endtab %}

{% tab title="src/App.js" %}

```jsx
import React from 'react';
import styled from 'styled-components'

import GetLatestBlock from './GetLatestBlock'
import Authenticate from './Authenticate'

const Wrapper = styled.div`
  font-size: 13px;
  font-family: Arial, Helvetica, sans-serif;
`;

function App() {
  return (
    <Wrapper>
      <GetLatestBlock />
      <Authenticate />
    </Wrapper>
  );
}

export default App;
```

{% endtab %}

{% tab title="src/index.js" %}

```jsx
import React from 'react'
import ReactDOM from 'react-dom'
import * as fcl from "@blocto/fcl"
import './index.css'
import App from './App'
import * as serviceWorker from './serviceWorker'

fcl.config({
  "accessNode.api": "https://rest-testnet.onflow.org", // connect to Flow testnet
  "discovery.wallet": `https://wallet-v2-dev.blocto.app/${YOUR_DAPP_ID}/flow/authn` // use Blocto testnet wallet
});

ReactDOM.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>,
  document.getElementById('root')
)

// If you want your app to work offline and load faster, you can change
// unregister() to register() below. Note this comes with some pitfalls.
// Learn more about service workers: https://bit.ly/CRA-PWA
serviceWorker.unregister()
```

{% endtab %}
{% endtabs %}

When user clicks the login button, FCL calls out to Blocto wallet and the user can either register a new Blocto account or login to their existing Blocto accounts. Once the login process completes and user chooses to use the Blocto account on the dApp, the dApp gets the connected account information and show it in `<UserProfile>`.

### Step 4 - Send a simple transaction

Finally, we can use the connected Blocto Flow account to send a transaction.

1. Create `src/SendTransaction.js`
2. Add the component to `src/App.js`

{% tabs %}
{% tab title="src/SendTransaction.js" %}

```jsx
import React, {useState} from "react"
import * as fcl from "@blocto/fcl"
import styled from 'styled-components'

const Card = styled.div`
  margin: 10px 5px;
  padding: 10px;
  border: 1px solid #c0c0c0;
  border-radius: 5px;
`

const Header = styled.div`
  font-size: 16px;
  font-weight: 600;
  margin-bottom: 5px;
`

const Code = styled.pre`
  background: #f0f0f0;
  border-radius: 5px;
  max-height: 300px;
  overflow-y: auto;
  padding: 5px;
`

const simpleTransaction = `\
transaction {
  execute {
    log("Hello World!!")
  }
}
`

const SendTransaction = () => {
  const [status, setStatus] = useState("Not started")
  const [transaction, setTransaction] = useState(null)

  const sendTransaction = async (event) => {
    event.preventDefault()
    
    setStatus("Resolving...")

    const blockResponse = await fcl.send([
      fcl.getLatestBlock(),
    ])

    const block = await fcl.decode(blockResponse)
    
    try {
      const tx = await fcl.send([
        fcl.transaction(simpleTransaction),
        fcl.proposer(fcl.currentUser().authorization),
        fcl.payer(fcl.currentUser().authorization),
        fcl.ref(block.id),
        fcl.limit(100)
      ])

      const { transactionId } = tx

      setStatus(`Transaction (${transactionId}) sent, waiting for confirmation`)

      const unsub = fcl
        .tx(transactionId)
        .subscribe(transaction => {
          setTransaction(transaction)

          if (fcl.tx.isSealed(transaction)) {
            setStatus(`Transaction (${transactionId}) is Sealed`)
            unsub()
          }
        })
    } catch (error) {
      console.error(error)
      setStatus("Transaction failed")
    }
  }

  return (
    <Card>
      <Header>send transaction</Header>

      <Code>{simpleTransaction}</Code>

      <button onClick={sendTransaction}>
        Send
      </button>

      <Code>Status: {status}</Code>

      {transaction && <Code>{JSON.stringify(transaction, null, 2)}</Code>}
    </Card>
  )
}

export default SendTransaction
```

{% endtab %}

{% tab title="src/App.js" %}

```jsx
import React from 'react';
import styled from 'styled-components'

import GetLatestBlock from './GetLatestBlock'
import Authenticate from './Authenticate'
import SendTransaction from './SendTransaction'

const Wrapper = styled.div`
  font-size: 13px;
  font-family: Arial, Helvetica, sans-serif;
`;

function App() {
  return (
    <Wrapper>
      <GetLatestBlock />
      <Authenticate />
      <SendTransaction />
    </Wrapper>
  );
}

export default App;
```

{% endtab %}
{% endtabs %}

When user clicks the `send` button, FCL summons Blocto wallet and prompts user to either approve the transaction or reject it. If user approves of the transaction, Blocto wallet signs the message with the key in custodial and pass the signature back to FCL, where the transaction and the signature is sent to Flow network.

{% hint style="info" %}
Awesome! You have sent a transaction to Flow testnet with Blocto wallet!
{% endhint %}

{% embed url="<https://codesandbox.io/s/flow-tutorial-918v90>" %}

## Other Resources

* **Flow App Quickstart**: <https://docs.onflow.org/fcl/tutorials/flow-app-quickstart/>
* **Other frameworks (community built)**
  * [Angular](https://github.com/ic3guy/FlowAngularExample)
  * [Svelte](https://github.com/amitkothari/crypto-candy)


# Configure FCL

Configure Blocto wallet to your Flow dApp

### Installation

{% hint style="info" %}
FCL is under heavy developments and the versions are not always backward compatible. We recommend that you use `@`blocto`/fcl@^1.4.0` for now.
{% endhint %}

{% hint style="info" %}
For why to use `@blocto/fcl` instead of `@onflow/fcl`, check out this [Github PR](https://github.com/onflow/fcl-js/pull/1679) for further information.
{% endhint %}

{% tabs %}
{% tab title="npm" %}

```bash
npm install @blocto/fcl@^1.4.0
```

{% endtab %}

{% tab title="yarn" %}

```bash
yarn add @blocto/fcl@^1.4.0
```

{% endtab %}

{% tab title="pnpm" %}

```bash
pnpm install @blocto/fcl@^1.4.0
```

{% endtab %}
{% endtabs %}

### **Configure Flow Networks & Blocto wallet URL**

Blocto wallet provides two ways to communicate with FCL, according to your needs, choose one of them to configure your dApp. Visit [How to Configure FCL](https://developers.flow.com/tooling/fcl-js/configure-fcl) to get further configuration settings.

#### Using front channel

{% tabs %}
{% tab title="Mainnet" %}

```javascript
import * as fcl from "@blocto/fcl";
  
fcl.config({
  "accessNode.api": "https://rest-mainnet.onflow.org", // connect to Flow mainnet
  "discovery.wallet": `https://wallet-v2.blocto.app/-/flow/authn` // use Blocto mainnet wallet
});
```

{% endtab %}

{% tab title="Testnet" %}
{% code fullWidth="false" %}

```javascript
import * as fcl from "@blocto/fcl";

fcl.config({
  "accessNode.api": "https://rest-testnet.onflow.org", // connect to Flow testnet
  "discovery.wallet": `https://wallet-v2-dev.blocto.app/-/flow/authn` // use Blocto testnet wallet
});
```

{% endcode %}
{% endtab %}
{% endtabs %}

#### Using back channel

{% tabs %}
{% tab title="Mainnet" %}

```javascript
import * as fcl from "@blocto/fcl";

fcl.config({
  "accessNode.api": "https://rest-mainnet.onflow.org", // connect to Flow mainnet
  "discovery.wallet": "https://wallet-v2.blocto.app/api/flow/authn", // use Blocto mainnet wallet
  "discovery.wallet.method": "HTTP/POST",
});
```

{% endtab %}

{% tab title="Testnet" %}
{% code fullWidth="false" %}

```javascript
import * as fcl from "@blocto/fcl";
  
fcl.config({
  "accessNode.api": "https://rest-testnet.onflow.org", // connect to Flow testnet
  "discovery.wallet": "https://wallet-v2-dev.blocto.app/api/flow/authn", // use Blocto testnet wallet
  "discovery.wallet.method": "HTTP/POST",
});
```

{% endcode %}
{% endtab %}
{% endtabs %}


# Authenticate / Unauthenticate

Connect to Blocto wallet through Flow Client Library (FCL)

### Step 1 - Configure FCL

```javascript
import * as fcl from "@blocto/fcl";

fcl.config({
  "accessNode.api": "https://rest-testnet.onflow.org", // connect to Flow testnet
  "discovery.wallet": `https://wallet-v2-dev.blocto.app/-/flow/authn` // use Blocto testnet wallet
});
```

Alternatively, if you already have user's email and would like to pre-fill it for user's Blocto account, you can use the custom `discovery.wallet` URL instead:

```javascript
import * as fcl from "@blocto/fcl";

const USER_EMAIL = "client@email.com";

fcl.config({
  "accessNode.api": "https://rest-testnet.onflow.org", // connect to Flow testnet
  "discovery.wallet": `https://wallet-v2-dev.blocto.app/-/flow/authn/${USER_EMAIL}` // use Blocto testnet wallet
});
```

### Step 2 - Authenticate

```javascript
import * as fcl from "@blocto/fcl";

// fires everytime account connection status updates
fcl.currentUser().subscribe(console.log);

// authenticate
fcl.authenticate();
```

### Step 3 - Unauthenticate

```javascript
import * as fcl from "@blocto/fcl";

// fires everytime account connection status updates
fcl.currentUser().subscribe(console.log);

// unauthenticate and clear account info in FCL
fcl.unauthenticate();
```

{% embed url="<https://codesandbox.io/s/flow-autenticate-unauthenticate-v2-hfq56w>" %}


# Send Transaction

Send Transaction with Blocto wallet through Flow Client Library (FCL)

{% hint style="warning" %}
Before sending a transaction, user needs to connect to Blocto wallet first.
{% endhint %}

### Step 1 - Send transaction

```javascript
import * as fcl from "@blocto/fcl";

const SIMPLE_TRANSACTION = `\
transaction {
  execute {
    log("Hello World!!")
  }
}
`;


const transactionId = await fcl.mutate({
  cadence: SIMPLE_TRANSACTION,
  proposer: fcl.currentUser,
  payer: fcl.currentUser,
  limit: 50,
});

// The transactions status and events after being sealed
const transaction = await fcl.tx(transactionId).onceSealed();
```

### Step 2 - Authorizing a transaction

```javascript
import * as fcl from "@blocto/fcl";

const transactionId = await fcl.mutate({
  cadence: `
    transaction {
      prepare(acct: AuthAccount) {
        log("Hello from prepare")
      }
      execute {
        log("Hello from execute")
      }
    }
  `,
  proposer: fcl.currentUser,
  payer: fcl.currentUser,
  authorizations: [fcl.currentUser],
  limit: 50,
});

const transaction = await fcl.tx(transactionId).onceSealed();
console.log(transaction); // The transactions status and events after being sealed
```

{% embed url="<https://codesandbox.io/s/flow-sign-transaction-v2-lxgc0g>" %}


# Account Proof

Prove account ownership of a Flow account

Flow provides a way for dApps to ask for users' signatures when they connect a wallet and verify account ownership. For more information, refer to [Account Proof on Flow](https://docs.onflow.org/fcl/reference/proving-authentication/).

Currently Blocto self-custody accounts generate this signature slightly differently and needs an alternative way to verify ownership.

```javascript
import { AppUtils } from '@blocto/fcl'

const isSignatureValid = await AppUtils.verifyAccountProof(
  appIdentifier,
  {
    address,
    nonce,
    signatures,
  },
  {
    fclCryptoContract: BLOCTO_FCLCRYPTO_CONTRACT_ADDRESS
  }
)
```

The addresses of the Blocto FCLCrypto contract `BLOCTO_FCLCRYPTO_CONTRACT_ADDRESS` can be found here:

| Network | Blocto FCLCrypto Address |
| ------- | ------------------------ |
| Mainnet | 0xdb6b70764af4ff68       |
| Testnet | 0x5b250a8a85b44a67       |

[More about verifyAccountProof api](https://github.com/onflow/fcl-js/blob/master/docs/reference/proving-authentication.mdx)

{% embed url="<https://codesandbox.io/s/flow-account-proof-v2-u3twk1>" %}


# Flow Networks

Flow networks that Blocto supports

### Mainnet

* Access Node `https://rest-mainnet.onflow.org`
* Blocto Wallet
  * front channel `https://wallet-v2.blocto.app/-/flow/authn`
  * back channel `https://wallet-v2.blocto.app/api/flow/authn`

#### Front Channel

```javascript
import * as fcl from "@blocto/fcl"

fcl.config({
  "accessNode.api": "https://rest-mainnet.onflow.org", // connect to Flow mainnet
  "discovery.wallet": `https://wallet-v2.blocto.app/-/flow/authn` // use Blocto mainnet wallet
});
```

#### Back Channel

```javascript
import * as fcl from "@blocto/fcl";

fcl.config({
  "accessNode.api": "https://rest-mainnet.onflow.org", // connect to Flow mainnet
  "discovery.wallet": "https://wallet-v2.blocto.app/api/flow/authn", // use Blocto mainnet wallet
  "discovery.wallet.method": "HTTP/POST",
});
```

### Testnet

* Access Node `https://rest-testnet.onflow.org`
* Blocto Wallet
  * front channel `https://wallet-v2-dev.blocto.app/-/flow/authn`
  * back channel `https://wallet-v2-dev.blocto.app/api/flow/authn`

#### Front Channel

```javascript
import * as fcl from "@blocto/fcl"

fcl.config({
  "accessNode.api": "https://rest-testnet.onflow.org", // connect to Flow testnet
  "discovery.wallet": `https://wallet-v2-dev.blocto.app/-/flow/authn` // use Blocto testnet wallet
});
```

#### Back Channel

```javascript
import * as fcl from "@blocto/fcl";

fcl.config({
  "accessNode.api": "https://rest-testnet.onflow.org", // connect to Flow testnet
  "discovery.wallet": "https://wallet-v2-dev.blocto.app/api/flow/authn", // use Blocto testnet wallet
  "discovery.wallet.method": "HTTP/POST",
});
```


# Verified Transaction

If you would like to show the verified badge on Blocto wallet, please send the PR to <https://github.com/blocto/flow-transactions>.

#### UI Example

| Not Verified                     | Verified                         |
| -------------------------------- | -------------------------------- |
| ![](/files/NIz3yiTxlj8rdLUw8YxV) | ![](/files/N3BihQuMVRmrkHMy7FO5) |
| ![](/files/NSBIcxpasPPma2oi2FfG) | ![](/files/o3VAF9s896TdWVz8WS14) |


# Migration Guide

Migrating Blocto wallet from v1 to v2

This guide is primarily for early Flow developers adopting Blocto wallet who want to learn about our latest progress on Flow & Blocto. Read the following guide to enhance your experience with Blocto.

{% hint style="info" %}
For why to use `@blocto/fcl` instead of `@onflow/fcl`, check out this [Github PR](https://github.com/onflow/fcl-js/pull/1679) for further information.
{% endhint %}

### Changes

* Latest version of `@blocto/fcl@1.6.1` has been released
* New version of the blocto wallet interface and endpoints
* Update some deprecated methods or properties

### Upgrading Dependency

Upgrade the `@blocto/fcl` in the package.json to `^1.6.1`

{% tabs %}
{% tab title="yarn" %}

```bash
yarn upgrade @blocto/fcl@^1.6.1
```

{% endtab %}

{% tab title="npm" %}

```bash
npm install @blocto/fcl@^1.6.1
```

{% endtab %}

{% tab title="pnpm" %}

```bash
npm install @blocto/fcl@^1.6.1
```

{% endtab %}
{% endtabs %}

### Upgrading the FCL Configuration

Replace the value of `accessNode.api` and configuration keys:

{% tabs %}
{% tab title="Mainnet" %}

```
import * as fcl from "@blocto/fcl";

fcl
  .config({
    "accessNode.api": "https://rest-mainnet.onflow.org",
    "discovery.wallet": `https://wallet-v2.blocto.app/-/flow/authn`
  })
```

{% endtab %}

{% tab title="Testnet" %}

```
import * as fcl from "@blocto/fcl";

fcl
  .config({
    "accessNode.api": "https://rest-testnet.onflow.org",
    "discovery.wallet": `https://wallet-v2-dev.blocto.app/-/flow/authn`
  })
```

{% endtab %}
{% endtabs %}

If you have been using the back channel to communicate with FCL, follow the guide below:

{% tabs %}
{% tab title="Mainnet" %}

```
import * as fcl from "@blocto/fcl";

fcl
  .config({
    "accessNode.api": "https://rest-mainnet.onflow.org",
    "discovery.wallet": "https://wallet-v2.blocto.app/api/flow/authn",
    "discovery.wallet.method": "HTTP/POST"
  })
```

{% endtab %}

{% tab title="Testnet" %}

```
import * as fcl from "@blocto/fcl";

fcl
  .config({
    "accessNode.api": "https://rest-testnet.onflow.org",
    "discovery.wallet": "https://wallet-v2-dev.blocto.app/api/flow/authn",
    "discovery.wallet.method": "HTTP/POST"
  })
```

{% endtab %}
{% endtabs %}

### FCL Wallet Discovery

Good news for those who use [wallet discovery](https://github.com/onflow/fcl-discovery) to support multiple wallet on Flow, there is no action required from your side. You can keep the configuration as you did in FCL and Blocto wallet v2 will show up there automatically.


# Token Listing

List your tokens in Blocto app

You can submit application to list your fungible tokens, so users can manage these tokens natively inside Blocto app and trade them on BloctoSwap.

[Fungible Tokens (Flow FT)](https://forms.gle/K2Pd8Pf5X81MxjN97)


# Key Management

Blocto uses mixed-custodial model to provide both convenience and security

Blocto uses **mixed-custodial key management model** to provide both convenience and security, since both custodial and non-custodial models have their flaws:

## Non-Custodial

In non-custodial systems, user takes full responsibility in their key management. This is aligned with some of core-values of blockchain: decentralization and autonomy.

### Advantages

1. Doesn't have to trust any organizations.
2. Users have full control over their accounts.

### Disadvantages

1. Complex and intimidating, especially for beginners.
2. If user loses the key, nobody can help recover the account.
3. If the key gets leaked, someone else will have full control over the user's account.

## Custodial

In custodial systems, some 3rd party helps users manage their keys and provide an account/password or OAuth interface for managing the access.

### Advantages

1. Much simpler user experience. Similar to centralized systems.
2. If user forgets the password, there's always a way to recover user's access.
3. Custodial service operators usually have better security measures to manage the keys than non-tech-savvy users.

### Disadvantages

1. The custodial service operator can be malicious. They may steal users' assets.
2. The custodial service poses an appealing target for hackers. Any centralized system has the potential to be hacked.

## Mixed-Custodial

Blocto incorporates a mixed-custodial key management model to take the advantages from both sides:

1. **Custodial at first**\
   When users just signed up, the key is stored in Blocto's custodial service. This is for providing an easy onboarding experience to the users and avoid bombarding them with complexity. The keys stored in our services are managed by HSMs to provide superior security.
2. **Non-custodial later**\
   Users have the option to upgrade to non-custodial mode by generating a new key on their mobile device and replacing the ownership of the account. By then the keys stored in Blocto's custodial service will be voided and won’t be able to access the account anymore.

The idea is that when user just started, they don't care that much about security, since they don't have anything in their wallet yet. At this stage, **custodial model** is a better choice. As time goes by, user have accumulated more assets in their wallets and more knowledge about how blockchain works. This is the appropriate time for advanced users to switch to **non-custodial model** for more security.


# Web Wallet v1 Sunset Notice and Migration Guide

Please upgrade your Blocto SDK / FCL ASAP

2023/10/02 updated:

In order to bring the best user experience to our users, we have decided to postpone the due day of the sunset to November 6th. Please upgrade to wallet v2 as soon as possible in case there are some unexpected issues occurred.

{% hint style="info" %}
If you already used FCL wallet discovery to support multiple wallet, you can keep using the original discovery URL.
{% endhint %}

To enhance user experience and safety, we will sunset Blocto Web Wallet v1 on October 2nd, 2023. After this date, users will *no longer have access* to Blocto Wallet on dApps integrated with Web Wallet v1. To continue providing services with Blocto Wallet, dApps need to upgrade Blocto SDK to versions interacting with v2 services.

By migrating to v2, Blocto users will enjoy an enhanced and safer experience, including new features like social login. To continue using Blocto Wallet and benefit from these features, please upgrade your Blocto SDK and/or update the FCL configuration following the guide below. The upgrade process takes approximately 15 minutes.

### **fcl.js:**

Please upgrade fcl.js to `1.6.1` and update the configuration referring to the following migration guide: <https://docs.blocto.app/blocto-sdk/javascript-sdk/flow/migration-guide>


