# Aleph Zero Signer integration

### Intro

In this tutorial, we create a simple web app integrated with the Aleph Zero Signer. This app will:

* import and display accounts from the Signer;
* sign a simple transfer transaction using one of those accounts.

### Requirements

* [Aleph Zero Signer](https://alephzero.org/signer)
  * Install on [Google Chrome, Brave, MS Edge, and Opera](https://chrome.google.com/webstore/detail/aleph-zero-signer/opbinaebpmphpefcimknblieddamhmol)
  * [Install on Firefox](https://addons.mozilla.org/en-US/firefox/addon/aleph-zero-signer/)
* `node` 14.18+ or 16+ (required to use `vite` with `react`: your dependencies may vary if you choose to use a different framework).

### Create project

We're using [`vite`](https://vitejs.dev/) to set up the React project.&#x20;

Run:

```bash
npm create vite@latest signer-integration -- --template react-ts
```

You will then be able to start the dev server like this:

```bash
cd signer-integration
npm install
npm run dev
```

### Install dependency

Aleph Zero Signer exposes the polkadot.{js} dapp extension library API. You can check out their docs [here](https://polkadot.js.org/docs/extension/).

```bash
npm install @polkadot/extension-dapp
```

### Check if Signer is injected

First, let's make sure Signer was successfully injected into our website.

If Signer (or any other extension supporting this API) is available, it is added to the `window.injectedWeb3` object.

You can test that by running this example:

```bash
npm run dev
```

and, using your browser's developer console, inspect the `window.injectedWeb3` object to see if Signer is registered.

<figure><img src="https://1927958252-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FjxGnEsASyxizmuYQHzry%2Fuploads%2F0coBK7iKVZPqXlspaQYS%2Fimage.png?alt=media&#x26;token=617bd8a4-cf28-4344-ab56-666b7eb8662e" alt=""><figcaption><p>Firefox developer console screenshot</p></figcaption></figure>

{% hint style="warning" %}
Common pitfalls/troubleshooting

* Signer extension wasn't successfully installed;
* Signer is disabled;
* Make sure your site is served from localhost, 127.0.0.1, or over https\:// - Signer isn't injected on other sites served over http\://.
  {% endhint %}

### Connect to Signer

Now, we will enable injected extensions as the API can handle more than one extension at a time–in our case, it's just the Signer.&#x20;

We will be using `web3Enable` - a util function from `@polkadot/extension-dapp`. It enables the connection and returns a list of all injected extensions.

We're going to call this method in the `onClick` handler of the 'Connect account' button:

```jsx
import { web3Enable } from "@polkadot/extension-dapp";

type InjectedExtension = Awaited<ReturnType<typeof web3Enable>>[number];

const [extensions, setExtensions] = useState<InjectedExtension[]>([]);

const loadAccountsFromExtensions = async () => {
  // extension-dapp API: connect to extensions; returns list of injected extensions
  const injectedExtensions = await web3Enable(APP_NAME);

  setExtensions(injectedExtensions);
};

<button onClick={loadAccountsFromExtensions}>
  Connect to extensions
</button>
```

`APP_NAME` is a string - the name of the app that is trying to connect. This is how your app is going to be represented inside the Signer.

{% hint style="info" %}
You have to call `web3Enable` before any other utility functions.
{% endhint %}

Now, after clicking the button and going through the `Your privacy is protected` screen, you should see one of these pop-ups:

<div align="center"><figure><img src="https://1927958252-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FjxGnEsASyxizmuYQHzry%2Fuploads%2FZW8zONeq3xAK9KDTlR5e%2Fno-accounts.png?alt=media&#x26;token=a30bdbff-4c55-4731-895d-1d791ad5a789" alt=""><figcaption><p>No accounts screen</p></figcaption></figure> <figure><img src="https://1927958252-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FjxGnEsASyxizmuYQHzry%2Fuploads%2FdSFDFgnQDUneRHKWsbiz%2Fconnect-app-screen.png?alt=media&#x26;token=3261beee-9e79-4664-9583-6b33cf108292" alt=""><figcaption><p>Connect app screen with one account</p></figcaption></figure></div>

Add an account to Signer if you haven't already, and make sure you select the checkbox next to it when connecting. Connecting an account means it will be available on a website–we'll be able to get the account information and initiate signing transactions.

You can change connected accounts by going to: `settings (top left corner) > Trusted apps > <Your app>`

### Loading accounts

Now we can use `web3Accounts` helper function to get all the accounts provided by the Signer:

```jsx
import { web3Accounts } from "@polkadot/extension-dapp";

type InjectedAccountWithMeta = Awaited<ReturnType<typeof web3Accounts>>[number];

const [accounts, setAccounts] = useState<InjectedAccountWithMeta[]>([]);

// extension-dapp API: get accounts from extensions filtered by name
const accounts = await web3Accounts(
  { extensions: ["aleph-zero-signer"] }
);

setAccounts(accounts);

<article>
  <h2>Signer accounts</h2>
  <ul>
    {accounts.map(({ address, meta: { name } }) => (
      <li key={address}>
        <strong>{name || "<unknown>"}</strong> {address}
      </li>
    ))}
  </ul>
</article>
```

Above, we're filtering to get only the accounts from the Signer, but you might choose to include all accounts.

### Transaction: prepare accounts

Since, in this example, we will make transactions on the Aleph Zero Testnet, we will need two accounts and some funds (TZERO). Create a second account in the Signer. Accounts have associated networks, and we want both accounts to have the Aleph Zero Testnet selected. You can either select it in the account creator or change it later in the settings.

We should be able to filter the accounts over the selected network. To that end, `web3Accounts` has a `genesisHash` parameter available, and for the Aleph Zero Testnet, we want:

```js
// extension-dapp API: get accounts from extensions filtered by name and chain
const accounts = await web3Accounts({
  extensions: ["aleph-zero-signer"],
  genesisHash:
    "0x05d5279c52c484cc80396535a316add7d47b1c5b9e0398dd1f584149341460c5",
});
```

#### Getting the funds

With the accounts ready, we need to set them up with some TZERO (the Aleph Zero Testnet currency). To do so, copy the first account address and paste it into the address field in the Testnet [Faucet](https://faucet.test.azero.dev/). You'll need to solve a captcha, and the system will transfer some TZERO to your account. You can check your accounts' balances e.g. in <https://test.azero.dev/#/accounts> (which, incidentally, is also an example of a Signer integration).

### Transaction: set up the API

To create a transaction, we will be using the `@polkadot/api` library - [docs](https://polkadot.js.org/docs/api/).

```bash
npm install @polkadot/api
```

We'll need to set it up and initialize it using the Aleph Zero Testnet websocket:

```js
import { ApiPromise, WsProvider } from "@polkadot/api";

const ALEPH_ZERO_TESTNET_WS_PROVIDER = new WsProvider(
  "wss://ws.test.azero.dev"
);

const API_PROMISE = ApiPromise.create({
  provider: ALEPH_ZERO_TESTNET_WS_PROVIDER,
});

const [api, setApi] = useState<ApiPromise>();

useEffect(() => {
  API_PROMISE.then(setApi);
}, []);
```

### Transaction: sign a transaction

Next, we are going to sign a simple transfer transaction. For the sake of simplicity, we are going to transfer `50 TZERO` from the first account to the second one.

Note that we're using the big number implementation from `@polkadot/util` to make sure we don't exceed JavaScript's safe integer range.

```bash
npm install @polkadot/util
```

The balance on–chain is kept in pico (1e-12) TZERO, so we need to adjust the transferred value. Instead of hard-coding the units here, we can get this information from the `api`.

```jsx
import { web3FromAddress } from "@polkadot/extension-dapp";
import { BN } from "@polkadot/util";

const makeTransfer = async () => {
  const [first, second] = accounts;

  // extension-dapp API: get address's injector
  const firstAddressInjector = await web3FromAddress(first.address);

  const transferAmount = new BN(50);
  const unitAdjustment = new BN(10).pow(new BN(api.registry.chainDecimals[0]));
  const finalAmount = transferAmount.mul(unitAdjustment);

  await api.tx.balances
    .transferAllowDeath(second.address, finalAmount)
    .signAndSend(first.address, { signer: firstAddressInjector.signer });
};

<button onClick={makeTransfer}>Make transfer</button>;
```

After clicking the button, you should see the Signer pop-up:

<figure><img src="https://1927958252-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FjxGnEsASyxizmuYQHzry%2Fuploads%2Fgn71H7MP9gX9uUgNW9Pi%2Ftransfer-authorization.png?alt=media&#x26;token=11543d09-9bad-4f9a-87e3-f23115bea8d1" alt=""><figcaption><p>Transaction authorization screen</p></figcaption></figure>

Lastly, you can confirm and check your accounts' balances in <https://test.azero.dev/#/accounts>.

{% hint style="info" %}
Just because the transaction Promise doesn't throw an exception, it doesn't mean it succeeded - see <https://polkadot.js.org/docs/api/cookbook/tx/#how-do-i-get-the-decoded-enum-for-an-extrinsicfailed-event>.
{% endhint %}

### Closing remarks

We hope you've enjoyed this tutorial, and now you know how to smoothly integrate your app with the Signer.\
\
For other tutorials, head over to [alephzero.org/developers](https://alephzero.org/developers)\
\
If you need any other help, make sure to join our [Discord](https://discord.gg/alephzero)!

### Signer icons

Feel free to use those icons when integrating Signer with your app:

<div><figure><img src="https://1927958252-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FjxGnEsASyxizmuYQHzry%2Fuploads%2FHHPMJTWvAFAuEtQRMRiV%2FA0%20Signer_icon_16.png?alt=media&#x26;token=6219e465-8024-4e81-b821-4ac2bb885e94" alt=""><figcaption></figcaption></figure> <figure><img src="https://1927958252-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FjxGnEsASyxizmuYQHzry%2Fuploads%2FduwmHjYkN0imZljJKpMg%2FA0%20Signer_icon_20.png?alt=media&#x26;token=5f89ec53-beca-4d31-97f1-c770fe31089f" alt=""><figcaption></figcaption></figure> <figure><img src="https://1927958252-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FjxGnEsASyxizmuYQHzry%2Fuploads%2FAAnAmRkVyS7nLa5UA3Lu%2FA0%20Signer_icon_32.png?alt=media&#x26;token=c56d863f-c7c1-4aa8-978f-0af432d4eeb9" alt=""><figcaption></figcaption></figure> <figure><img src="https://1927958252-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FjxGnEsASyxizmuYQHzry%2Fuploads%2FjywNXE3bb4nvdOTTp3DC%2FA0%20Signer_icon_48.png?alt=media&#x26;token=c7a78e8c-64f2-414a-a4f5-3cb3c4c302fc" alt=""><figcaption></figcaption></figure> <figure><img src="https://1927958252-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FjxGnEsASyxizmuYQHzry%2Fuploads%2F2aJyZJkCqlUjljt8hf2u%2FA0%20Signer_icon_64.png?alt=media&#x26;token=6ca2c1bb-9b60-466b-b92d-44572587ccbf" alt=""><figcaption></figcaption></figure> <figure><img src="https://1927958252-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FjxGnEsASyxizmuYQHzry%2Fuploads%2FcdXJisSNRhTdJV2dzaqV%2FA0%20Signer_icon_128.png?alt=media&#x26;token=96bd9bb2-b4ee-423f-8da6-cdd12d2040dd" alt=""><figcaption></figcaption></figure></div>


---

# 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://docs.alephzero.org/aleph-zero/build/aleph-zero-signer-integration.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.
