# Welcome to Wander

A non-custodial Arweave and AO native wallet with extensive features.  Wander is available as a browser extension, mobile application, and embedded smart account.

<figure><img src="/files/OXLmZHENdxM4mlJJ5onW" alt="ArConnect cover image"><figcaption></figcaption></figure>

Wander is an Arweave and AO native wallet that provides non-custodial wallet and asset management. Wander allows wallet holders to interact with any Arweave or AO dApps without sharing the user needing to share private keys with the dApp.

{% hint style="info" %}
*Wander was formerly known as ArConnect*
{% endhint %}

<figure><img src="/files/jSzm57MEwXcgn6ts2LAT" alt="ArConnect user flow"><figcaption></figcaption></figure>

The isolated environment that Wander creates is not only a security improvement for users, but it also provides a more seamless login flow for applications. Developers no longer have to build sign in functionality, they can let Wander do the hard work for them.


# Wander Devtools

Custom devtools tab for easier Wander testing

<div data-full-width="false"><figure><img src="/files/76QpmSRUNkongcBjMHlA" alt=""><figcaption></figcaption></figure></div>

The Wander devtools allows you to easily connect your application to Wander and manage its settings.

## Connect

Upon startup, you'll be able to connect your app. You can select what permissions you want to allow the app to have. Once you selected the permissions you want, click *Force Connect*.

## Manage your app

The following settings are available at a glance for your app:

* Permissions\
  Manage permissions for your application quickly.
* Allowance\
  Manage spending allowance for your app
* Gateway\
  Select from suggested gateways or enter a custom one
* Bundler node\
  Set the bundler node your app uses when calling [`dispatch()`](/api/dispatch) .

  Turbo is the default bundler node


# ArLocal Devtools

Custom devtools tab for easier ArLocal testing and operations

<div data-full-width="false"><figure><img src="/files/S1tWm9QTwb1exQ3RYI6M" alt=""><figcaption></figcaption></figure></div>

The new [`ArLocal`](https://github.com/textury/arlocal) Devtools allow developers to easily interact with their local or public testnet without having to run scripts to perform certain actions. The tool can be accessed by opening the browser's devtools and clicking on the `ArLocal` tab.

## Setup

Upon startup, the tool will ask you to provide some information about the arlocal gateway you want to use. After setting the gateway URL, click the refresh button to load the action sheet.

<div data-full-width="false"><figure><img src="/files/rZGJ7RADWwMa1ssbUWDO" alt=""><figcaption></figcaption></figure></div>

## Mint testnet AR

You can mint testnet Arweave tokens that can be used like regular AR. Enter the desired amount in the input under the `Mint AR` title and click *Mint*. The tool will call the testnet to deposit AR into the currently active wallet in Wander and request the testnet to mine a block.

## Create testnet transaction

The ArLocal Devtools allow you to create new transactions with tags, a target and data. Simply set the desired fields under the `Create Transaction` title, enter your password and click *Send Transaction*. The tool will submit the transaction and request the testnet to mine a block.

## Manual block mining

You can manually request the testnet to mine a block by clicking the *Mine* button, under the *Send Transaction* button.


# Intro

Introducing the Wander Injected API

<div data-full-width="false"><figure><img src="/files/VKr61vpOt1qVgFcHVPHQ" alt=""><figcaption></figcaption></figure></div>

The Wander API is a JavaScript object, injected into each browser tab. To interact with it, you simply need to call one of the functions in the `window.arweaveWallet` object.

## Basic usage

To use Wander in your application, you don't need to integrate or learn how the Wander Injected API works. Using [`arweave-js`](https://npmjs.com/arweave), you can easily sign a transaction through Wander in the background:

```ts
// create Arweave transaction
const tx = await arweave.createTransaction({
  /* tx options */
});

// sign transaction
await arweave.transactions.sign(tx);

// TODO: handle signed transaction
```

When signing a transaction through [`arweave-js`](https://npmjs.com/arweave), you'll need to omit the second argument of the `sign()` function, or set it to `"use_wallet"`. This will let the package know to use the extension in the background to sign the transaction.

Once the transaction is signed, you can safely post it to the network.

## Advanced usage

The Wander Injected API provides extra functionalities in case you wish to utilize the user's wallet to its full extent securely. These features are not integrated in the `arweave-js` package, but can be useful to further customize your app. The above mentioned `window.arweaveWallet` object holds the api functions necessary for this.

Each function is described in detail in the following pages.

{% hint style="danger" %}
**Please remember:** to interact with the API, make sure that the `arweaveWalletLoaded` event has already been fired. Read more about that [here](/api/events#arweavewalletloaded-event).
{% endhint %}

## TypeScript types

To support Wander types for `window.arweaveWallet`, you can install the npm package `arconnect`, like this:

{% hint style="info" %}
*Wander was formerly know as ArConnect.  There are some API references that still use ArConnect*
{% endhint %}

```sh
npm i -D arconnect
```

or

```sh
yarn add -D arconnect
```

To add the types to your project, you should either include the package in your `tsconfig.json`, or add the following to your `env.d.ts` file:

```ts
/// <reference types="arconnect" />
```

## Additional Injected API fields

The Wander Injected API provides some additional information about the extension. You can retrieve the wallet version (`window.arweaveWallet.walletVersion`) and you can even verify that the currently used wallet API indeed belongs to Wander using the wallet name (`window.arweaveWallet.walletName`).

```ts
addEventListener("arweaveWalletLoaded", () => {
  console.log(`You are using the ${window.arweaveWallet.walletName} wallet.`);
  console.log(`Wallet version is ${window.arweaveWallet.walletVersion}`);
});
```


# Events

Wander DOM events

Wander provides useful custom events to track the state of the extension. These events implement the [`CustomEvent`](https://developer.mozilla.org/en-US/docs/Web/Events/Creating_and_triggering_events#adding_custom_data_%E2%80%93_customevent) browser API.

## `arweaveWalletLoaded` event

This event is dispatched once the Wander Injected API has been initialized in the `window` object. Before this event is fired, you cannot interact with Wander and the `window.arweaveWallet` object will be undefined.

### Example

```ts
addEventListener("arweaveWalletLoaded", () => {
  // now we can interact with Wander
  const permissions = await window.arweaveWallet.getPermissions();

  if (permissions.length <= 0) {
    await window.arweaveWallet.connect(["ACCESS_ADDRESS"]);
  }
});
```

## `walletSwitch` event

This event is fired when the user manually switches their active wallet. The even also includes the new active wallet's address, if the user allowed the `ACCESS_ADDRESS` and the `ACCESS_ALL_ADDRESSES` permissions.

### Example

```ts
addEventListener("walletSwitch", (e) => {
  const newAddress = e.detail.address;

  // handle wallet switch
});
```

## Event emitter

The event emitter is available under `window.arweaveWallet.events` as a more advanced event system for the extension.

{% hint style="info" %}
**Note:** This documentation is incomplete and the feature is experimental.
{% endhint %}


# Connect

Wander Injected API connect() function

To use the different functionalities the Wander API provides, you need to request permissions from the user to interact with their wallets. Each API function has their own permission(s), which can be requested at any time with the `connect()` function.

| Argument      | Type                                             | Description                                                                       |
| ------------- | ------------------------------------------------ | --------------------------------------------------------------------------------- |
| `permissions` | [`Array<PermissionType>`](#permissions)          | An array of permission to request from the user (at least one has to be included) |
| `appInfo?`    | [`AppInfo`](#additional-application-information) | Additional information about the app                                              |
| `gateway?`    | [`Gateway`](#custom-gateway-config)              | Custom gateway config                                                             |

{% hint style="info" %}
**Note:** The `appInfo` argument is optional, if it is not provided, the extension will use your site's title and favicon as application data.
{% endhint %}

{% hint style="info" %}
**Note:** The `gateway` argument is optional, if it is not provided, the extension will use the default `arweave.net` gateway for the executed API. functions
{% endhint %}

## Permissions

Wander requires specific permissions from the user for each interaction that involves the usage of their wallet.

| Permission              | Description                                                           |
| ----------------------- | --------------------------------------------------------------------- |
| `ACCESS_ADDRESS`        | Allow the app to get the active wallet's address                      |
| `ACCESS_PUBLIC_KEY`     | Enable the app to access the active wallet's public key               |
| `ACCESS_ALL_ADDRESSES`  | Enable the app to access all wallet addresses added to Wander         |
| `SIGN_TRANSACTION`      | Allow the app to sign an Arweave transaction (Base layer)             |
| `ENCRYPT`               | Enable the app to encrypt data with the user's wallet through Wander  |
| `DECRYPT`               | Allow the app to decrypt data encrypted with the user's wallet        |
| `SIGNATURE`             | Allow the app to sign messages with the user's wallet through Wander  |
| `ACCESS_ARWEAVE_CONFIG` | Enable the app to access the current gateway config                   |
| `DISPATCH`              | Allow the app to dispatch a transaction (bundle or base layer)        |
| `ACCESS_TOKENS`         | Allow the app to access all tokens and token balances added in Wander |

## Additional application information

You can provide your application's name and logo to the extension. Please make sure the app name only includes the **name of your application** and the logo is **high quality** and clearly visible on dark and light backgrounds.

```ts
interface AppInfo {
  name?: string; // optional application name
  logo?: string; // optional application logo url
}
```

## Custom gateway config

If your application requires the usage of a special gateway or you want to test with an [ArLocal](https://github.com/textury/arlocal) testnet gateway, you'll have to provide some information about these when connecting to Wander.

```ts
interface Gateway {
  host: string;
  port: number;
  protocol: "http" | "https";
}
```

## Example usage

```ts
// connect to the extension
await window.arweaveWallet.connect(
  // request permissions to read the active address
  ["ACCESS_ADDRESS"],
  // provide some extra info for our app
  {
    name: "Super Cool App",
    logo: "https://arweave.net/jAvd7Z1CBd8gVF2D6ESj7SMCCUYxDX_z3vpp5aHdaYk",
  },
  // custom gateway
  {
    host: "g8way.io",
    port: 443,
    protocol: "https",
  }
);
```


# Disconnect

Wander Injected API disconnect() function

To end the current Wander session for the user, you can disconnect from the extension, using the `disconnect()` function. This removes all permissions from your site and Wander will no longer store application and gateway data related to your application. To use the Injected API again, you'll need to [reconnect](/api/connect).

{% hint style="info" %}
**Note:** It is recommended to only use this function once the user clicks a clearly marked "Disconnect" button in your application.
{% endhint %}

## Example usage

```ts
// connect to the extension
await window.arweaveWallet.connect(["ACCESS_ADDRESS", "SIGN_TRANSACTION"]);

// disconnect from the extension
await window.arweaveWallet.disconnect();
```


# Get active address

Wander Injected API getActiveAddress() function

In order to identify the user's wallet, your application might need to obtain their crypto address. Arweave addresses are derived from the user's public key. The `getActiveAddress()` function returns the address that belongs to the wallet that is currently being used in Wander.

{% hint style="info" %}
**Note:** This function requires the [`ACCESS_ADDRESS`](/api/connect#permissions) permission.
{% endhint %}

## Example usage

```ts
// connect to the extension
await window.arweaveWallet.connect(["ACCESS_ADDRESS"]);

// obtain the user's wallet address
const userAddress = await window.arweaveWallet.getActiveAddress();

console.log("Your wallet address is", userAddress);
```


# Get active public key

ArConnect Injected API getActivePublicKey() function

This function allows you to get the public key of the currently active wallet in Wander.

{% hint style="info" %}
**Note:** This function requires the [`ACCESS_PUBLIC_KEY`](/api/connect#permissions) permission.
{% endhint %}

## Example usage

```ts
// connect to the extension
await window.arweaveWallet.connect(["ACCESS_PUBLIC_KEY"]);

// obtain the user's public key
const publicKey = await window.arweaveWallet.getActivePublicKey();

console.log("JWK.n field is:", publicKey);

// create public key JWK
const publicJWK: JsonWebKey = {
    e: "AQAB",
    ext: true,
    kty: "RSA",
    n: publicKey
};

// import it with webcrypto, etc.
```


# Get all addresses

Wander Injected API getAllAddresses() function

Wander provides enhanced key management for your Arweave wallets. Because of this, the extension might store more than one wallet and your application can take advantage of that. For example, this feature can make it easier for your app to transfer tokens between the user's addresses. The `getAllAddresses()` function returns an array of addresses added to Wander.

{% hint style="info" %}
**Note:** This function requires the [`ACCESS_ALL_ADDRESSES`](/api/connect#permissions) permission.
{% endhint %}

## Example usage

```ts
// connect to the extension
await window.arweaveWallet.connect(["ACCESS_ADDRESS", "ACCESS_ALL_ADDRESSES"]);

// get all wallet addresses added to ArConnect
const addresses = await window.arweaveWallet.getAllAddresses();

// obtain the user's active wallet address
const activeAddress = await window.arweaveWallet.getActiveAddress();

console.log("Your wallet address is", activeAddress);
console.log("You can transfer your assets to your other addresses:\n", addresses.filter((addr) => addr !== activeAddress).join("\n"));
```


# Get wallet names

Wander Injected API getWalletNames() function

In Wander, each wallet has a nickname. This is either the user's [ArNS](https://arns.app/) name, or a user-given nickname. To provide better UX, you can retrive these names and display them for the user, so they can easily recognize which wallet they're using. The `getWalletNames()` function returns an object, where the object keys are the wallet addresses and the values are the nicknames.

{% hint style="info" %}
**Note:** This function requires the [`ACCESS_ALL_ADDRESSES`](/api/connect#permissions) permission.
{% endhint %}

## Example usage

```ts
// connect to the extension
await window.arweaveWallet.connect(["ACCESS_ADDRESS", "ACCESS_ALL_ADDRESSES"]);

// get all wallet names from Wander
const walletNames = await window.arweaveWallet.getWalletNames();

// obtain the user's active wallet address
const activeAddress = await window.arweaveWallet.getActiveAddress();

console.log("Your active wallet's nickname is", walletNames[activeAddress]);
```


# Sign Transaction

Wander Injected API sign() function

To submit a transaction to the Arweave Network, it first has to be signed using a private key. The `sign()` function is meant to replicate the behavior of the `transactions.sign()` function of [`arweave-js`](https://github.com/arweaveTeam/arweave-js#sign-a-transaction), but instead of mutating the transaction object, it returns a new and signed transaction instance.

| Argument      | Type                                                                                                                     | Description                                                  |
| ------------- | ------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------ |
| `transaction` | [`Transaction`](https://github.com/arweaveTeam/arweave-js#transactions)                                                  | A valid Arweave transaction instance (**without a keyfile**) |
| `options?`    | [`SignatureOptions`](https://github.com/ArweaveTeam/arweave-js/blob/master/src/common/lib/crypto/crypto-interface.ts#L3) | Arweave transaction signature options                        |

{% hint style="info" %}
**Note:** This function requires the [`SIGN_TRANSACTION`](/api/connect#permissions) permission.
{% endhint %}

{% hint style="info" %}
**Note:** The `options` argument is optional, if it is not provided, the extension will use the default signature options (default salt length) to sign the transaction.
{% endhint %}

{% hint style="warning" %}
**Tip:** A better alternative to this function is using the [`arweave-js`](https://github.com/arweaveTeam/arweave-js#sign-a-transaction) `transactions.sign()` instead. Just omit the second parameter (`JWK` key) when calling the method, and [`arweave-js`](https://github.com/arweaveTeam/arweave-js#sign-a-transaction) will automatically use Wander.
{% endhint %}

{% hint style="warning" %}
**Note:** If you are trying to sign a larger piece of data (5 MB <), make sure to notify the user to not switch / close the browser tab. Larger transactions are split into chunks in the background and will take longer to sign.
{% endhint %}

## Example usage

### With `arweave-js` (recommended)

```ts
import Arweave from "arweave";

// create arweave client
const arweave = new Arweave({
  host: "ar-io.net",
  port: 443,
  protocol: "https"
});

// connect to the extension
await window.arweaveWallet.connect(["SIGN_TRANSACTION"]);

// create a transaction
const transaction = await arweave.createTransaction({
  data: '<html><head><meta charset="UTF-8"><title>Hello permanent world! This was signed via Wander!!!</title></head><body></body></html>'
});

// sign using arweave-js
await arweave.transactions.sign(transaction);

// TODO: post the transaction to the network
```

### Directly using Wander

```ts
import Arweave from "arweave";

// create arweave client
const arweave = new Arweave({
  host: "ar-io.net",
  port: 443,
  protocol: "https"
});

// connect to the extension
await window.arweaveWallet.connect(["SIGN_TRANSACTION"]);

// create a transaction
let transaction = await arweave.createTransaction({
  data: '<html><head><meta charset="UTF-8"><title>Hello permanent world! This was signed via Wander!!!</title></head><body></body></html>'
});

// sign using arweave-js
const signedFields = await window.arweaveWallet.sign(transaction);

// update transaction fields with the
// signed transaction's fields
transaction.setSignature({
  id: signedFields.id,
  owner: signedFields.owner,
  reward: signedFields.reward,
  tags: signedFields.tags,
  signature: signedFields.signature
});

// TODO: post the transaction to the network
```


# Dispatch Transaction

Wander Injected API dispatch() function

The `dispatch()` function allows you to quickly sign and send a transaction to the network in a bundled format. It is best for smaller datas and contract interactions. If the bundled transaction cannot be submitted, it will fall back to a base layer transaction. The function returns the [result](#dispatch-result) of the API call.

| Argument      | Type                                                                    | Description                                                  |
| ------------- | ----------------------------------------------------------------------- | ------------------------------------------------------------ |
| `transaction` | [`Transaction`](https://github.com/arweaveTeam/arweave-js#transactions) | A valid Arweave transaction instance (**without a keyfile**) |

{% hint style="info" %}
**Note:** This function requires the [`DISPATCH`](/api/connect#permissions) permission.
{% endhint %}

{% hint style="warning" %}
**Note:** If you are trying to sign a larger piece of data (5 MB <), make sure to notify the user to not switch / close the browser tab. Larger transactions are split into chunks in the background and will take longer to sign.
{% endhint %}

{% hint style="warning" %}
**Note:** The function uses the default bundler node set by the user or the extension. Consider using the [`signDataItem()`](/api/sign-dataitem) function to submit data to a custom bundler.&#x20;
{% endhint %}

## Dispatch result

The `dispatch()` function returns the result of the operation, including the ID of the submitted transaction, as well as if it was submitted in a bundle or on the base layer.

```ts
export interface DispatchResult {
  id: string;
  type?: "BASE" | "BUNDLED";
}
```

## Example usage

```ts
import Arweave from "arweave";

// create arweave client
const arweave = new Arweave({
  host: "ar-io.net",
  port: 443,
  protocol: "https"
});

// connect to the extension
await window.arweaveWallet.connect(["DISPATCH"]);

// create a transaction
const transaction = await arweave.createTransaction({
  data: '<html><head><meta charset="UTF-8"><title>Hello permanent world! This was signed via Wander!!!</title></head><body></body></html>'
});

// dispatch the tx
const res = await window.arweaveWallet.dispatch(transaction);

console.log(`The transaction was dispatched as a ${res.type === "BUNDLED" ? "bundled" : "base layer"} Arweave transaction.`)
```


# Sign DataItem

Wander Injected API signDataItem() function

The signDataItem() function allows you to create and sign a data item object, compatible with [`arbundles`](https://www.npmjs.com/package/@dha-team/arbundles). These data items can then be submitted to an [ANS-104](https://github.com/ArweaveTeam/arweave-standards/blob/master/ans/ANS-104.md) compatible bundler.

| Argument   | Type                     | Description                   |
| ---------- | ------------------------ | ----------------------------- |
| `dataItem` | [`DataItem`](#data-item) | The bundled data item to sign |

{% hint style="info" %}
**Note:** This function requires the [`SIGN_TRANSACTION`](/api/connect#permissions) permission.
{% endhint %}

{% hint style="warning" %}
**Warning:** The function returns a buffer of the signed data item. You'll need to manually load it into an [`arbundles`](https://www.npmjs.com/package/@dha-team/arbundles) `DataItem` instance as seen in the [example usage](#example-usage).
{% endhint %}

## Data item

This function requires a valid data item object, like so:

```typescript
export interface DataItem {
  data: string | Uint8Array;
  target?: string;
  anchor?: string;
  tags?: {
    name: string;
    value: string;
  }[];
}
```

## Example usage

```ts
import { DataItem } from "@dha-team/arbundles";

// connect to the extension
await window.arweaveWallet.connect(["SIGN_TRANSACTION"]);

// sign the data item
const signed = await window.arweaveWallet.signDataItem({
  data: "This is an example data",
  tags: [
    {
      name: "Content-Type",
      value: "text/plain",
    },
  ],
});

// load the result into a DataItem instance
const dataItem = new DataItem(signed);

// now you can submit it to a bunder
await fetch(`https://upload.ardrive.io/v1/tx`, {
  method: "POST",
  headers: {
    "Content-Type": "application/octet-stream",
  },
  body: dataItem.getRaw(),
});
```


# Batch Sign DataItem

Wander Injected API batchSignDataItem() function

The batchSignDataItem() function allows you to create and sign an array of data item objects, compatible with [`arbundles`](https://www.npmjs.com/package/@dha-team/arbundles). These data items can then be submitted to an [ANS-104](https://github.com/ArweaveTeam/arweave-standards/blob/master/ans/ANS-104.md) compatible bundler.

| Argument    | Type                       | Description                    |
| ----------- | -------------------------- | ------------------------------ |
| `dataItems` | [`DataItem[]`](#data-item) | An array of data items to sign |

{% hint style="info" %}
**Note:** This function requires the [`SIGN_TRANSACTION`](/api/connect#permissions) permission.
{% endhint %}

{% hint style="warning" %}
**Warning:** This function is designed to sign multiple small data items. There is a limit of 200kb total for the function. Please ensure that the combined size of all data items does not exceed this limit.
{% endhint %}

{% hint style="warning" %}
**Warning:** The function returns an array of buffers of the signed data items. You'll need to manually load them into an [`arbundles`](https://www.npmjs.com/package/@dha-team/arbundles) `DataItem` instance as seen in the [example usage](#example-usage).
{% endhint %}

## Data item

This function requires valid data item objects, like so:

```typescript
export interface DataItem[] {
  data: string | Uint8Array;
  target?: string;
  anchor?: string;
  tags?: {
    name: string;
    value: string;
  }[];
}
```

## Example usage

```ts
import { DataItem } from "@dha-team/arbundles";

// connect to the extension
await window.arweaveWallet.connect(["SIGN_TRANSACTION"]);

// sign the data item
const signed = await window.arweaveWallet.batchSignDataItem([
  {
    data: "This is an example transaction 1",
    tags: [
      {
        name: "Content-Type",
        value: "text/plain",
      },
    ],
  },
  {
    data: "This is an example transaction 2",
    tags: [
      {
        name: "Content-Type",
        value: "text/plain",
      },
    ],
  },
]);

// load the result into a DataItem instance
const dataItems = signed.map((buffer) => new DataItem(buffer));

// now you can submit them to a bundler
for (const dataItem of dataItems) {
  await fetch(`https://upload.ardrive.io/v1/tx`, {
    method: "POST",
    headers: {
      "Content-Type": "application/octet-stream",
    },
    body: dataItem.getRaw(),
  });
}
```


# Sign message

Wander Injected API signMessage() function

This function allows creating a cryptographic signature for any piece of data for later validation.

| Argument   | Type                             | Description                            |
| ---------- | -------------------------------- | -------------------------------------- |
| `data`     | `ArrayBuffer`                    | The data to generate the signature for |
| `options?` | [`SignMessageOptions`](#options) | Configuration for the signature        |

{% hint style="info" %}
**Note:** This function requires the [`SIGNATURE`](/api/connect#permissions) permission.
{% endhint %}

{% hint style="warning" %}
**Note**: This function should only be used to allow data validation. It cannot be used for on-chain transactions, interactions or bundles, for security reasons. Consider implementing [`sign()`](/api/sign), [`signDataItem()`](/api/sign-dataitem) or [dispatch()](/api/dispatch).
{% endhint %}

{% hint style="warning" %}
**Note**: The function first hashes the input data for security reasons. We recommend using the built in [`verifyMessage()`](/api/verify-message) function to validate the signature, or hashing the data the same way, before validation ([example](#verification-without-arconnect)).
{% endhint %}

{% hint style="info" %}
**Note:** The `options` argument is optional, if it is not provided, the extension will use the default signature options (default hash algorithm: `SHA-256`) to sign the data.
{% endhint %}

## Options

Currently Wander allows you to customize the hash algorithm (`SHA-256` by default):

```typescript
export interface SignMessageOptions {
  hashAlgorithm?: "SHA-256" | "SHA-384" | "SHA-512";
}
```

## Example usage

```ts
// connect to the extension
await window.arweaveWallet.connect(["SIGNATURE"]);

// message to be signed
const data = new TextEncoder().encode("The hash of this msg will be signed.");

// create signature
const signature = await window.arweaveWallet.signMessage(data);

// verify signature
const isValidSignature = await window.arweaveWallet.verifyMessage(data, signature);

console.log(`The signature is ${isValidSignature ? "valid" : "invalid"}`);
```

## Verification without Wander

You might encounter situations where you need to verify the signed message against an Wander generated signature, but the extension is not accessible or not installed (for e.g.: server side code, unsupported browser, etc.).

In these cases it is possible to validate the signature by hashing the message (with the algorithm you used when generating the signature through Wander) and verifying that against the Wander signature. This requires the message to be verified, the signature and the [wallet's public key](/api/get-active-public-key). Below is the JavaScript (TypeScript) example implementation with the [Web Crypto API](https://developer.mozilla.org/en-US/docs/Web/API/Web_Crypto_API), using `SHA-256` hashing:

{% hint style="info" %}
*Wander was formerly know as ArConnect.  There are some API references that still use ArConnect*
{% endhint %}

```typescript
// connect to the extension
await window.arweaveWallet.connect(["SIGNATURE"]);

// message to be signed
const data = new TextEncoder().encode("The hash of this msg will be signed.");

// create signature
const signature = await window.arweaveWallet.signMessage(data);

/** This is where we start the verification **/
// hash the message (we used the default signMessage() options
// so the extension hashed the message using "SHA-256"
const hash = await crypto.subtle.digest("SHA-256", data);

// import public JWK
// we need the user's public key for this
const publicJWK: JsonWebKey = {
    e: "AQAB",
    ext: true,
    kty: "RSA",
    // !! You need to obtain this on your own !!
    // possible ways are: 
    // - getting from Wander if available
    // - storing it beforehand
    // - if the wallet has made any transactions on the Arweave network
    //   the public key is going to be the owner field of the mentioned
    //   transactions
    n: publicKey
};

// import public jwk for verification
const verificationKey = await crypto.subtle.importKey(
    "jwk",
    publicJWK,
    {
      name: "RSA-PSS",
      hash: "SHA-256"
    },
    false,
    ["verify"]
);

// verify the signature by matching it with the hash
const isValidSignature = await crypto.subtle.verify(
    { name: "RSA-PSS", saltLength: 32 },
    verificationKey,
    signature,
    hash
);

console.log(`The signature is ${isValidSignature ? "valid" : "invalid"}`);
```


# Verify message

Wander Injected API verifyMessage() function

This function allows verifying a cryptographic signature [created by ](/api/sign-message)Wander.

| Argument     | Type                                              | Description                                                                                                    |
| ------------ | ------------------------------------------------- | -------------------------------------------------------------------------------------------------------------- |
| `data`       | `ArrayBuffer`                                     | The data to verify the signature for                                                                           |
| `signature`  | `ArrayBuffer \| string`                           | The signature to validate                                                                                      |
| `publicKey?` | `string`                                          | Arweave wallet `JWK.n` field, transaction owner field or [public key from Wander](/api/get-active-public-key). |
| `options?`   | [`SignMessageOptions`](/api/sign-message#options) | Configuration for the signature                                                                                |

{% hint style="info" %}
**Note:** This function requires the [`SIGNATURE`](/api/connect#permissions) permission.
{% endhint %}

{% hint style="info" %}
**Note:** The `publicKey` argument is optional, if it is not provided, the extension will use the currently selected wallet's public key. You might only need this if the message to be verified was not made by the connected user.
{% endhint %}

{% hint style="info" %}
**Note:** The `options` argument is optional, if it is not provided, the extension will use the default signature options (default hash algorithm) to sign the data.
{% endhint %}

## Example usage

```ts
// connect to the extension
await window.arweaveWallet.connect(["SIGNATURE"]);

// data to be signed
const data = new TextEncoder().encode("The hash of this msg will be signed.");

// create signature
const signature = await window.arweaveWallet.signMessage(data);

// verify signature
const isValidSignature = await window.arweaveWallet.verifyMessage(data, signature);

console.log(`The signature is ${isValidSignature ? "valid" : "invalid"}`);
```


# Private hash

Wander Injected API privateHash() function

The `privateHash()` function allows you to create deterministic secrets (hashes) from some data.

| Argument  | Type                                              | Description                |
| --------- | ------------------------------------------------- | -------------------------- |
| `data`    | `ArrayBuffer`                                     | The data to hash           |
| `options` | [`SignMessageOptions`](/api/sign-message#options) | Configuration for the hash |

{% hint style="info" %}
**Note:** This function requires the [`SIGNATURE`](/api/connect#permissions) permission.
{% endhint %}

## Example usage

```ts
// connect to the extension
await window.arweaveWallet.connect(["SIGNATURE"]);

// data to be hashed
const data = new TextEncoder().encode("The hash of this msg will be signed.");

// create the hash using the active wallet
const hash = await window.arweaveWallet.privateHash(
    data,
    { hashAlgorithm: "SHA-256" }
);

console.log("Data hash is", hash);
```


# User Tokens

Wander Injected API userTokens() function

Some applications may request access to the tokens in your wallet and their associated balances. The `userTokens()` function returns the [result](#result) from the API call.

| Argument   | Type                            | Description                             |
| ---------- | ------------------------------- | --------------------------------------- |
| `options?` | [`UserTokensOptions`](#options) | Optional settings for balance inclusion |

{% hint style="info" %}
**Note:** This function requires the [`ACCESS_TOKENS`](/api/connect#permissions) permission.
{% endhint %}

{% hint style="info" %}
**Note:** The `options` argument is optional. If not provided, the balance will not be included in the result.
{% endhint %}

## Options

Currently Wander allows you to customize the balance fetching behavior (`false` by default):

```typescript
export interface UserTokensOptions {
  fetchBalance?: boolean;
}
```

## Result

The `userTokens()` function returns an array of token information objects. If the `fetchBalance` option is set to `true`, each token object will include its balance. The `balance` property of the token object may be `null` if there is an issue retrieving it.

```typescript
export type UserTokensResult = Array<{
  Name?: string;
  Ticker?: string;
  Logo?: string;
  Denomination: number;
  processId: string;
  balance?: string | null;
}>
```

## Example usage

```ts
// Connect to the extension and request access to the ACCESS_TOKENS permission
await window.arweaveWallet.connect(["ACCESS_TOKENS"]);

// Retrieve the list of tokens owned by the user
const tokens = await window.arweaveWallet.userTokens();
console.log("Tokens owned by the user:", tokens);

// Retrieve the list of tokens owned by the user, including their balances
const tokensWithBalances = await window.arweaveWallet.userTokens({ fetchBalance: true });
console.log("Tokens with their balances:", tokensWithBalances);
```


# Token Balance

Wander Injected API tokenBalance() function

Some applications may request access to the balance of a specific token in your wallet. The `tokenBalance()` function returns the balance of the token identified by its ID.

| Argument | Type   | Description                                    |
| -------- | ------ | ---------------------------------------------- |
| `id`     | string | The unique identifier (processId) of the token |

{% hint style="info" %}
**Note:** This function requires the [`ACCESS_TOKENS`](/api/connect#permissions) permission.
{% endhint %}

## Result

The `tokenBalance()` function returns the balance of the requested token as a string.

{% hint style="warning" %}
**Note**: This function throws an error if there is an issue retrieving the balance. Please make sure to handle such cases in your code.
{% endhint %}

```typescript
export type TokenBalanceResult = string;
```

## Example usage

```ts
// Connect to the extension and request access to the ACCESS_TOKENS permission
await window.arweaveWallet.connect(["ACCESS_TOKENS"]);

// Retrieve the list of tokens owned by the user
const tokens = await window.arweaveWallet.userTokens();
console.log("Tokens owned by the user:", tokens);

try {
  // Retrieve the balance of a user token
  const tokenId = tokens[0].processId
  const balance = await window.arweaveWallet.tokenBalance(tokenId);
  console.log(`Balance of the token with ID ${tokenId}:`, balance);
} catch (error) {
  console.error("Error fetching token balance:", error);
}
```


# Encrypt

Wander Injected API encrypt() function

Some applications (such as private file storage apps, mail clients, messaging platforms) might want to upload content to Arweave that is encrypted and only accessible by the user via their private key. The `encrypt()` function does just that: it encrypts data with the active private key and returns the encrypted bytes, similarly to the [webcrypto encrypt API](https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/encrypt).

| Argument    | Type                                                                                                                                                                                                                                                                                                                                   | Description                                                                        |
| ----------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------- |
| `data`      | [`ArrayBuffer`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/ArrayBuffer), [`TypedArray`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray) or [`DataView`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/DataView)  | The data to be encrypted with the user's private key                               |
| `algorithm` | [`RsaOaepParams`](https://developer.mozilla.org/en-US/docs/Web/API/RsaOaepParams), [`AesCtrParams`](https://developer.mozilla.org/en-US/docs/Web/API/AesCtrParams), [`AesCbcParams`](https://developer.mozilla.org/en-US/docs/Web/API/AesCbcParams) or [`AesGcmParams`](https://developer.mozilla.org/en-US/docs/Web/API/AesGcmParams) | An object specifying the algorithm to be used and any extra parameters if required |

{% hint style="info" %}
**Note:** This function requires the [`ENCRYPT`](/api/connect#permissions) permission.
{% endhint %}

## Example usage

```typescript
// connect to the extension
await window.arweaveWallet.connect(["ENCRYPT"]);

// encrypt data using RSA-OAEP
const encrypted = await arweaveWallet.encrypt(
    new TextEncoder().encode("This message will be encrypted"),
    { name: "RSA-OAEP" }
);

console.log("Encrypted bytes:", encrypted);
```

### Old (deprecated) usage

```ts
// connect to the extension
await window.arweaveWallet.connect(["ENCRYPT"]);

// encrypt data
const encrypted = await window.arweaveWallet.encrypt(
  new TextEncoder().encode("This message will be encrypted"),
  {
    algorithm: "RSA-OAEP",
    hash: "SHA-256",
  }
);

console.log("Encrypted bytes", encrypted);
```


# Decrypt

Wander Injected API decrypt() function

Data [encrypted with the user's wallet](/api/encrypt) should be accessible by the owner of the private key. The `decrypt()` function allows applications to decrypt any piece of data encrypted with the user's private key, similarly to the [webcrypto encrypt API](https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/decrypt).

| Argument    | Type                                                                                                                                                                                                                                                                                                                                   | Description                                                                        |
| ----------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------- |
| `data`      | [`ArrayBuffer`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/ArrayBuffer), [`TypedArray`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray) or [`DataView`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/DataView)  | The encrypted data to be decrypted with the user's private key                     |
| `algorithm` | [`RsaOaepParams`](https://developer.mozilla.org/en-US/docs/Web/API/RsaOaepParams), [`AesCtrParams`](https://developer.mozilla.org/en-US/docs/Web/API/AesCtrParams), [`AesCbcParams`](https://developer.mozilla.org/en-US/docs/Web/API/AesCbcParams) or [`AesGcmParams`](https://developer.mozilla.org/en-US/docs/Web/API/AesGcmParams) | An object specifying the algorithm to be used and any extra parameters if required |

{% hint style="info" %}
**Note:** This function requires the [`DECRYPT`](/api/connect#permissions) permission.
{% endhint %}

## Example usage

```typescript
// connect to the extension
await window.arweaveWallet.connect(["ENCRYPT", "DECRYPT"]);

// encrypt data using RSA-OAEP
const encrypted = await arweaveWallet.encrypt(
    new TextEncoder().encode("This message will be encrypted"),
    { name: "RSA-OAEP" }
);

console.log("Encrypted bytes:", encrypted);

// now decrypt the same data using
// the same algorithm
const decrypted = await arweaveWallet.decrypt(
    encrypted,
    { name: "RSA-OAEP" }
);

console.log(
    "Decrypted data:",
    new TextDecoder().decode(decrypted)
);
```

### Old (deprecated) usage

```ts
// connect to the extension
await window.arweaveWallet.connect(["ENCRYPT", "DECRYPT"]);

// encrypt data
const encrypted = await window.arweaveWallet.encrypt(
  new TextEncoder().encode("This message will be encrypted"),
  {
    algorithm: "RSA-OAEP",
    hash: "SHA-256",
  }
);

console.log("Encrypted bytes:", encrypted);

// decrypt data
const decrypted = await window.arweaveWallet.decrypt(
  encrypted,
  {
    algorithm: "RSA-OAEP",
    hash: "SHA-256",
  }
);

console.log("Decrypted data:", new TextDecoder().decode(decrypted));
```


# Crypto signature

Wander Injected API signature() function

{% hint style="danger" %}
**Deprecation warning:** The `signature()` function is deprecated in ArConnect 1.0.0. Read about the alternatives below.
{% endhint %}

## Alternatives

There are quite a few cases where you might need to generate a cryptographic signature for a piece of data or message so that you can verify them. The most common ones and their alternatives are the following:

* Generating a signature for a transaction: [`sign()`](/api/sign)
* Generating a signature for a bundle data item: [`signDataItem()`](/api/sign-dataitem) or [`dispatch()`](/api/dispatch)
* Signing a message to later validate ownership: [`signMessage()`](/api/sign-message) combined with [`verifyMessage()`](/api/verify-message)

The safety of our users' wallets is our top priority, so we've decided to deprecate our `signature()` function, following the example of *Arweave.app* and we expect other Arweave wallets now or in the future to do the same, so eventually, this should be a smooth transition to the new alternatives. We are sorry for any inconveniences caused by this change.

~~Often an application might need a piece of data that is created, authorized or confirmed by the owner of a wallet. The `signature()` function creates a cryptographical signature that allows applications to verify if a piece of data has been signed using a specific wallet. This function works similarly to the~~ [~~webcrypto sign API~~](https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/sign)~~.~~

| Argument        | Type                                                                                                                                                                                                                                                                                                                                                      | Description                                                                            |
| --------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------- |
| ~~`data`~~      | [~~`ArrayBuffer`~~](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/ArrayBuffer)~~,~~ [~~`TypedArray`~~](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray) ~~or~~ [~~`DataView`~~](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/DataView) | ~~The encrypted data to be signed with the user's private key~~                        |
| ~~`algorithm`~~ | [~~`RsaPssParams`~~](https://developer.mozilla.org/en-US/docs/Web/API/RsaPssParams)~~, `AesCmacParams` or~~ [~~`EcdsaParams`~~](https://developer.mozilla.org/en-US/docs/Web/API/EcdsaParams)                                                                                                                                                             | ~~An object specifying the algorithm to be used and any extra parameters if required~~ |

{% hint style="info" %}
~~**Note:** This function requires the~~ [~~`SIGNATURE`~~](/api/connect#permissions) ~~permission.~~
{% endhint %}

{% hint style="warning" %}
~~**Note:** Not to be confused with the~~ [~~`sign()`~~](/api/sign) ~~function that is created to sign Arweave transactions.~~
{% endhint %}

## ~~Example usage~~

```ts
// connect to the extension
await window.arweaveWallet.connect(["SIGNATURE"]);

// sign data
const signature = await window.arweaveWallet.signature(new TextEncoder().encode("Data to sign"), {
  name: 'RSA-PSS',
  saltLength: 0,
});

console.log("The signature is", signature);
```


# Subscriptions

Wander Injected API subscription() function

Subscriptions is a feature that allows users to subscribe to applications and be charged on a periodic basis such as monthly, weekly, or quarterly. Users will be charged the moment they subscribe

<table><thead><tr><th width="283">Argument</th><th width="278">Type</th><th>Description</th></tr></thead><tbody><tr><td><code>arweaveAccountAddress</code></td><td><code>string</code></td><td>The account address where payments will be made</td></tr><tr><td><code>applicationName</code></td><td><code>string</code></td><td>The name of your application</td></tr><tr><td><code>subscriptionName</code></td><td><code>string</code></td><td>The name of the subscription</td></tr><tr><td><code>subscriptionManagementUrl</code></td><td><code>string</code></td><td>A URL where users are able to manage their subscriptions</td></tr><tr><td><code>subscriptionFeeAmount</code></td><td><code>number</code></td><td>The amount in AR to be paid each period</td></tr><tr><td><code>recurringPaymentFrequency</code></td><td><a href="#recurring-payment-frequency"><code>RecurringPaymentFrequency</code></a></td><td>Frequency for period to be charged</td></tr><tr><td><code>subscriptionEndDate</code></td><td><code>Date</code></td><td>When the subscription ends</td></tr><tr><td><code>applicationIcon</code></td><td><code>string</code></td><td>URL where an image is hosted, ideally 48x48</td></tr></tbody></table>

{% hint style="info" %}
**Note:** This function requires the [`ACCESS_ALL_ADDRESSES`](/api/connect#permissions) permission.
{% endhint %}

## Recurring Payment Frequency

This function requires a recurring frequency such as listed:

Recurring Payment Frequency

```typescript
export enum RecurringPaymentFrequency {
  QUARTERLY = "Quarterly",
  MONTHLY = "Monthly",
  WEEKLY = "Weekly",
  DAILY = "Daily",
}
```

## Example usage

{% hint style="info" %}
*Wander was formerly know as ArConnect. There are some API references that still use ArConnect*
{% endhint %}

```ts
// connect to the extension
await window.arweaveWallet.connect(["ACCESS_ALL_ADDRESSES"]);

// submit the subscription information
const subscription = await window.arweaveWallet.subscription({
  arweaveAccountAddress: "hY70z-mbKfDByqXh4y43ybSxReFVo1i9lB1dDdCkO_U",
  applicationName: "Wander",
  subscriptionName: "Wander Premium",
  subscriptionManagementUrl: "https://wander.app/premium",
  subscriptionFeeAmount: 0.5,
  recurringPaymentFrequency: "Monthly",
  subscriptionEndDate: new Date("2024-12-31"),
  applicationIcon: "https://wander.app/logo",
});

// Subscription will output the details and the initial payment txn
console.log("Subscription details with paymentHistory array:", subscription);
```


# Retrive permissions

Wander Injected API getPermissions() function

As discussed [here](/api/connect#permissions), Wander requires a specific type of permission for each API function that involves an action with the user's wallet. It is important for an application to be aware of the permissions given to them by the user. The `getPermissions()` function returns an array of permissions given to the current application. If the array is empty, it means that the app has not yet connected to the extension.

## Example usage

```ts
// get permissions
const permissions = await window.arweaveWallet.getPermissions();

console.log("The app has the following permissions:", permissions);
```


# Retrive Gateway Config

Wander Injected API getArweaveConfig() function

It can be useful to know what Arweave gateway the extension uses for your application. You can set this when [connecting](/api/connect#custom-gateway-config) your application to Wander, but the user can always update it later. Using the `getArweaveConfig()`, you can make sure your application works, no matter what gateway the extension uses.

{% hint style="info" %}
**Note:** This function requires the [`ACCESS_ARWEAVE_CONFIG`](/api/connect#permissions) permission.
{% endhint %}

## Example usage

```ts
import Arweave from "arweave";

// connect to the extension
await window.arweaveWallet.connect(["ACCESS_ARWEAVE_CONFIG"]);

// get the current gateway
const gateway = await window.arweaveWallet.getArweaveConfig();

// setup an arweave-js client using
// the obtained gateway 
const client = new Arweave(gateway);
```


