# Introducing Tomo

"Tomo" means "Friend" in Japanese

In the rapidly evolving landscape of decentralized finance (DeFi) and Web3, managing digital assets and interacting with various applications can be a complex and fragmented experience.

1. **Fragmented Wallet Experience**: Users often need to manage multiple wallets for different chains and dApps, leading to fragmented and cumbersome user experience and inconsistent service quality.
2. **Complex Access Management**: Securely accessing wallets across various platforms typically involves multiple passwords, seed phrases, and authentication methods, which can be confusing and prone to user error.
3. **Integration Challenges for Developers**: Integrating wallet functionalities into applications can be daunting for developers, requiring significant time and effort to ensure compatibility and security.

Users and developers face the challenge of navigating multiple wallets, maintaining private keys and secure access across different platforms, and integrating seamlessly with various applications.

### What is Tomo

[Tomo ](https://tomo.inc/)is here to revolutionize this experience by providing a streamlined, secure, and user-friendly Web3 wallet solution. We provide an all-in-one Web3 social wallet designed to bring the mass adoption of crypto while using the highest standard for our user's asset security. Tomo provides two product lines: Tomo Labs and Tomo Wallets. **Tomo Labs** focuses on helping developers integrate social and wallet logins into their products and provide a web2-like user experience for all users. **Tomo Wallets** offer the highest security guarantee, allowing users to securely access their wallets and manage their assets across different devices.

### Why Choose Tomo?

On Tomo, users can easily manage assets, send crypto to each other, chat, post content, make friends, participate in the crypto community, and trade according to the latest market movement.

1. **Cross Platforms Social Login Integration**: Tomo allows users to access their wallets through a simple and secure social login, eliminating the need for multiple passwords and seed phrases. We support users creating and connecting their wallets with social accounts like X, Facebook, Google, Apple, and more. This feature ensures a smooth user experience across different platforms like iOS, Android, Web, and Apple Vision Pro, etc., making it easier than ever to manage digital assets.
2. **Rich Asset Management Integration:** Tomo wallets provide multi-chain support for Bitcoin, Ethereum, Cosmos, Solana, and various EVM chains. We provide various functions for users to manage their on-chain assets, from basic send/receive to dApp integration. We also provide smooth integration of cross-chain swap functions, so users can easily exchange tokens across different blockchains with one click.
3. **Enhanced Trader Experience:** Tomo is a Web3-rooted wallet that tries its best to help users catch up on all important market movements. While using the Tomo wallet, users can find crypto communities that share the same interests and receive the latest market news. We also provide complete trade functionality, so users can easily purchase cryptos with cryptos or an Integrated Fiat Onramp.
4. **dApp integration**: Tomo Labs provides a tool kit for dApps to integrate wallet service into their product so that users can connect their Tomo wallet or third-party wallet with the dApp smoothly. The Tomo wallet can provide a smooth experience for users to explore new Web3 products with their existing assets through our trade functionality.
5. **Security Insurance**: Tomo incorporates state-of-the-art security measures to protect user assets and data. From [secure hardware wallets ](/overview/tomos-key-management)based on trusted execution environments (TEE) to rigorous access control and authentication protocols, Tomo ensures that users' digital assets are always safe and accessible.

\
**Join Tomo and enjoy the web3 journey in a new style!**

***

## Backed by Industry Leaders

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


# Tomo's Key Management

Tomo Social Wallet uses OAuth and TEE to provide secure service.

#### **OAuth**

[OAuth ](https://cloud.google.com/apigee/docs/api-platform/security/oauth/oauth-introduction)(Open Authorization) is a widely adopted standard for authorization that allows users to grant websites or applications access to their information without exposing their passwords. OAuth uses established social media platforms with robust security measures, such as two-factor authentication (2FA) and continuous monitoring for suspicious activities. As long as the social account is secure, you don't need to worry about losing your private key.

#### **TEE**

OAuth provides authentication to the wallet, and hardware wallets based on the Trusted Execution Environment (TEE) provide rock-solid security for your private key. TEE is a secure area within a device's main processor that ensures sensitive data is stored, processed, and protected in an isolated environment. Hardware wallets based on TEE leverage this technology to manage private keys and execute cryptographic operations securely. No matter who owns the device, a wallet in TEE is always owned and can only be operated by you.\
TEE protects against attacks, ensuring that private keys are securely stored and never exposed outside the secure environment. Hardware wallets with TEE are designed to resist physical tampering, adding an extra layer of security. Any access to the private key requires the user to use MFA to confirm the operation. Users can have greater confidence in the security of their wallets, knowing that hardware-level security measures protect their private keys.

<figure><img src="/files/9lIBxuaUgcW5aEg1QEyc" alt=""><figcaption><p>Security guarantee of Tomo social wallet</p></figcaption></figure>

#### Integration

Integrating social login with OAuth and hardware wallets based on TEE into a single social wallet combines the strengths of both approaches. Using social login with OAuth, users can quickly and easily connect their wallets through familiar social media accounts and enjoy wallet recovery if the old device is inaccessible. The TEE-based hardware wallet ensures that private keys and cryptographic operations are securely managed, providing robust protection against unauthorized access and attacks.

#### **Control the key yourself**.

We fully understand users may want to control their keys themselves. Therefore, Tomo allows users to export their private key to their social wallet anytime. The user needs to download a Tomo mobile wallet or Tomo Extension wallet to verify their identity and intention to export the key. With all confirmations accomplished, the client (mobile / extension wallet ) can directly access the hardware wallet, retrieve the private key to the local environment, and keep it safe.\
In summary, Tomo social wallet presents a powerful solution that addresses the dual challenges of security and user experience. This integrated approach between OAuth and TEE ensures that users can enjoy the convenience of social logins while benefiting from the robust security offered by edge hardware wallet technology, ultimately fostering broader adoption and trust in blockchain-based applications.


# TomoEVMKit

TomoEVMKit provides a unified solution for Web3 authentication. It integrates social login options (email, Google, Telegram, Twitter, KakaoTalk) alongside support for all major EVM wallets.

## Enhanced RainbowKit

<figure><img src="/files/idBrKZpsg3Gm2l2qaV9J" alt=""><figcaption><p>TomoEVMKit UI</p></figcaption></figure>

**TomoEVMKit** extends **RainbowKit** with the following enhancements:

**• Embedded Wallet:** A non-custodial wallet created upon social login, ensuring seamless and secure onboarding for users.

**• Social Login Support:** Users can log in using popular platforms like Google, Telegram, Twitter, and Kakao. Each social login automatically generates a secure, non-custodial wallet, powered by Cubist’s enterprise-grade infrastructure.

**• Improved Security:** App information is now securely retrieved via API using a \`clientId\`, protecting against phishing risks.

#### Embedded Wallet

Powered by Cubist: Ensures high security for user wallets. Learn more at [cubist.dev](https://cubist.dev/).

For developers already using RainbowKit, Tomo EVM Kit expands login options while preserving existing wallet functionality. Meet your users wherever they are: any wallet, any login option.

#### Demo&#x20;

You can explore our [demo site](http://tomoevmkit.pages.dev/) to experience our SDK UI and features.


# Enhanced RainbowKit

<figure><img src="/files/H9zKgxK83jqBrxLHnyZb" alt=""><figcaption><p>TomoEVMKit UI</p></figcaption></figure>

**TomoEVMKit** extends **RainbowKit** with the following enhancements:

**• Embedded Wallet:** A non-custodial wallet created upon social login, ensuring seamless and secure onboarding for users.

**• Social Login Support:** Users can log in using popular platforms like Google, Telegram, Twitter, and Kakao.

**• Improved Security:** App information is now securely retrieved via API using a \`clientId\`, protecting against phishing risks.

#### Embedded Wallet

Powered by Cubist: Ensures high security for user wallets. Learn more at [cubist.dev](https://cubist.dev/).


# Quick Start

## Installation

```bash
npm install @tomo-inc/tomo-evm-kit
```

or

```bash
pnpm i @tomo-inc/tomo-evm-kit
```

## Import Styles

```javascript
import '@tomo-inc/tomo-evm-kit/styles.css';
```

## Use TomoEVMKitProvider

### Create a Project and Retrieve clientId

* [Talk to us](https://docs.google.com/forms/d/e/1FAIpQLSfqMQH80c9Py0V1rNDgfXqL8kNXKn66WMCgtczNLriruJicjw/viewform) to create a developer account. Please provide a non-gmail business email address.
* Log in to the [Tomo Developer Dashboard](https://dashboard.tomo.inc/).
* Create a new project and copy the generated `clientId`.
* Use this `clientId` in your TomoEVMKitProvider.

### Setup Provider

#### Use React, Wagmi and Viem

Use a `clientId` obtained from the <https://dashboard.tomo.inc/>. Your application will fetch application data from our backend with `clientId`

```tsx
import { getDefaultConfig, TomoEVMKitProvider } from '@tomo-inc/tomo-evm-kit';
import { WagmiProvider } from 'wagmi';
import { mainnet, polygon, optimism, arbitrum, base } from 'wagmi/chains';
import { QueryClientProvider, QueryClient } from '@tanstack/react-query';

const config = getDefaultConfig({
  clientId: 'XXXXXXXXXXXXXXXXXXXXXXX', // Replace with your clientId
  appName: 'My TomoEVMKit App',
  projectId: 'YOUR_PROJECT_ID', // Note: Every dApp that relies on WalletConnect now needs to obtain a projectId from WalletConnect Cloud.
  chains: [mainnet, polygon, optimism, arbitrum, base],
  ssr: true, // If your dApp uses server-side rendering (SSR)
});

const queryClient = new QueryClient();

const App = () => {
  return (
    <WagmiProvider config={config}>
      <QueryClientProvider client={queryClient}>
        <TomoEVMKitProvider>
          {/* Your App */}
        </TomoEVMKitProvider>
      </QueryClientProvider>
    </WagmiProvider>
  );
};

export default App;
```

**TomoEVMKit** integrates multiple wallets, including MetaMask, WalletConnect, and more. Add wallets during configuration using the following example:

```tsx
import { metaMaskWallet, rainbowWallet, walletConnectWallet } from '@tomo-inc/tomo-evm-kit/wallets';

const config = getDefaultConfig({
  clientId: 'XXXXXXXXXXXXXXXXXXXXXXX', // Replace with your clientId
  appName: 'My TomoEVMKit App',
  projectId: 'YOUR_PROJECT_ID', // Note: Every dApp relying on WalletConnect needs a projectId from WalletConnect Cloud.
  // Additional configuration options can be added here
  wallets: [
    {
      groupName: 'Popular',
      wallets: [
        metaMaskWallet, 
        rainbowWallet, 
        walletConnectWallet, // Add other wallets if needed
      ],
    },
  ],
});

export default config;
```

### Displaying the Modal

To display the modal for wallet connection, you can use the hooks provided by **TomoEVMKit**. These hooks are based on RainbowKit’s modal system.

#### Example Code:

```tsx
import { useConnectModal } from '@tomo-inc/tomo-evm-kit';

const ConnectButton = () => {
  const { openConnectModal } = useConnectModal();

  return (
    <button onClick={openConnectModal}>
      Connect Wallet
    </button>
  );
};

export default ConnectButton;
```

### Customize Theme

Same as RainbowKit: <https://www.rainbowkit.com/docs/theming#customizing-the-built-in-themes>.

```tsx
const App = () => {
  return (
    <TomoEVMKitProvider
      theme={darkTheme({
        accentColor: "blue",
        accentColorForeground: "white",
      })}
      {...etc}
    >
      {/* Your App */}
    </TomoEVMKitProvider>
  );
};
```

If you want to put the wallet list before social login, you can set the property `socailsFirst` to false.

<figure><img src="/files/ntosRIByXb178RZOLJmf" alt="" width="375"><figcaption></figcaption></figure>

### Additional Reference

For more advanced usage, refer to the [RainbowKit Documentation](https://www.rainbowkit.com/docs/modal-hooks). The behavior and integration are similar, making it easy to adapt.

#### FAQ

1. How to use with Next.js?

```typescript
/** @type {import('next').NextConfig} */
module.exports = {
  ...
  transpilePackages: ['@tomo-inc/tomo-evm-kit', '@tomo-wallet/uikit-lite', '@tomo-inc/shared-type'],
  ...
}
```

Additionally, manually install `core-js-pure`.

2. How to add chains?

For security reasons, Tomo must manually whitelist any new mainnet. You can send us a request, and we will schedule it according to your launch time. Before formally supporting the mainnet, you can use a customized chain to integrate the testnet and continue your development with extension wallets.


# Use with Ethers.js

For more wallet support, please refer to the Web3-Onboard documentation at [https://onboard.blocknative.com/docs](<https://onboard.blocknative.com/docs >).

```typescript
import { ethers } from 'ethers'; // "ethers": "^6.13.5",
import { Onboard } from "@tomo-inc/tomo-evm-kit";

import injectedModule from '@web3-onboard/injected-wallets';

const injected = injectedModule();

const chains = [{
    id: 1,
    token: "ETH",
    label: "Ethereum Mainnet",
    rpcUrl: `https://rpc.flashbots.net`,
  },
  ...
];

const appMetadata = {
  name: "Web3-Onboard Vanilla JS Demo",
};

const onboard = await Onboard({
  wallets: [injected],
  chains,
  appMetadata,
  theme: 'default' | 'dark' | 'light' | 'system'，
  clientId: "..", // client id from tomo
  projectId: ".." // project id for wallet connect
});

const wallets = await onboard.connectWallet();
const currentWallet = wallets[0];
const walletProvider = wallet.provider;
const provider = new ethers.BrowserProvider(walletProvider);
provider.send('personal_sign', ["0x313233", fromAccount]);

```


# Migration from RainbowKit

{% stepper %}
{% step %}
Update imports

{% code title="" %}

```tsx
// Old
import '@rainbow-me/rainbowkit/styles.css';
import { RainbowKitProvider } from '@rainbow-me/rainbowkit';

import { metaMaskWallet, walletConnectWallet, coinbaseWallet } from '@rainbow-me/rainbowkit/wallets';


// New
import '@tomo-inc/tomo-evm-kit/styles.css';
import { TomoEVMKitProvider } from '@tomo-inc/tomo-evm-kit';

import { metaMaskWallet, walletConnectWallet, coinbaseWallet } from '@tomo-inc/tomo-evm-kit/wallets';
```

{% endcode %}
{% endstep %}

{% step %}
Add `clientId` to config

```tsx
const config = getDefaultConfig({
  appName: 'My TomoEVMKit App',
  …
  // New
  clientId: 'XXXXXXXXXXXXXXXXXXXXXXX', // Replace with your clientId
});
```

{% endstep %}

{% step %}
Replace **RainbowKitProvider** with **TomoEVMKitProvider**

```tsx
// Old
<RainbowKitProvider>
  {/* Your App */}
</RainbowKitProvider>

// New
<TomoEVMKitProvider>
  {/* Your App */}
</TomoEVMKitProvider>
```

{% endstep %}
{% endstepper %}


# Migration from Blocknative

**TomoEVMKit** provides an API interface for projects based on `@web3-onboard` to migrate with minimum efforts.

## Update Initiate

To initiate the onboard in **TomoEVMKit**, you need to add the `await` keyword.

```typescript
// Old
import Onboard from '@web3-onboard/core'
// New
import { Onboard } from "@tomo-inc/tomo-evm-kit";

// Old
onboard = Onboard({
  wallets,
  chains,
  appMetadata,
  …
});

// New
onboard = await Onboard({
  wallets,
  chains,
  clientId: "..", // client id from tomo
  projectId: "..", // project id for wallet connect
  …
});
```

You can get `clientId` from the Tomo [dashboard ](https://dashboard.tomo.inc/)and `projectId` from the Walletconnect [dashboard](https://cloud.reown.com/sign-in). \
Done!

## Different API logics

Due to the different logic of implementation of  **TomoEVMKit** and **Blocknative**, we do not support all options in `onboard`now, below are lists:

### **InitOptions**

✅ Fully Support, ⚠️ Partial Support, ✖️ Not Support,

<pre class="language-typescript"><code class="lang-typescript"><strong>export interface InitOptions {
</strong>    /**
     * Wallet modules to be initialized and added to wallet selection modal
     */
<strong>    wallets: WalletInit[]; //  ✅
</strong>    /**
     * The chains that your app works with
     */
<strong>    chains: (Chain | ChainWithDecimalId)[]; //  ✅
</strong>    /**
     * Additional metadata about your app to be displayed in the Onboard UI
     */
<strong>    appMetadata?: AppMetadata; //  ✅
</strong>    /**
     * Define custom copy for the 'en' locale or add locales to i18n your app
     */
<strong>    i18n?: i18nOptions; // ✖️
</strong>    /**
     * Customize the connect modal
     */
<strong>    connect?: ConnectModalOptions; // ⚠️ only support `autoConnectLastWallet`
</strong>    /**
     * Customize the account center UI
     */
<strong>    accountCenter?: AccountCenterOptions; // ✖️
</strong>    /**
     * @deprecated apiKey parameter has been deprecated and is no
     * longer used within Web3-Onboard to provide notifications
     */
    apiKey?: string; // ✖️ 
    /**
     * Transaction notification options
     */
<strong>    notify?: Partial&#x3C;NotifyOptions> | Partial&#x3C;Notify>; // ✖️ 
</strong>    /** Gas module */
    gas?: typeof gas; // ✖️
    /** Web3-Onboard module to add Wagmi support
     * see https://www.npmjs.com/package/@web3-onboard/wagmi
     */
    wagmi?: typeof wagmi; // ✖️ 
    /**
     * Object mapping for W3O components with the key being the DOM
     * element to mount the component to, this defines the DOM container
     *  element for svelte to attach the component
     */
<strong>    containerElements?: Partial&#x3C;ContainerElements>; // ✖️ 
</strong>    /**
     * @deprecated Transaction Preview support has ended and Transaction Preview
     * is no longer supported as part of Web3-Onboard.
     * Please remove from your onboard config to avoid
     * console errors and un-expected behavior
     */
    transactionPreview?: unknown; // ✖️
    /**
     * Custom or predefined theme for Web3Onboard
     * BuiltInThemes: ['default', 'dark', 'light', 'system']
     * or customize with a ThemingMap object.
     */
<strong>    theme?: Theme; //  ✅
</strong>    /**
     * Defaults to False - use to reduce load time
     * If set to true the Inter font will not be imported and
     * instead the default 'sans-serif' font will be used
     * To define the font used see `--w3o-font-family` prop within
     * the Theme initialization object or set as css variable
     */
    disableFontDownload?: boolean; // ✖️
    /**
     * Type of unstoppableResolution module
     * A small module that can bee added to allow Unstoppable Domain
     * address resolution similar to that of ens (Ethereum Name Service)
     * ENS resolution will take president if available
     */
    unstoppableResolution?: typeof unstoppableResolution; // ✖️
}
</code></pre>

### onboard API

```typescript
declare const OnboardAPI: {
  connectWallet: typeof connectWallet; // ✅
  disconnectWallet: typeof disconnectWallet; // ✅
  setChain: typeof setChain; // ✅
  
  state: {
    // ⚠️ only support state.select('wallet').subscribe for autoconnect
    // The remaining properties will not respond.
    get: () => AppState;
    select: {
      (): Observable<AppState>;
      <T extends keyof AppState>(stateKey: T): Observable<AppState[T]>;
    };
    
    actions: {
      setWalletModules: typeof setWalletModules; // ✖️
      setLocale: typeof setLocale; // ✖️
      updateNotify: typeof updateNotify; // ✖️
      customNotification: typeof customNotification; // ✖️
      updateBalances: typeof updateBalances; // ✖️
      updateAccountCenter: typeof updateAccountCenter; // ✖️
      setPrimaryWallet: typeof setPrimaryWallet; // ✖️
      updateTheme: typeof updateTheme; // ✅
      updateAppMetadata: typeof updateAppMetadata; // ✖️
    };
  };
};
```

### onboard.connectWallet&#x20;

Currently, if you call `connectWallet` it only supports no parameter input way and will return a connected status window.

```typescript
// ⚠️ no input parameters
declare function connectWallet(): Promise<WalletState[]>;

// ✖️
export interface ConnectOptions {
  autoSelect?: {
    label: string;
    disableModals: boolean;
  };
}

// ✖️
export interface ConnectOptionsString {
  autoSelect?: string;
}
```

### connect configuration

We only support the automatical reconnect mode &#x20;

<pre class="language-javascript"><code class="lang-javascript"><strong>onboard = Onboard({
</strong>    ...
    connect: {
      autoConnectLastWallet: true // need explicitly set to true
    }
})

<strong>onboard.state.select("wallets").subscribe((wallets) => { // you can subscribe the connection
</strong>  if (wallets.length > 0) {
<strong>    console.log("Wallet is connected");
</strong><strong>    console.log('provider',wallets[0].provider) // only one provider provided.
</strong>  } else {
<strong>    console.log("Wallet is disconnected");
</strong>  }
});
</code></pre>

## Unsupported Wallets

| Wallets                             | Support |
| ----------------------------------- | ------- |
| *@web3-onboard/arcana-auth*         | ❌       |
| *@web3-onboard/bloom*               | ❌       |
| *@web3-onboard/capsule*             | ❌       |
| *@web3-onboard/cede-store*          | ❌       |
| *@web3-onboard/dcent*               | ❌       |
| *@web3-onboard/finoaconnect*        | ❌       |
| *@web3-onboard/fortmatic*           | ❌       |
| *@web3-onboard/keepkey*             | ❌       |
| *@web3-onboard/magic*               | ❌       |
| *@web3-onboard/particle-network*    | ❌       |
| *@web3-onboard/passport*            | ❌       |
| *@web3-onboard/portis*              | ❌       |
| *@web3-onboard/taho*                | ❌       |
| *@web3-onboard/tallyho*             | ❌       |
| *@web3-onboard/transaction-preview* | ❌       |
| *@web3-onboard/trezor*              | ❌       |
| *@web3-onboard/venly*               | ❌       |
| *@web3-onboard/web3auth*            | ❌       |


# Internal Wallet Services

Tomo provides a few internal wallet services to wallet users so developers can selectively embed these services into their applications with minimum effort. <mark style="color:red;">**Currently, these features are only available for users using social login, and users can only operate through a pop-up Tomo UI component.**</mark> We will add support for extension wallet users and provide more configurable ways to invoke these services.

### Service Types

Tomo supports the following basic service types:

```tsx
enum WebWalletInvokeType {
  SWAP = "swap",             // Swap between selected token pairs
  ONRAMP = "onramp",         // Purchase Token by card
  SEND = "send",             // Send token to a given address
  RECEIVE = "receive",       // Display QR code and address for given token
}
```

#### Modals for Internal Services

<img src="/files/43k6AFoXtz1TYLXel4Bz" alt="Modals for Onramp Services" class="gitbook-drawing">

<img src="/files/1CbAgEXwtEEHDa8XYvn6" alt="Modals for Swap Services" class="gitbook-drawing">

### Invoke Services

```tsx
import { TomoEVMKitProvider, WebWalletInvokeType} from "@tomo-inc/tomo-evm-kit";

const handleAction = async (type: WebWalletInvokeType) => {
     // Take SDK from the provider core
    const provider = (await connector?.getProvider());
    const tomoSDK = provider?.core;
    try {
      tomoSDK?.handleWebWalletInvoke(type);
    } catch (e) {
      console.log("handleAction error:", e);
    }
  };

//your app logic
...
<button onClick={() => handleAction(WebWalletInvokeType.SWAP)}>
        Swap
      </button>
```

#### Example

```tsx

import { getDefaultConfig, TomoEVMKitProvider, useConnectModal, useAccountModal, useWalletConnectors, WebWalletInvokeType } from "@tomo-inc/tomo-evm-kit";
import { WagmiProvider, useAccount } from "wagmi";
import { mainnet, polygon, optimism, arbitrum, base } from "wagmi/chains";
import { QueryClientProvider, QueryClient } from "@tanstack/react-query";

const ConnectButton = () => {
  const { openConnectModal } = useConnectModal();

  return (
    <button onClick={openConnectModal}>
      Connect Wallet
    </button>
  );
};

const OrderComponent = () => {

  const { connector } = useAccount();

  const handleAction = async (type: WebWalletInvokeType) => {
     // get sdk instance
    const provider = (await connector?.getProvider());
    const tomoSDK = provider?.core;
    try {
      tomoSDK?.handleWebWalletInvoke(type);
    } catch (e) {
      console.log("handleAction error:", e);
    }
  };

  return (
    <div style={{ display: 'flex', flexDirection: 'column', gap: '10px' }}>
      <h1>EVMKit Demo</h1>
      <button onClick={() => handleAction(WebWalletInvokeType.ONRAMP)}>
        Onramp
      </button>
      <button onClick={() => handleAction(WebWalletInvokeType.SWAP)}>
        Swap
      </button>
      <button onClick={() => handleAction(WebWalletInvokeType.SEND)}>
        Send
      </button>
      <button onClick={() => handleAction(WebWalletInvokeType.RECEIVE)}>
        Receive
      </button>
    </div>
  );
};

export default function EVMKitPage() {
  const config = getDefaultConfig({
    clientId:
      "YOUR_CLIENT_ID", // Replace with your clientId
    appName: "My TomoEVMKit App",
    projectId: "YOUR_PROJECT_ID", // Note: Every dApp that relies on WalletConnect now needs to obtain a projectId from WalletConnect Cloud.
    chains: [mainnet, polygon, optimism, arbitrum, base],
    ssr: true, // If your dApp uses server-side rendering (SSR)
  });

  const queryClient = new QueryClient();

  return (
    <WagmiProvider config={config}>
      <QueryClientProvider client={queryClient}>
        <TomoEVMKitProvider>
          <ConnectButton />
          <OrderComponent />
        </TomoEVMKitProvider>
      </QueryClientProvider>
    </WagmiProvider>
  );
}
```


# Supported Chains

More chain will be listed, contact us if you want a specific chain in your project

The Following Mainnets are supported natively in the EVM kit

* Ethereum
* BNB Chain
* AILayer
* Arbitrum One
* Avalanche
* B3
* Base
* Bitlayer
* Blast
* DuckChain&#x20;
* Gravity
* Merlin
* Neo x
* Optimism
* Polygon
* Scroll
* Worldchain
* opBNB
* zkSync Era
* Corn
* Berachain
* Mantle
* X Layer
* Polygon zkEVM

We also support the following testnets:

* Duckchain
* Botanix
* Story Odyssey
* Story Aeneid
* Berachain bArtio
* Monad
* Neura

We also support testing using a customized chain and extension wallet.


# For Telegram (Coming soon)


# Tomo Web SDK

**Tomo Web SDK** provides a seamless Web3 onboarding experience by integrating social login options (Google, Telegram, Twitter, KakaoTalk, email) and supporting major wallets like Phantom and OKX Wallet. With compatibility across a broad range of blockchains, including EVM, Solana, Tron, and Sui, users can effortlessly access their wallets.

For developers, the SDK simplifies wallet interactions and blockchain requests, enabling efficient and secure integration for both users and decentralized applications.

<figure><img src="/files/1HK7Ekug11uf8fFy0PDf" alt=""><figcaption></figcaption></figure>


# Quick Start

To use Tomo Web SDK, you need to install the following:

```bash
npm install @tomo-inc/tomo-web-sdk
```

or

```bash
pnpm i @tomo-inc/tomo-web-sdk
```

### Prepare the Client ID

1. [Talk to us](https://docs.google.com/forms/d/e/1FAIpQLSfqMQH80c9Py0V1rNDgfXqL8kNXKn66WMCgtczNLriruJicjw/viewform) to create an developer account.
2. Log in to the [Tomo Developer Dashboard](https://dashboard.tomo.inc/).
3. Create a new project and copy the generated `clientId`.
4. Use this `clientId` in your `TomoContextProvider`.

<figure><img src="/files/TbphoXs8zd8GPWZbkz12" alt=""><figcaption><p>Tomo's Developer Dashboard</p></figcaption></figure>

### Initialize Tomo Web SDK

Set up  `TomoContextProvider` using the `clientId` from the first step. For react framework:

{% code overflow="wrap" %}

```tsx
import { TomoContextProvider } from '@tomo-inc/tomo-web-sdk';

<TomoContextProvider
  theme="light"
  chainTypes={['solana','tron','movement']}
  clientId="your client Id"
>
  <YourApp />
</TomoContextProvider>
```

{% endcode %}

For pure Javascript project:

<pre class="language-javascript"><code class="lang-javascript">import { initTomoModal } from '@tomo-inc/tomo-web-sdk';
import '@tomo-inc/tomo-web-sdk/style.css'

initTomoModal({
  theme: "light",
  clientId: "your client Id",
  chainTypes: ['solana'],
<strong>  onConnect: (walletState) => {
</strong>    console.log('onConnect', walletState)
  },
})
</code></pre>

#### Use Tomo

We expose the wallet state and functions through `useTomo()` method

```tsx
function useTomo() {
  const tomoModal = useAtomValue(tomoModalAtom)
  const tomoModalControl = useTomoModalControl()
  const tomoWalletState = useTomoWalletState()
  const tomoClientMap = useTomoClientMap()
  const tomoWalletConnect = useTomoWalletConnect()

  return {
    opened: tomoModal.open,
    openConnectModal: tomoModalControl.open,
    closeConnectModal: tomoModalControl.close,
    connected: tomoWalletState.isConnection,
    disconnect: tomoWalletConnect.disconnect,
    solanaAddress: tomoWalletState.solanaAddress,
    providers: {
      solanaProvider: tomoClientMap.solanaProvider
    }
  }
}
```

To connect a wallet, call `openConnectModal` to display the modal.

```tsx
// react
const { openConnectModal } = useTomo();
openConnectModal();

// pure js
window.openTomoConnectModal?.()
```

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

Checking connection status:

```tsx
import { getWalletState } from '@tomo-inc/tomo-web-sdk';

// react
const { connected } = useTomo();

// pure js or react
const walletState = getWalletState()
const connected = walletState.isConnected
```

Disconnect the wallet:

```typescript
// react
const { disconnect } = useTomo();
disconnect()

// pure js
window.tomo_sol?.disconnect
```

### Demo

We provide a demo application to show the functionalities and UI components:

<https://socialwallet-react-demo.tomo.inc/>\\

### FAQ

1. How to use with Next.js?

```typescript
/** @type {import('next').NextConfig} */
module.exports = {
  ...
  transpilePackages: ['@tomo-inc/tomo-web-sdk', '@tomo-wallet/uikit', '@tomo-inc/shared-type'],
  ...
}
```

Additionally, manually install `core-js-pure`.


# Solana Provider

After setting up your wallet, you can have access to the Solana provider:

```javascript
// react
const { providers } = useTomo()
const { solanaProvider } = providers;

// pure js
const solanaProvider = window.tomo_sol
```

### Get Solana Address

&#x20;the Solana address from the wallet state or provider. In React framework:

```tsx
// get address from wallet state
const { walletState } = useTomo()
const solanaAddress = walletState.solanaAddress

// or get address from provider
const { providers } = useTomo()
const solanaAddress = await providers.solanaProvider.getAddress()
```

Or Pure JS:

<pre class="language-javascript"><code class="lang-javascript"><strong>/** pure js */
</strong>import { getWalletState } from '@tomo-inc/tomo-web-sdk';
// get from wallet state
const walletState = getWalletState()
const solanaAddress = walletState.solanaAddress

// or get from provider
const solanaAddress = await window.tomo_sol.getAddress()
</code></pre>

## Provider Functions

`providers.solanaProvider` exposes three functions for sending requests to the user's wallet:

### **Signing a Message**

It uses the Solana provider to sign a plain text offchain message, which returns the signature of the given message with the message header.

{% code overflow="wrap" %}

```tsx
import bs58 from 'bs58'

// interface
signMessage(message: Uint8Array): Promise<Uint8Array>;

// example
const res = await solanaProvider.signMessage(new TextEncoder().encode('hello world'))
console.log('res:', bs58.encode(res))
// res:6EpGiRj6UMPWKZSNQoPsrpDxN9Mw25PmAtrWkD2V6wLZ5HLePPcwJV9DB3aCCeD2eEfW56NzuEkfXJHu2rgwhL7wweJeKJwrU7CoTvndykUPGkaM1mJb7N25NeyeUq7NBEFCNVt3LWPvDvVBmUMU88Vo6jTTjC4jPYnVsfZDrodsEx9
```

{% endcode %}

### **Sign Transaction**

Given a transaction in the format of `Transaction` from `@solana/web3.js`  you can use `signTransaction`method to get the signed transaction in hex value if the user approves the request.

{% code overflow="wrap" %}

```tsx
// interface
signTransaction<T extends Transaction>(transaction: T): Promise<Transaction>;

// example, see next session for definition of createSolTx
const transaction = await createSolTx(from, to, amount);
const res = await solanaProvider.signTransaction(transaction)
```

{% endcode %}

### **Send Transaction**

You can also send the transaction directly through this `sendTransaction` method. The return value is the transaction signature if signed and sent correctly.

{% code overflow="wrap" %}

```tsx
// interface
type TransactionSignature = string;
sendTransaction<T extends Transaction>(transaction: T, connection?: Connection): Promise<TransactionSignature>;


// example, see next session for definition of createSolTx
const connection = getConnection()
const transaction = await createSolTx(from, to, amount, mintAddress)
const signature = await solanaProvider.sendTransaction(transaction, connection)
```

{% endcode %}

## **Example**

We provide an [example](https://socialwallet-react-prod.tomo.inc/solana) as follows:

### React

{% code overflow="wrap" %}

```tsx
import {
  Connection,
  PublicKey,
  SystemProgram,
  Transaction
} from '@solana/web3.js'

import {
  createAssociatedTokenAccountInstruction,
  createTransferInstruction,
  getAccount,
  getAssociatedTokenAddress,
  TOKEN_PROGRAM_ID,
  TokenAccountNotFoundError,
  TokenInvalidAccountOwnerError
} from '@solana/spl-token'
import BigNumber from 'bignumber.js'
import { TomoContextProvider, useTomo } from '@tomo-inc/tomo-web-sdk'
import '@tomo-inc/tomo-web-sdk/style.css'

const solEndpoint = 'Your rpc endpoint'
const CLIENT_ID = 'Your client id'

// Get Sol Connection
function getConnection() {
  const connection = new Connection(solEndpoint, 'recent')
  return connection
}

// Get Sol Connection
let connection: Connection
function getConnection() {
  if (!connection) {
    connection = new Connection(solEndpoint, 'recent')
  }
  return connection
}

// create transaction
async function createSolTx(
  fromAddress: string,
  toAddress: string,
  amount: number,
  mintAddress?: string
) {
  try {
    const connection = getConnection()
    const tx = new Transaction()
    const fromPublicKey = new PublicKey(fromAddress)
    const toPublicKey = new PublicKey(toAddress)

    if (!tx.feePayer) {
      tx.feePayer = fromPublicKey
    }

    if (mintAddress) {
      const tokenPublicKey = new PublicKey(mintAddress)
      const fromTokenPubKey = await getAssociatedTokenAddress(
        tokenPublicKey,
        new PublicKey(fromAddress)
      )
      const toTokenPubKey = await getAssociatedTokenAddress(
        tokenPublicKey,
        new PublicKey(toAddress)
      )

      tx.recentBlockhash = (await connection.getLatestBlockhash()).blockhash

      let account: any
      try {
        account = await getAccount(connection, toTokenPubKey)
      } catch (error: unknown) {
        if (
          error instanceof TokenAccountNotFoundError ||
          error instanceof TokenInvalidAccountOwnerError
        ) {
          try {
            tx.add(
              createAssociatedTokenAccountInstruction(
                fromPublicKey,
                toTokenPubKey,
                toPublicKey,
                tokenPublicKey
              )
            )
          } catch (error: unknown) {}
        } else {
          throw error
        }
      }
      console.log('account', account)

      tx.add(
        createTransferInstruction(
          fromTokenPubKey,
          toTokenPubKey,
          fromPublicKey,
          amount,
          [],
          TOKEN_PROGRAM_ID
        )
      )
    } else {
      tx.recentBlockhash = (await connection.getLatestBlockhash()).blockhash
      tx.add(
        SystemProgram.transfer({
          fromPubkey: fromPublicKey,
          toPubkey: toPublicKey,
          lamports: amount
        })
      )
    }
    return tx
  } catch (e) {
    return null
  }
}

enum Theme {
  Light = 'light',
  Dark = 'dark'
}

export default function SOLDemo() {
  return (
    <TomoContextProvider
      theme={Theme.Light}
      chainTypes={['solana']}
      clientId={CLIENT_ID}
    >
      <App />
    </TomoContextProvider>
  )
}
function App() {
  const { providers, walletState, openConnectModal } = useTomo()
  const { solanaProvider } = providers

  return (
    <div style={{ display: 'flex', gap: '10px' }}>
      <button onClick={openConnectModal}>openConnectModal</button>
      <br />
      <button
        onClick={async () => {
          const from = walletState.solanaAddress || ''
          const to = 'xxx'
          const decimals = 9
          const amount = Number(new BigNumber(0.00001).shiftedBy(decimals))
          const transaction = await createSolTx(from, to, amount)

          if (!transaction) throw new Error('Failed to create transaction')

          const res = await solanaProvider.signTransaction(transaction)
          console.log('sign transaction res:', res)

          // continue to send transaction
          // const tx = await solanaProvider.sendTransaction(res)
          // console.log('send transaction res:', tx)
        }}
      >
        sign sol transaction
      </button>
      <br />
      <button
        onClick={async () => {
          const from = walletState.solanaAddress || ''
          const to = 'xxxx'
          const usdtMintAddress = 'Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB'
          const decimals = 6
          const amount = Number(new BigNumber(0.00001).shiftedBy(decimals))
          const transaction = await createSolTx(from, to, amount, usdtMintAddress)
          if (!transaction) throw new Error('Failed to create transaction')

          const connection = getConnection()
          const res = await solanaProvider.sendTransaction(transaction, connection)
          console.log('send token transaction res:', res)
        }}
      >
        send spl token transaction
      </button>
    </div>
  )
}
```

{% endcode %}

### Pure JavaScript

```javascript
import {
  Connection,
  PublicKey,
  SystemProgram,
  Transaction
} from '@solana/web3.js'

import {
  createAssociatedTokenAccountInstruction,
  createTransferInstruction,
  getAccount,
  getAssociatedTokenAddress,
  TOKEN_PROGRAM_ID,
  TokenAccountNotFoundError,
  TokenInvalidAccountOwnerError
} from '@solana/spl-token'
import BigNumber from 'bignumber.js'
import { CLIENT_ID } from 'constant'
import { initTomoModal } from '@tomo-inc/tomo-web-sdk'
import '@tomo-inc/tomo-web-sdk/style.css'

const solEndpoint = 'Your rpc endpoint'
const CLIENT_ID = 'Your client id'

// Get Sol Connection
function getConnection() {
  const connection = new Connection(solEndpoint, 'recent')
  return connection
}

// Get Sol Connection
let connection: Connection
function getConnection() {
  if (!connection) {
    connection = new Connection(solEndpoint, 'recent')
  }
  return connection
}


// create transaction
async function createSolTx(
  fromAddress: string,
  toAddress: string,
  amount: number,
  mintAddress?: string
) {
  // ...
}

enum Theme {
  Light = 'light',
  Dark = 'dark'
}
initTomoModal({
  onConnect: (param) => {
    console.log('onConnect', param)
  },
  theme: Theme.Light,
  clientId: CLIENT_ID,
  chainTypes: ['solana']
})
export default function SOLPureDemo() {
  return (
    <div style={{ display: 'flex', gap: '10px' }}>
      <button
        onClick={() => {
          window.openTomoConnectModal?.()
        }}
      >
        openTomoConnectModal
      </button>

      <button
        onClick={async () => {
          const solanaProvider = window.tomo_sol
          if (!solanaProvider) return
          const solanaAddress = await solanaProvider?.getAddress()
          const from = solanaAddress || ''
          const to = 'xxxx'
          const decimals = 9
          const amount = Number(new BigNumber(0.000001).shiftedBy(decimals))
          const transaction = await createSolTx(from, to, amount)

          if (!transaction) throw new Error('Failed to create transaction')

          const res = await solanaProvider.signTransaction(transaction)
          console.log('sign transaction res:', res)
        }}
      >
        sign sol transaction
      </button>

      <button
        onClick={async () => {
          const solanaProvider = window.tomo_sol
          if (!solanaProvider) return
          const solanaAddress = await solanaProvider?.getAddress()
          const from = solanaAddress || ''
          const to = 'xxxx'
          const usdtMintAddress = 'Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB'
          const decimals = 6
          const amount = Number(new BigNumber(0.000001).shiftedBy(decimals))
          const transaction = await createSolTx(from, to, amount, usdtMintAddress)
          if (!transaction) throw new Error('Failed to create transaction')

          const connection = getConnection()
          const res = await solanaProvider.sendTransaction(transaction, connection)
          console.log('send token transaction res:', res)
        }}
      >
        send spl token transaction
      </button>
    </div>
  )
}

```


# EVM Provider

After setting up your wallet, you can access the EVM provider:

```javascript
import { useTomo, getWalletState } from '@tomo-inc/tomo-web-sdk';
// react
const { providers } = useTomo()
const { ethereumProvider } = providers;

// pure js
const ethereumProvider = window.tomo_ethereum
```

### Switch Chain ID

You can switch chains between different EVM networks (see [Supported Chains](/tomo-sdk/tomoevmkit/supported-chains) for the enabled network list). By default, you use the Ethereum mainnet.

```tsx
//interface
switchChain(chainId: string): Promise<void>

getChainId(): number | string


const chainId = '1'
// react
const current = await ethereumProvider.getChainId();
const res = await ethereumProvider.switchChain(chainId);

// pure js
const current = await window.tomo_ethereum.getChainId();
const res = await window.tomo_ethereum.switchChain(chainId);
```

### Get the EVM address

&#x20;The EVM address from the wallet state or provider.

```tsx
import { useTomo, getWalletState } from '@tomo-inc/tomo-web-sdk';
const { walletState, providers } = useTomo()

// get from wallet state
const address = walletState.address

// or get from provider
const address = await providers.ethereumProvider.request({ method: "eth_accounts" })?.[0]

/** pure js */
// get from wallet state
const address = getWalletState().address

// or get from provider
const address = await window.tomo_ethereum.request({ method: "eth_accounts" })?.[0]
```

## Provider Functions

`providers.ethereumProvider` exposes three functions for sending requests to the user's wallet:

### **Signing a Message**

It uses the Ethereum provider to sign a plaintext offchain message, which returns the message's signature with the message header. We also provide a shortcut for sign type data where the `msg` is a json string of the data.

{% code overflow="wrap" %}

```tsx
// interface
signMessage(msg: string, address:string): Promise<string>
signTypedData(address: string, msg: string): Promise<string>

 // react
 const personalSignResult = await ethereumProvider.request(msg, address);
 
 // pure js
 const personalSignResult = await window.tomo_ethereum.request(msg, address);
```

{% endcode %}

### **Send Transaction**

You can also send the transaction directly through this `sendTransaction` method. The return value is the transaction signature if signed and sent correctly.

<pre class="language-tsx" data-overflow="wrap"><code class="lang-tsx">// interface
sendTransaction(params: EvmTxParams): Promise&#x3C;any>
<strong>
</strong>interface EvmTxParams {
  from: string;
  to: string;
  value: string;
  gasPrice?: string;
  gasLimit?: string;
  maxFeePerGas?: string;
  maxPriorityFeePerGas?: string;
  data?: string;
}

<strong>const Tx= {
</strong>    from: address,
    to: address,
    value: "0x5af3107a4000",
    nonce: "0x0",
  },
// react
const res = await ethereumProvider.sendTransaction(Tx);

// pure js
const res = await window.tomo_ethereum.sendTransaction(Tx);
</code></pre>

### Requests

We also support the [standard ](https://ethereum.github.io/execution-apis/api-documentation/)wallet JSON RPC API for wallet actions

```tsx
//interface
request<Result = any, Params = any>(request: RequestArguments<Params>, context?: any): Promise<Result>


interface RequestArguments<T = any> {
    method: string;
    params?: T;
    id?: number;
}

const walletActions = {
  eth_requestAccounts: "eth_requestAccounts",
  eth_accounts: "eth_accounts",
  wallet_watchAsset: "wallet_watchAsset",
  eth_addEthereumChain: "eth_addEthereumChain",
  eth_switchEthereumChain: "eth_switchEthereumChain",
  wallet_switchEthereumChain: "wallet_switchEthereumChain",
  personal_sign: "personal_sign",
  eth_signTypedData_v4: "eth_signTypedData_v4",
  wallet_getPermissions: "wallet_getPermissions",
  wallet_requestPermissions: "wallet_requestPermissions",
  eth_sendTransaction: "eth_sendTransaction",
  eth_sendRawTransaction: "eth_sendRawTransaction",
  personal_ecRecover: "personal_ecRecover",
  eth_swapTransaction: "eth_swapTransaction",
  eth_approveTransaction: "eth_approveTransaction",
  eth_chainId: "eth_chainId",
};


const data = {
  method: "eth_sendTransaction",
  params: [
    {
      from: address,
      to: address,
      value: "0x5af3107a4000",
      nonce: "0x0",
    },
  ],
}
// react
const res = await ethereumProvider.request(data);

// pure js
const res = await window.tomo_ethereum.request(data);
```


# Bitcoin Provider

After setting up your wallet, you can have access to the Bitcoin provider:

```javascript
// react
const { providers } = useTomo()
const { bitcoinProvider } = providers;

// pure js
const bitcoinProvider = window.tomo_bitcoin
```

### Get Address and Balance

You can first check and change the address type you want to use

```tsx
// interface
getAddressType(): string
changeAddressType(addressType: string): Promise<void>

export enum AddressType {
  P2PKH,
  P2WPKH,
  P2TR,
  P2SH_P2WPKH,
}

// react
const btcAddressType= await bitcoinProvider.getAddressType()
await bitcoinProvider.changeAddressType("P2SH_P2WPKH")

// pure js
const btcAddress = await window.tomo_bitcoin.getAddressType()
await window.tomo_bitcoin.changeAddressType("P2PKH")
```

Then, get the address. However, if the user uses extension wallet, not all address type may have value.

<pre class="language-tsx"><code class="lang-tsx">// interface
// get current type address, by default it is taproot
getAddress(): Promise&#x3C;string>
getAllAddresses(): Promise&#x3C;AddressInfo[]>
getBalance(address?: string): Promise&#x3C;number>

interface AddressInfo {
  value: AddressType;
  label: string;
  name: string;
  displayName?: string;
  hdPath: string;
  address?: string;
}

// form wallet state
const { walletState, providers } = useTomo()
const { btcAddress } = walletState

// or 
const { bitcoinProvider } = providers;
<strong>const btcAddress = await bitcoinProvider.getAddress()
</strong>const allAddresses= await bitcoinProvider.getAllAddresses()
const balance= await bitcoinProvider.getBalance(btcAddress)

// pure js
const btcAddress = await window.tomo_bitcoin.getAddress()
const allAddresses= await window.tomo_bitcoin.getAllAddresses()
const balance= await window.tomo_bitcoin.getBalance(btcAddress)
</code></pre>

### Get the public key

In addition to the address, you can get the concrete public key from the provider.

```tsx
//interface 
getPublicKey(): Promise<string>

//react
const publicKey = await bitcoinProvider.getPublicKey()

// pure js

const publicKey = await window.tomo_bitcoin.getPublicKey()
```

### Switch Network

We support three networks for different purposes:

```tsx
// interface
getNetwork()： string
switchNetwork(network: Network): Promise<void>
const network = 'signet' | 'testnet' | 'mainnet'

// react
const current = await bitcoinProvider.getNetwork()
const sendRes = await bitcoinProvider.switchNetwork(network)

// pure js
const current = await window.tomo_bitcoin.getNetwork()
const sendRes = await window.tomo_bitcoin.switchNetwork(network)
```

## Provider Functions

`providers.bitcoinProvider` exposes three functions for sending requests to the user's wallet:

### **Signing a Message**

It uses the `bitcoinprovider` to sign a plaintext offchain message, which returns the message's signature.

{% code overflow="wrap" %}

```tsx
// interface
signMessage(message: string, _type: "ecdsa" | "bip322-simple" = "ecdsa"): Promise<string>

const message = 'your message'
const type: "ecdsa" | "bip322-simple" = 'ecdsa'   // default is ecdsa
// react
const signedMessage = await bitcoinProvider.signMessage(message, type)

// pure js
const signedMessage = window.tomo_bitcoin.signMessage(message, type)
```

{% endcode %}

Currently, the `bip32-simple` type does not support taproot addresses. Please select other address types when you need to sign a message with `bip322-simple`.

### **Sign Psbt**

Given a hex raw transaction  you can use `signPsbt`method to get the signed transaction in hex value if the user approves the request.

{% code overflow="wrap" %}

```tsx
// interface
signPsbt(psbtHex: string): Promise<string>
signPsbts(psbtHexs: string[]): Promise<string[]>


const psbtHex = 'hex String'

// react
const signed = await bitcoinProvider.signPsbt(psbtHex)

// pure js
const signed = await window.tomo_bitcoin.signPsbt(psbtHex)
```

{% endcode %}

### **Send Bitcoin**

You can also send the transaction directly through this `sendBitcoin` method. The return value is the transaction signature if signed and sent correctly.

{% code overflow="wrap" %}

```tsx
const toAddress = 'toAddress'
const satAmount = 1 // BTC
const feeRate = 123 // sat/vB


// react
const sendRes = await bitcoinProvider.sendBitcoin(toAddress, satAmount, feeRate)

// pure js
const sendRes = await  window.tomo_bitcoin.sendBitcoin(toAddress, satAmount, feeRate)
```

{% endcode %}


# Tron Provider

After setting up your wallet, you can have access to the Tron provider:

```javascript
// react
const { providers } = useTomo()
const { tronProvider } = providers;

// pure js
const tronProvider = window.tomo_tron
```

### Get Tron Address

&#x20;the Tron address from the wallet state or provider. In React framework:

```tsx
// get address from wallet state
const { walletState } = useTomo()
const tronAddress = walletState.tronAddress

// or get address from provider
const { providers } = useTomo()
const tronAddress = await providers.tronProvider.getAddress()
```

Or Pure JS:

<pre class="language-javascript"><code class="lang-javascript"><strong>/** pure js */
</strong>import { getWalletState } from '@tomo-inc/tomo-web-sdk';
// get from wallet state
const walletState = getWalletState()
const tronAddress = walletState.tronAddress

// or get from provider
const tronAddress = await window.tomo_tron.getAddress()
</code></pre>

## Provider Functions

### **Signing a Message**

It uses the Tron provider to sign a plain text offchain message, which returns the signature of the given message.

<pre class="language-tsx" data-overflow="wrap"><code class="lang-tsx">// interface
signMessage(message: string, privateKey?: string): Promise&#x3C;string>;

<strong>// Social Wallet does not support signing messages currently, will support soon.
</strong>const signedMessage = await tronProvider.signMessage('hello world')
</code></pre>

### **Sign Transaction**

To sign a transaction, you need first initiate a client with`tronweb` for connecting to the network.&#x20;

```tsx
let tronWeb: TronWebType | null = null
export async function getTronWeb() {
  if (tronWeb) return tronWeb
  const {
    default: { TronWeb }
  } = await import('tronweb')
  tronWeb = new TronWeb({
    fullHost:
      'https://orbital-dimensional-season.tron-mainnet.quiknode.pro/d14878573fe23f8f40621a303ee2eaa3c812ba1c'
  })
  return tronWeb as TronWebType
}
```

Then, create the transaction and sign with our `tronProvider` . Eventually, you need to send the transaction again through the `tronWeb` client.

{% code overflow="wrap" %}

```tsx
// interface
import { SignedTransaction, Transaction } from 'tronweb/lib/esm/types'
signTransaction(transaction: Transaction): Promise<SignedTransaction>;

// example 1: send TRX
const unSignedTransaction = await tronWeb.transactionBuilder.sendTrx(to, amount, from);
const signedTransaction = await tronProvider.signTransaction(unSignedTransaction)
await tronWeb.trx.sendRawTransaction(signedTransaction);

// example 2: call smart contract
const transactionWrapper = await tronWeb.transactionBuilder.triggerSmartContract(contractAddress, functionSelector, triggerSmartContractOptions, contractFunctionParameter, issuerAddress)
const signedTransaction = await tronProvider.signTransaction(transactionWrapper.transaction)
await tronWeb.trx.sendRawTransaction(signedTransaction);
```

{% endcode %}

## **Example**

We provide an [example ](https://socialwallet-react-prod.tomo.inc/tron)of a tron provider as follows:

### React

<pre class="language-tsx" data-overflow="wrap"><code class="lang-tsx">import { parseUnits } from 'viem'
import type { TronWeb as TronWebType } from 'tronweb' // "^6.0.0"
import { TomoContextProvider, useTomo } from '@tomo-inc/tomo-web-sdk'

const CLIENT_ID = 'Your client id'

enum Theme {
  Light = 'light',
  Dark = 'dark'
}

export default function TronDemo() {
  return (
    &#x3C;TomoContextProvider
      theme={Theme.Light}
      chainTypes={['tron']}
      clientId={CLIENT_ID}
    >
      &#x3C;App />
    &#x3C;/TomoContextProvider>
  )
}

export function App() {
  const { providers, walletState, openConnectModal } = useTomo()
  const { tronProvider } = providers

  return (
    &#x3C;div style={{ display: 'flex', gap: '10px' }}>
      &#x3C;button
        onClick={() => {
          openConnectModal()
        }}
      >
        openConnectModal
      &#x3C;/button>

      &#x3C;button
        onClick={async () => {
          if (!tronProvider) throw new Error('tronProvider not found')

          const amount = '0.000001'
          const to = 'xxx'
          const from = walletState.tronAddress
          const decimals = 6
          const amountInSunBigInt = parseUnits(amount.toString(), decimals)
          const tronWeb = await getTronWeb()
          const unSignedTransaction = await tronWeb.transactionBuilder.sendTrx(
            to,
            Number(amountInSunBigInt),
            from
          )

          const signedTransaction =
            await tronProvider.signTransaction(unSignedTransaction)
          console.log('signTx res:', signedTransaction)

          const res = await tronWeb.trx.sendRawTransaction(signedTransaction)
          console.log('sendTx res:', res)
        }}
      >
        sign transaction
      &#x3C;/button>

      &#x3C;button
        onClick={async () => {
          if (!tronProvider) throw new Error('tronProvider not found')

          const decimals = 6
          const amount = '0.000001'
          const to = 'xxx'
          const from = walletState.tronAddress
          const usdtContractAddr = 'TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t'
          const functionSelector = 'transfer(address,uint256)'

          const amountInSunBigInt = parseUnits(amount.toString(), decimals)
          const parameters = [
            { type: 'address', value: to },
            { type: 'uint256', value: amountInSunBigInt }
          ]
          const triggerSmartContractOptions = {}
          const tronWeb = await getTronWeb()
          const transactionWrapper =
            await tronWeb.transactionBuilder.triggerSmartContract(
              usdtContractAddr,
              functionSelector,
              triggerSmartContractOptions,
              parameters,
              from
            )
          const transaction = transactionWrapper.transaction
          const signedTransaction =
            await tronProvider.signTransaction(transaction)
          console.log('signTx res:', signedTransaction)

          const res = await tronWeb.trx.sendRawTransaction(signedTransaction)
          console.log('sendTx res:', res)
        }}
      >
        sign token transaction
      &#x3C;/button>
    &#x3C;/div>
  )
}

<strong>let tronWeb: TronWebType | null = null
</strong>export async function getTronWeb() {
  if (tronWeb) return tronWeb
  const {
    default: { TronWeb }
  } = await import('tronweb')
  tronWeb = new TronWeb({
    fullHost:
      'https://orbital-dimensional-season.tron-mainnet.quiknode.pro/d14878573fe23f8f40621a303ee2eaa3c812ba1c'
  })
  return tronWeb as TronWebType
}

</code></pre>

### Pure JavaScript

```javascript
import { parseUnits } from 'viem'
import type { TronWeb as TronWebType } from 'tronweb' // "^6.0.0"
import { initTomoModal } from '@tomo-inc/tomo-web-sdk'

const CLIENT_ID = 'Your client id'

enum Theme {
  Light = 'light',
  Dark = 'dark'
}

initTomoModal({
  theme: Theme.Light,
  clientId: CLIENT_ID,
  chainTypes: ['tron']
})

export default function TronDemo() {
  return (
    <div style={{ display: 'flex', gap: '10px' }}>
      <button
        onClick={() => {
          window.openTomoConnectModal?.()
        }}
      >
        openConnectModal
      </button>

      <button
        onClick={async () => {
          const tronProvider = window.tomo_tron
          if (!tronProvider) throw new Error('tronProvider not found')

          const amount = '0.000001'
          const to = 'xxx'
          const from = await tronProvider.getAddress()
          const decimals = 6
          const amountInSunBigInt = parseUnits(amount.toString(), decimals)
          const tronWeb = await getTronWeb()
          const unSignedTransaction = await tronWeb.transactionBuilder.sendTrx(
            to,
            Number(amountInSunBigInt),
            from
          )

          const signedTransaction =
            await tronProvider.signTransaction(unSignedTransaction)
          console.log('signTx res:', signedTransaction)

          const res = await tronWeb.trx.sendRawTransaction(signedTransaction)
          console.log('sendTx res:', res)
        }}
      >
        sign transaction
      </button>

      <button
        onClick={async () => {
          const tronProvider = window.tomo_tron
          if (!tronProvider) throw new Error('tronProvider not found')

          const decimals = 6
          const amount = '0.000001'
          const to = 'xxx'
          const from = await tronProvider.getAddress()
          const usdtContractAddr = 'TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t'
          const functionSelector = 'transfer(address,uint256)'

          const amountInSunBigInt = parseUnits(amount.toString(), decimals)
          const parameters = [
            { type: 'address', value: to },
            { type: 'uint256', value: amountInSunBigInt }
          ]
          const triggerSmartContractOptions = {}
          const tronWeb = await getTronWeb()
          const transactionWrapper =
            await tronWeb.transactionBuilder.triggerSmartContract(
              usdtContractAddr,
              functionSelector,
              triggerSmartContractOptions,
              parameters,
              from
            )
          const transaction = transactionWrapper.transaction
          const signedTransaction =
            await tronProvider.signTransaction(transaction)
          console.log('signTx res:', signedTransaction)

          const res = await tronWeb.trx.sendRawTransaction(signedTransaction)
          console.log('sendTx res:', res)
        }}
      >
        sign token transaction
      </button>
    </div>
  )
}

let tronWeb: TronWebType | null = null
export async function getTronWeb() {
  if (tronWeb) return tronWeb
  const {
    default: { TronWeb }
  } = await import('tronweb')
  tronWeb = new TronWeb({
    fullHost:
      'https://orbital-dimensional-season.tron-mainnet.quiknode.pro/d14878573fe23f8f40621a303ee2eaa3c812ba1c'
  })
  return tronWeb as TronWebType
}

```


# Movement Provider

After setting up your wallet, you can have access to the Movement provider:

```javascript
// react
const { providers } = useTomo()
const { movementProvider } = providers;

// pure js
const tronProvider = window.tomo_movement
```

### Get Movement Address

&#x20;The Movement address is from the wallet state or provider. In React framework:

```tsx
import { useTomo} from '@tomo-inc/tomo-web-sdk';
const { walletState, providers } = useTomo()

// get from wallet state
const movementAddress = walletState.movementAddress

// or get from provider
const movementAddress = await providers.movementProvider.getAddress()


```

Or Pure JS:

<pre class="language-javascript"><code class="lang-javascript"><strong>/** pure js */
</strong>import { getWalletState } from '@tomo-inc/tomo-web-sdk';
/** pure js */
// get from wallet state
const movementAddress = getWalletState().movementAddress

// or get from provider
const movementAddress = await window.tomo_movement.getAddress()
</code></pre>

## Provider Functions

### **Signing a Message**

It uses the Movement provider to sign a plaintext message with a nonce. The output is a response message output defined as below:&#x20;

{% code overflow="wrap" %}

```tsx
// interface
signMessage(
  input: AptosSignMessageInput
): Promise<UserResponse<AptosSignMessageOutput>>;

type AptosSignMessageInput = {
  address?: boolean;
  application?: boolean;
  chainId?: boolean;
  message: string;
  nonce: string;
};

declare enum UserResponseStatus {
  APPROVED = "Approved",
  REJECTED = "Rejected",
}

interface UserApproval<TResponseArgs> {
  status: UserResponseStatus.APPROVED;
  args: TResponseArgs;
}

interface UserRejection {
  status: UserResponseStatus.REJECTED;
}

type UserResponse<TResponseArgs> =
  | UserApproval<TResponseArgs>
  | UserRejection;

type AptosSignMessageOutput = {
  address?: string;
  application?: string;
  chainId?: number;
  fullMessage: string;
  message: string;
  nonce: string;
  prefix: "APTOS";
  signature: Signature;
};

// example
const signedMessage = await movementProvider.signMessage({
  message: "hello movement",
  nonce: "123",
});
```

{% endcode %}

### **Sign Transaction**

To sign a transaction, you need to create a `AnyRawTransaction`  from `Aptos` SDK and send it to the movement Provider for signing.&#x20;

{% code overflow="wrap" %}

```tsx
// interface
import {
  AnyRawTransaction,
  AptosConfig,
  Aptos,
  AccountAddress,
} from "@aptos-labs/ts-sdk";

signTransaction(
  transaction: AnyRawTransaction,
  asFeePayer?: boolean
): Promise<SignedTransaction>;

// example
const config = new AptosConfig({
  fullnode: yourRpcUrl,
});

const client = new Aptos(config);

const transaction = await client.transaction.build.simple({
  sender: AccountAddress.fromString(fromAddress),
  data: {
    functionArguments: [
      AccountAddress.fromString(toAddress),
      +value,
    ],
    function: "0x1::aptos_account::transfer",
  },
});

const signedRes = await movementProvider.signTransaction(transaction);
```

{% endcode %}

### Send Transaction

Our movement provider also supports signing and submitting a transaction through one call, which require a `InputGenerateTransactionPayloadData`  as inputs.

```typescript
// interface
import { InputGenerateTransactionPayloadData } from "@aptos-labs/ts-sdk";

signAndSubmitTransaction(
  transaction: AptosSignAndSubmitTransactionInput
): Promise<SignedTransaction>;

interface AptosSignAndSubmitTransactionInput {
  gasUnitPrice?: number;
  maxGasAmount?: number;
  payload: InputGenerateTransactionPayloadData;
}

// example
const transaction: { payload: InputEntryFunctionData } = {
  payload: {
    functionArguments: ["0x34324...", 123],
    function: "0x1::aptos_account::transfer",
  },
};

const sendRes = await movementProvider.signAndSubmitTransaction(transaction);
```

## Example

We provide an [example ](https://socialwallet-react-prod.tomo.inc/movement)as follows:

### React

```tsx
import {
  AnyRawTransaction,
  AptosConfig,
  Aptos,
  AccountAddress,
  InputEntryFunctionData,
} from "@aptos-labs/ts-sdk";
import { TomoContextProvider, useTomo } from "@tomo-inc/tomo-web-sdk";

const CLIENT_ID = "Your client id";

enum Theme {
  Light = "light",
  Dark = "dark",
}

export default function MovementDemo() {
  return (
    <TomoContextProvider
      theme={Theme.Light}
      chainTypes={["movement"]}
      clientId={CLIENT_ID}
    >
      <App />
    </TomoContextProvider>
  );
}

export function App() {
  const { providers, walletState, openConnectModal } = useTomo();
  const { movementProvider } = providers;

  return (
    <div style={{ display: "flex", gap: "10px" }}>
      <button onClick={openConnectModal}>openConnectModal</button>

      <button
        onClick={async () => {
          if (!movementProvider) throw new Error("movementProvider not found");

          try {
            const config = new AptosConfig({ fullnode: yourRpcUrl });
            const client = new Aptos(config);

            const transaction = await client.transaction.build.simple({
              sender: AccountAddress.fromString(fromAddress),
              data: {
                functionArguments: [AccountAddress.fromString(toAddress), value],
                function: "0x1::aptos_account::transfer",
              },
            });

            const signRes = await movementProvider.signTransaction(transaction);
            console.log("signRes>>>", signRes);

            if (signRes?.status === UserResponseStatus.REJECTED) {
              throw new Error("User rejected the request or failed to sign Move transaction");
            }

            console.log("The transaction was signed successfully:", signRes.args);
          } catch (error) {
            console.error("Error signing transaction:", error);
          }
        }}
      >
        sign transaction
      </button>

      <button
        onClick={async () => {
          if (!movementProvider) throw new Error("movementProvider not found");

          try {
            const transaction: { payload: InputEntryFunctionData } = {
              payload: {
                functionArguments: [address, 123],
                function: "0x1::aptos_account::transfer",
              },
            };

            const sendRes = await movementProvider.signAndSubmitTransaction(transaction);
            console.log("sendRes>>>", sendRes);

            if (sendRes?.status === UserResponseStatus.REJECTED) {
              throw new Error("User rejected the request or failed to send Move transaction");
            }

            console.log("The transaction was sent successfully:", sendRes.args.hash);
          } catch (error) {
            console.error("Error signing and submitting transaction:", error);
          }
        }}
      >
        sign and submit transaction
      </button>
    </div>
  );
}
```

### Pure JS

```javascript
import { initTomoModal } from "@tomo-inc/tomo-web-sdk";
import {
  AnyRawTransaction,
  AptosConfig,
  Aptos,
  AccountAddress,
  InputEntryFunctionData,
} from "@aptos-labs/ts-sdk";

const CLIENT_ID = "Your client id";

enum Theme {
  Light = "light",
  Dark = "dark",
}

initTomoModal({
  theme: Theme.Light,
  clientId: CLIENT_ID,
  chainTypes: ["movement"],
});

export default function MovementDemo() {
  return (
    <div style={{ display: "flex", gap: "10px" }}>
      <button onClick={() => window.openTomoConnectModal?.()}>
        openConnectModal
      </button>

      <button
        onClick={async () => {
          if (!window.movementProvider)
            throw new Error("movementProvider not found");

          try {
            const config = new AptosConfig({ fullnode: yourRpcUrl });
            const client = new Aptos(config);

            const transaction = await client.transaction.build.simple({
              sender: AccountAddress.fromString(fromAddress),
              data: {
                functionArguments: [
                  AccountAddress.fromString(toAddress),
                  value,
                ],
                function: "0x1::aptos_account::transfer",
              },
            });

            const signRes = await window.movementProvider.signTransaction(
              transaction
            );
            console.log("signRes>>>", signRes);

            if (signRes?.status === UserResponseStatus.REJECTED) {
              throw new Error(
                "User rejected the request or failed to sign Move transaction"
              );
            }

            console.log("The transaction was signed successfully:", signRes.args);
          } catch (error) {
            console.error("Error signing transaction:", error);
          }
        }}
      >
        sign transaction
      </button>

      <button
        onClick={async () => {
          if (!window.movementProvider)
            throw new Error("movementProvider not found");

          try {
            const transaction: { payload: InputEntryFunctionData } = {
              payload: {
                functionArguments: [address, 123],
                function: "0x1::aptos_account::transfer",
              },
            };

            const sendRes =
              await window.movementProvider.signAndSubmitTransaction(transaction);
            console.log("sendRes>>>", sendRes);

            if (sendRes?.status === UserResponseStatus.REJECTED) {
              throw new Error(
                "User rejected the request or failed to send Move transaction"
              );
            }

            console.log(
              "The transaction was sent successfully:",
              sendRes.args.hash
            );
          } catch (error) {
            console.error("Error signing and submitting transaction:", error);
          }
        }}
      >
        sign and submit transaction
      </button>
    </div>
  );
}
```


# Sui Provider

After setting up your wallet, you can have access to the Sui provider:

```javascript
// react
const { providers } = useTomo()
const { suiProvider } = providers;

// pure js
const suiProvider = window.tomo_sui
```

### Get Sui Address

&#x20;The Sui address is from the wallet state or provider. In the React framework:

<pre class="language-tsx"><code class="lang-tsx">import { useTomo, getWalletState } from '@tomo-inc/tomo-web-sdk';
const { walletState, providers } = useTomo()

// get from wallet state
const suiAddress = walletState.suiAddress

// or get from provider
<strong>const suiAddress = await providers.suiProvider.getAddress()
</strong>
</code></pre>

Or Pure JS:

<pre class="language-javascript"><code class="lang-javascript"><strong>/** pure js */
</strong>import { getWalletState } from '@tomo-inc/tomo-web-sdk';

// get from wallet state
const suiAddress = getWalletState().suiAddress

// or get from provider
const suiAddress = await window.tomo_sui.getAddress()
</code></pre>

## Provider Functions

### **Signing a Message**

The Sui provider signs messages in bytes and outputs the message and signature:&#x20;

{% code overflow="wrap" %}

```tsx
// interface
signPersonalMessage(_input: { message: Uint8Array; }): Promise<
    string | 
    {
        bytes: string;
        signature: string;
    }
>;

// example
const encoder = new TextEncoder();
const message = encoder.encode("hello world sui");
const res = await provider?.signPersonalMessage({ message });
```

{% endcode %}

### **Sign Transaction**

We follow the standard from Mysten Lab for signing transactions. The user needs to provide a [`SuiSignTransactionInput` ](https://sdk.mystenlabs.com/typedoc/interfaces/_mysten_wallet-standard.SuiSignTransactionInput.html)and get a [`signedtransaction`](https://sdk.mystenlabs.com/typedoc/interfaces/_mysten_wallet-standard.SignedTransaction.html).&#x20;

{% code overflow="wrap" %}

```tsx
// interface
signTransaction: (input: SuiSignTransactionInput) => Promise<SignedTransaction>;

/** Input for signing transactions. */
interface SuiSignTransactionInput {
    transaction: {
        toJSON: () => Promise<string>;
    };
    account: WalletAccount;
    chain: IdentifierString;
    signal?: AbortSignal;
}
/** Output of signing transactions. */
interface SignedTransaction {
    /** Transaction as base64 encoded bcs. */
    bytes: string;
    /** Base64 encoded signature */
    signature: string;
}

// example
const input = {
  transaction,
  account: { address: walletState.suiAddress!, chain: "sui:mainnet" },
  chain: "sui:mainnet",
};

const signRes = await suiProvider.signTransaction(input);
```

{% endcode %}

### Sign and Execute Transaction

We support standard sign and execute a transaction through one call, which requires `SuiSignTransactionInput` as inputs.

{% code overflow="wrap" %}

```typescript
signAndExecuteTransaction: (input: SuiSignAndExecuteTransactionInput) => Promise<SuiSignAndExecuteTransactionOutput>;

/** Input for signing and sending transactions. */
interface SuiSignAndExecuteTransactionInput extends SuiSignTransactionInput {
}

/** Output of signing and sending transactions. */
interface SuiSignAndExecuteTransactionOutput extends SignedTransaction {
    digest: string;
    /** Transaction effects as base64 encoded bcs. */
    effects: string;
}

/** Input for signing transactions. */
interface SuiSignTransactionInput {
    transaction: {
        toJSON: () => Promise<string>;
    };
    account: WalletAccount;
    chain: IdentifierString;
    signal?: AbortSignal;
}

/** Output of signing transactions. */
interface SignedTransaction {
    /** Transaction as base64 encoded bcs. */
    bytes: string;
    /** Base64 encoded signature */
    signature: string;
}


// example
const input = {
  transaction,
  account: { address: walletState.suiAddress!, chain: "sui:mainnet" },
  chain: "sui:mainnet",
};

const sendRes = await suiProvider.signAndExecuteTransaction(input);
```

{% endcode %}

## Example

We provide an [example ](https://socialwallet-react-prod.tomo.inc/sui)of a transfer transaction as follows:

### React

```tsx
import { TomoContextProvider, useTomo } from '@tomo-inc/tomo-web-sdk'

const CLIENT_ID = 'Your client id'

enum Theme {
  Light = 'light',
  Dark = 'dark'
}

export default function SuiDemo() {
  return (
    <TomoContextProvider
      theme={Theme.Light}
      chainTypes={['sui']}
      clientId={CLIENT_ID}
    >
      <App />
    </TomoContextProvider>
  )
}
export function App() {
  const { providers, walletState, openConnectModal } = useTomo()
  const { suiProvider } = providers

  return (
    <div style={{ display: 'flex', gap: '10px' }}>
      <button
        onClick={() => {
          openConnectModal()
        }}
      >
        openConnectModal
      </button>

      <button
        onClick={async () => {
            if (!suiProvider) throw new Error("TronProvider not found");
            const transaction = await buildSuiTransaction({
              fromAddress: walletState.suiAddress!,
              toAddress: address,
              amount: String(amount),
              // coinType: "0x2::sui::SUI",
            });
            const input = {
              transaction,
              account: { address: walletState.suiAddress!, chain: "sui:mainnet" },
              chain: "sui:mainnet",
            };
            const signRes = await suiProvider.signTransaction(input);
            console.log("signRes", signRes);
        }}
      >
        sign transaction
      </button>

      <button
         onClick={async () => {
            if (!suiProvider) throw new Error("TronProvider not found");
            const transaction = await buildSuiTransaction({
              fromAddress: walletState.suiAddress!,
              toAddress: address,
              amount: String(amount),
              // coinType: "0x2::sui::SUI",
            });
            const input = {
              transaction,
              account: { address: walletState.suiAddress!, chain: "sui:mainnet" },
              chain: "sui:mainnet",
            };
            const sendRes = await suiProvider.signAndExecuteTransaction(input);
            console.log("sendRes", sendRes);
        }}
      >
        sign and submit transaction
      </button>
    </div>
  )
}


```

### Pure JS

```javascript

import { initTomoModal } from '@tomo-inc/tomo-web-sdk'

const CLIENT_ID = 'Your client id'

enum Theme {
  Light = 'light',
  Dark = 'dark'
}
initTomoModal({
  theme: Theme.Light,
  clientId: CLIENT_ID,
  chainTypes: ['sui']
})

export default function SuiDemo() {
  return (
    <div style={{ display: 'flex', gap: '10px' }}>
      <button
        onClick={() => {
          window.openTomoConnectModal?.()
        }}
      >
        openConnectModal
      </button>

      <button
        onClick={async () => {
            const suiProvider = window.tomo_sui
            if (!suiProvider) throw new Error("TronProvider not found");
            const transaction = await buildSuiTransaction({
              fromAddress: walletState.suiAddress!,
              toAddress: address,
              amount: String(amount),
              // coinType: "0x2::sui::SUI",
            });
            const input = {
              transaction,
              account: { address: walletState.suiAddress!, chain: "sui:mainnet" },
              chain: "sui:mainnet",
            };
            const signRes = await suiProvider.signTransaction(input);
            console.log("signRes", signRes);
        }}
      >
        sign transaction
      </button>

      <button
         onClick={async () => {
            const suiProvider = window.tomo_sui
            if (!suiProvider) throw new Error("TronProvider not found");
            const transaction = await buildSuiTransaction({
              fromAddress: walletState.suiAddress!,
              toAddress: address,
              amount: String(amount),
              // coinType: "0x2::sui::SUI",
            });
            const input = {
              transaction,
              account: { address: walletState.suiAddress!, chain: "sui:mainnet" },
              chain: "sui:mainnet",
            };
            const sendRes = await suiProvider.signAndExecuteTransaction(input);
            console.log("sendRes", sendRes);
        }}
      >
        sign and submit the transaction
      </button>
    </div>
  )
}
```


# Internal Wallet Services

Tomo provides a few internal wallet services to wallet users so developers can selectively embed these services into their applications with minimum effort. <mark style="color:red;">**Currently, these features are only available for users using social login, and users can only operate through a pop-up Tomo UI component**</mark>. We will add support for extension wallet users and provide more configurable ways to invoke these services.

### Service Types

Tomo supports the following basic service types:

<pre class="language-tsx"><code class="lang-tsx"><strong>enum WebWalletInvokeType {
</strong>  SWAP = "swap",             // Swap between selected token pairs
  ONRAMP = "onramp",         // Purchase Token by card
  SEND = "send",             // Send token to a given address
  RECEIVE = "receive",       // Display QR code and address for given token
}
</code></pre>

#### Modals for Internal Services

<img src="/files/43k6AFoXtz1TYLXel4Bz" alt="Modals for Onramp Services" class="gitbook-drawing">

<img src="/files/1CbAgEXwtEEHDa8XYvn6" alt="Modals for Swap Services" class="gitbook-drawing">

### Invoke Services

```tsx
import "@tomo-inc/tomo-web-sdk/style.css";
import { TomoContextProvider, useTomo,WebWalletInvokeType  } from "@tomo-inc/tomo-web-sdk";

// Get tomo SDK instance
const { openConnectModal, tomoSDK } = useTomo();

const handleAction = async (type: WebWalletInvokeType) => {
    tomoSDK?.handleWebWalletInvoke(type);
  };

// your app logic
...
<button onClick={() => handleAction(WebWalletInvokeType.SWAP)}>
        Swap
      </button>
```

#### Example

```tsx

import "@tomo-inc/tomo-web-sdk/style.css";
import { TomoContextProvider, useTomo,WebWalletInvokeType  } from "@tomo-inc/tomo-web-sdk";

const OrderComponent = () => {
  const { openConnectModal, tomoSDK } = useTomo();

  const handleAction = async (type: WebWalletInvokeType) => {
    tomoSDK?.handleWebWalletInvoke(type);
  };

  return (
    <div style={{ display: 'flex', flexDirection: 'column', gap: '10px' }}>
      <h1>WebSDK Demo</h1>
      <button  onClick={() => openConnectModal()}>Connect Wallet</button>
      <button  onClick={() => handleAction(WebWalletInvokeType.ONRAMP)}>Onramp</button>
      <button  onClick={() => handleAction(WebWalletInvokeType.SWAP)}>Swap</button>
      <button  onClick={() => handleAction(WebWalletInvokeType.SEND)}>Send</button>
      <button  onClick={() => handleAction(WebWalletInvokeType.RECEIVE)}>Receive</button>
    </div>
  );
};

export default function WebSDKPage() {

  return (
    <TomoContextProvider
      theme="light"
      chainTypes={["sui"]}
      clientId="YOUR_CLIENT_ID"
    >
      <div style={{ display: 'flex', flexDirection: 'column', gap: '10px' }}>
        {/* Add your page content here */}
        <OrderComponent />
      </div>
    </TomoContextProvider>
  );
}
```


# Wallet Adaptor SDK

Coming Soon


# Wallet Providers

Tomo wallet functions

Tomo Wallet exposes all functions to specific blockchain network through wallet providers. By default, we provide three commonly used providers for Bitcoin, EVM, and Solna.

To use different networks of Bitcoin or EVM chain, you need to configure the wallet provider accordingly:

```javascript
await bitcoinProvider.switchNetwork(network: Network) 

await evmProvider.swithChain(chainId: string)
```

In addition, one can configure the custom wallet provider to support new network by [contributing ](/tomo-sdk/tomo-web-sdk/wallet-providers/add-custom-wallets)to our SDK


# Chains / Networks

Currently Tomo Connect SDK supports the following chains:

* Bitcoin chain
* Solana chain
* EVM chains

For EVM chains, the built-in supported chains are:

* Arbitrum
* Avalanche
* B2
* B3
* Base
* Berachain
* Bitlayer
* Blast
* BOB
* BNB Chain
* Cronos
* Fantom
* Gnosis
* Linea
* Lorenzo
* Ethereum
* Manta
* Mantle
* Merlin
* MEVM
* Mode
* opBNB
* Optimism
* Polygon
* Polygon zkEvm
* SatoshiVM
* Scroll
* Sei
* Taiko
* xLayer
* ZetaChain
* zkLink Nova
* zkSync
* Zora


# EVM Integrations

The `EthereumProvider` defined in Tomo Connect SDK contains all the necessary functions to interact with EVM chains. Core functions are:

### requestAddresses

Implemented `eth_requestAccounts`

```javascript
public async requestAddresses()
```

### getAddresses

Implemented `eth_accounts`

```javascript
public async getAddresses()
```

### signMessage

Implemented `personal_sign`

```javascript
public async signMessage(msg: string, address: string)
```

### signTypedData

Implemented `eth_signTypedData_v4`

```javascript
public async signTypedData(address: string, msg: string)
```

### sendTransaction

Implemented `eth_sendTransaction`

```javascript
export interface EvmTxParams {
  from: string,
  to: string,
  value: string,
  gasPrice?: string,
  gasLimit?: string,
  maxFeePerGas?: string,
  maxPriorityFeePerGas?: string,
  data?: string,
}

public async sendTransaction(params: EvmTxParams)
```

### sendRawTransaction

Implemented `eth_sendRawTransaction`

```javascript
public async sendRawTransaction(signedTx: string) 
```

### swithChain

Implemented `wallet_switchEthereumChain`

```javascript
public async swithChain(chainId: string)
```

### recoverMessageAddress

Implemented `personal_ecRecover`

```javascript
public async recoverMessageAddress(message: string, signature: string)
```

Also EthereumProvider is a provider compatible with EIP 1193. It can be integrated with third-party libraries like viem, ethers, just like window\.ethereum.

```
// Integrated with viem
const client = createWalletClient({
  chain: mainnet,
  transport: custom(tomoSDK.ethereumProvider)
})
```


# Bitcoin Integrations

The `BitcoinProvider` defined in Tomo Connect SDK contains all the necessary functions to interact with the Bitcoin chain. Core functions are:

### Get Wallet Address

```javascript
async getAddress(): Promise<string>
```

### Get Wallet Public Key

```javascript
async getPublicKeyHex(): Promise<string>
```

### Change Address Type

```javascript
// supported types are P2PKH, P2WPKH, P2TR, P2SH
changeAddressType(addressType: string)
```

### Get All Wallet Types and Addreses

```javascript
export interface AddressInfo {
  value: AddressType;
  label: string;
  name: string;
  displayName?: string;
  hdPath: string;
  address?: string;
}

export const addressInfos: AddressInfo[] = [
  {
    value: AddressType.P2PKH,
    label: "P2PKH",
    name: "Legacy (P2PKH)",
    displayName: "Legacy",
    hdPath: "m/44'/0'/0'/0",
  },
  {
    value: AddressType.P2WPKH,
    label: "P2WPKH",
    name: "Native Segwit (P2WPKH)",
    displayName: "Native Segwit",
    hdPath: "m/84'/0'/0'/0",
  },
  {
    value: AddressType.P2TR,
    label: "P2TR",
    name: "Taproot (P2TR)",
    displayName: "Taproot",
    hdPath: "m/86'/0'/0'/0",
  },
  {
    value: AddressType.P2SH_P2WPKH,
    label: "P2SH",
    name: "Nested Segwit (P2SH-P2WPKH)",
    displayName: "Nested Segwit",
    hdPath: "m/49'/0'/0'/0",
  }
];

async getAllAddresses(): Promise<AddressInfo[]>
```

### Send Bitcoin

<pre class="language-javascript"><code class="lang-javascript"><strong>// send BTC and returns the tx hash
</strong><strong>async sendBitcoin(to: string, satAmount: number): Promise&#x3C;string>
</strong></code></pre>

### Sign Psbt

```javascript
async signPsbt(psbtHex: string): Promise<string>
```

### Sign Message

```javascript
async signMessageBIP322(message: string): Promise<string> 
```

### Switch Network

<pre class="language-javascript"><code class="lang-javascript">export type Network = "mainnet" | "testnet" | "signet";

<strong>async switchNetwork(network: Network) 
</strong></code></pre>

### Get Balance

```javascript
async getBalance(): Promise<number>
```

### Get Network Fees

```javascript
export type Fee = {
  // description of this fee type
  desc: string
  // fee rate
  feeRate: number
  // fee type, slow, fast, avg
  title: string
}
export type Fees = {
  list: Fee[]
}

async getFeeRate(): Promise<Fees>
```

### Get UTXOs

```javascript
export interface UTXO {
  // hash of transaction that holds the UTXO
  txid: string;
  // index of the output in the transaction
  vout: number;
  // amount of satoshis the UTXO holds
  value: number;
  // the script that the UTXO contains
  scriptPubKey: string;
}

getUtxos(address: string, amount: number): Promise<UTXO[]>
```

### Get Latest Height

```javascript
getBTCTipHeight(): Promise<number>
```

### Get inscription data

```typescript
export interface Inscription {
  inscriptionNumber: number
  inscriptionId: string
  offset: number
  moved: boolean
  sequence: number
  isCursed: boolean
  isVindicate: boolean
  isBRC20: boolean
}
export interface UTXOInscription {
  // hash of transaction that holds the UTXO
  txid: string
  // index of the output in the transaction
  vout: number
  // amount in satoshi
  satoshi: number
  // the script that the UTXO contains
  scriptPk: string
  // address uxto belongs to
  address: string
  // inscription info
  inscriptions: Inscription[]
}
export interface InscriptionData {
  // hash of transaction that holds the UTXO
  data: {
    utxo: UTXOInscription[]
  };
  // index of the output in the transaction
  vout: number;
  // amount of satoshis the UTXO holds
  value: number;
  // the script that the UTXO contains
  scriptPubKey: string;
}
getInscriptionData(address: string, network: 'MAINNET'|'TESTNET'): Promise<InscriptionData>
```


# Add Custom Wallets

It is easy to add all kinds of wallets to Tomo Connect SDK.  Here is an example of how to add a Bitcoin wallet to Tomo Connect SDK.

### Fork Tomo Wallet Provider Repo

Please fork the main branch of <https://github.com/UnyxTech/tomo-wallet-provider> into your own repo. After you finish the following integration steps, submit a PR to the `tomo-wallet-provider` repo.

### Add Your Wallet Icon and Wallet Info

Put your wallet icon into the `icons` folder, and create your wallet info into the `list.ts`, such as:

```javascript
  {
    name: "Tomo",
    icon: tomoIcon,
    wallet: TomoWallet,
    provider: tomoProvider,
    linkToDocs: "https://tomo.inc/",
  }
```

### Create Your Wallet Provider

Put your wallet provider into the `providers` folder, and it should extend the `WalletProvider` defined in the library.

Example:

```javascript
import { getNetworkConfig } from "@/config/network.config";
import {
  getAddressBalance,
  getFundingUTXOs,
  getNetworkFees,
  getTipHeight,
  pushTx,
} from "@/utils/mempool_api";

import {
  Fees,
  Network,
  UTXO,
  WalletInfo,
  WalletProvider,
} from "../wallet_provider";

export const tomoProvider = "tomo_btc";

// Internal network names
const INTERNAL_NETWORK_NAMES = {
  [Network.MAINNET]: "mainnet",
  [Network.TESTNET]: "testnet",
  [Network.SIGNET]: "signet",
};

export class TomoWallet extends WalletProvider {
  private tomoWalletInfo: WalletInfo | undefined;
  private bitcoinNetworkProvider: any;
  private networkEnv: Network | undefined;

  constructor() {
    super();

    // check whether there is Tomo extension
    if (!window[tomoProvider]) {
      throw new Error("Tomo Wallet extension not found");
    }
    this.networkEnv = getNetworkConfig().network;

    this.bitcoinNetworkProvider = window[tomoProvider];
  }

  connectWallet = async (): Promise<this> => {
    const workingVersion = "1.2.0";
    if (!this.bitcoinNetworkProvider) {
      throw new Error("Tomo Wallet extension not found");
    }
    if (!this.networkEnv) {
      throw new Error("Network not found");
    }
    if (this.bitcoinNetworkProvider.getVersion) {
      const version = await this.bitcoinNetworkProvider.getVersion();
      if (version < workingVersion) {
        throw new Error("Please update Tomo Wallet to the latest version");
      }
    }

    await this.bitcoinNetworkProvider.switchNetwork(
      INTERNAL_NETWORK_NAMES[this.networkEnv],
    );

    let addresses = null;
    let pubKey = null;
    try {
      // this will not throw an error even if user has no BTC Signet enabled
      addresses = await this.bitcoinNetworkProvider.connectWallet();
      pubKey = await this.bitcoinNetworkProvider.getPublicKey();
      if (!addresses || addresses.length === 0 || !pubKey) {
        throw new Error("BTC is not enabled in Tomo Wallet");
      }
    } catch (error) {
      throw new Error("BTC is not enabled in Tomo Wallet");
    }

    this.tomoWalletInfo = {
      publicKeyHex: pubKey,
      address: addresses[0],
    };
    return this;
  };

  getWalletProviderName = async (): Promise<string> => {
    return "Tomo";
  };

  getAddress = async (): Promise<string> => {
    if (!this.tomoWalletInfo) {
      throw new Error("Tomo Wallet not connected");
    }
    return this.tomoWalletInfo.address;
  };

  getPublicKeyHex = async (): Promise<string> => {
    if (!this.tomoWalletInfo) {
      throw new Error("Tomo Wallet not connected");
    }
    return this.tomoWalletInfo.publicKeyHex;
  };

  signPsbt = async (psbtHex: string): Promise<string> => {
    if (!this.tomoWalletInfo) {
      throw new Error("Tomo Wallet not connected");
    }
    // sign the PSBT
    return await this.bitcoinNetworkProvider.signPsbt(psbtHex);
  };

  signPsbts = async (psbtsHexes: string[]): Promise<string[]> => {
    if (!this.tomoWalletInfo) {
      throw new Error("Tomo Wallet not connected");
    }

    // sign the PSBTs
    return await this.bitcoinNetworkProvider.signPsbts(psbtsHexes);
  };

  signMessageBIP322 = async (message: string): Promise<string> => {
    if (!this.tomoWalletInfo) {
      throw new Error("Tomo Wallet not connected");
    }
    return await this.bitcoinNetworkProvider.signMessage(
      message,
      "bip322-simple",
    );
  };

  getNetwork = async (): Promise<Network> => {
    const internalNetwork = await this.bitcoinNetworkProvider.getNetwork();

    for (const [key, value] of Object.entries(INTERNAL_NETWORK_NAMES)) {
      if (value === internalNetwork) {
        return key as Network;
      }
    }

    throw new Error("Unsupported network");
  };

  on = (eventName: string, callBack: () => void) => {
    if (!this.tomoWalletInfo) {
      throw new Error("Tomo Wallet not connected");
    }
    // subscribe to account change event
    if (eventName === "accountChanged") {
      return this.bitcoinNetworkProvider.on(eventName, callBack);
    }
  };

  // Mempool calls

  getBalance = async (): Promise<number> => {
    return await getAddressBalance(await this.getAddress());
  };

  getNetworkFees = async (): Promise<Fees> => {
    return await getNetworkFees();
  };

  pushTx = async (txHex: string): Promise<string> => {
    return await pushTx(txHex);
  };

  getUtxos = async (address: string, amount?: number): Promise<UTXO[]> => {
    // mempool call
    return await getFundingUTXOs(address, amount);
  };

  getBTCTipHeight = async (): Promise<number> => {
    return await getTipHeight();
  };
}
```


# TomoContextProvider props

TomoContextProvider is the primary provider for the Tomo Connect SDK. It initializes the SDK and configures its settings and controls the UI component.

Here is the full list of props that can be passed to the TomoContextProvider.

### Settings

<table><thead><tr><th width="201">Property</th><th width="210">Type</th><th>Description</th></tr></thead><tbody><tr><td>clientId</td><td>string</td><td>Client ID applied from Tomo's social dashboard</td></tr><tr><td>evmDefaultChainId?</td><td>number</td><td>Selected EVM chain id,  default is 1</td></tr><tr><td>evmChains?</td><td>(TomoChain | number)[]</td><td>Supported EVM chains, default is all </td></tr><tr><td>chainTypes?</td><td>ChainType[]</td><td>Supported chains, default are EVM chains, Solana, Bitcoin</td></tr><tr><td>sdkMode?</td><td>string</td><td>Used for developer mode, allowed value is undefined | 'dev', default is undefined</td></tr><tr><td>logLevel?</td><td>string</td><td>Used for developer mode, allowed value is undefined | 'debug', default is undefined</td></tr></tbody></table>

Related type definitions are:

```javascript
import { Chain } from 'viem'

export type ChainType = 'evm' | 'bitcoin' | 'solana'
export type TomoChain = Chain<undefined> & { img?: string }
```


# Embedded Wallet (UI Component)

### What is the Tomo Embedded Wallet

Tomo Embedded Wallet offers seamless and visually engaging login experiences tailored for crypto-native users and easy onboarding for everyone else. Key features include:

* **Unified Account System**: Tomo provides a unified wallet for your social account. That is, if you log in to dApp A with your Gmail and buy X tokens, when you log in to dApp B, you can directly use the previously purchased token. This feature is the core of the Tomo wallet, allowing users to smoothly use their assets in one wallet with one social account.
* **Multi-Blockchain Support**: Tomo wallet supports most mainstream blockchains, including Bitcoin, Ethereum, Solana, etc. We support built-in swap functionalities between different on-chain assets, so users can easily invest in new assets within our embedded wallet.
* **Secure and Reliable**: We take security as our highest priority in wallet design. The embedded wallet stores your private key into a secure hardware wallet and dApp. The dApps will have no access to the user's private key, and only the user can authorize the transaction signing or private key exports through Multi-Factor Authorization (MFA)

<figure><img src="/files/7mkbrAJ4PkWGV850nuxr" alt=""><figcaption><p>Social Login</p></figcaption></figure>

With simplified developer tools and cryptographic security measures, Tomo embedded wallet is designed to provide user-friendly wallets while maintaining the highest security for web3 developers and users.


# Login and Setting

When a web3 product supports the Tomo social wallet, you can use the social login option to connect to your Tomo social wallet. Currently, we support login from Email, Gmail, and X (Twitter) accounts.&#x20;

<figure><img src="/files/pYtYf1lhafr594hXkPsP" alt=""><figcaption><p>Social login interface</p></figcaption></figure>

&#x20;If it's your first time using the social wallet, you must set up your passkey as 2FA to sign transactions. 2FA is necessary for using Tomo wallet.

<figure><img src="/files/2utFuKI845EXowKhzxlR" alt="" width="375"><figcaption><p>Setup 2FA</p></figcaption></figure>

&#x20;After login, Tomo will automatically connect to the existing wallet or create a new wallet for a new account. A new wallet will require the user to set the passkey for security.&#x20;

<figure><img src="/files/AZIJMarN7zm1npmceF23" alt="" width="563"><figcaption><p>Main page of Tomo social wallet</p></figcaption></figure>

The first-time logging into a dApp, you can check the token list specified by the dApp developers directly, including balance, price, and total value.<br>

<figure><img src="/files/v2YJ85o7Pdu4yGuFdsZ6" alt=""><figcaption><p>Account's security setting</p></figcaption></figure>

In the setting phase, you can bind your wallet to other social accounts and emails by clicking the profile icon. It is recommended that you bind the email to log in even if your social account is no longer available. You can also set up new 2FA methods (new passkey or Google authenticator) to enhance security in case of device loss. Finally, if you are confident about maintaining the private key, you can download a Tomo wallet (mobile or extension) and social login to it to export your mnemonic phrase.


# Sign a Transaction / Message

Tomo provides a smooth and secure experience when interacting with the dApp. Whenever the dApp creates a transaction according to your request, or you send/swap a token in the social wallet, it triggers Tomo's signing flow. You can look into the details of the transaction. If the transaction is in standard format, like a transfer token or function call, Tomo will parse the transaction so you can confirm whether the details are correct and the transaction fee.

<figure><img src="/files/joFzJwqgLK3k7HcW5MM4" alt=""><figcaption><p>View transaction to be signed</p></figcaption></figure>

After clicking the sign button, Tomo will trigger the second-factor authentication with your default MFA setting to ensure it's your operation. Then, sign the transaction and send it to the corresponding network. If the wallet has insufficient balance or the transaction is malformed, the procedure will fail with an error message.

<figure><img src="/files/baoLmzskGKt2bGS3txiU" alt=""><figcaption><p>Signing transaction with 2FA</p></figcaption></figure>


# Built-in Functions

The Tomo social wallet provides built-in operations for handling your assets: receive, send, and swap(coming soon). To receive tokens, select the network for the chain you want to operate and click receive to show your address. If supported, you may also pick different address types.&#x20;

<figure><img src="/files/0n13WfNyF5FfOSyxUzau" alt=""><figcaption><p>Receive Tokens</p></figcaption></figure>

Similarly, to send tokens, you only need to select the network and choose your token to send it to, along with the receiver's address and amount. Transaction fees will be automatically calculated. After clicking the continue, you trigger the signing transaction flow.

<figure><img src="/files/KGksUzJCXz4VSI1Tl3SI" alt=""><figcaption><p>Send Tokens</p></figcaption></figure>

Coming Soon) Tomo social wallet will provide a swapping function for users to easily swap their tokens. When exploring dApp in a new blockchain that Tomo supports, you can easily swap the new token with your existing tokens and enjoy your web3 journey easily and smoothly. You can select the source token and target token with gas/time estimation by clicking the swap. After clicking the continue, you trigger the signing transaction flow.

<figure><img src="/files/K7BqfBi5fXbi6EKzIoZI" alt=""><figcaption><p>swap tokkens</p></figcaption></figure>

If you have not found the token you want to operate in the default list, you can use the manage asset function to search for the token. If you want to use tokens not listed on Tomo, you can add the token by specifying the contract address, token symbol, and precision decimals.

<figure><img src="/files/35srlfdDA7EI7iMBlhvX" alt=""><figcaption><p>Asset management</p></figcaption></figure>


# Backup

As the adoption of blockchain technology and decentralized applications (dApps) continues to grow, the need for user-friendly and secure wallet solutions becomes increasingly critical. Traditional wallets (Externally Owned Accounts (EOA) or Account Abstraction (AA) wallets) have often faced challenges related to usability and security.

1. **Complexity and Usability**: Traditional EOA wallets require users to manage complex seed phrases or private keys, which can be daunting for newcomers and lead to user error. While offering more flexibility and features, AA wallets still require users to understand blockchain mechanics.
2. **Security Risks**: Reliance on a single private key in EOA wallets creates a single point of failure. The user loses access to their assets if the private key is lost or compromised, the user loses access to their assets. Despite offering improved security models, AA wallets still face similar key management complexity and can be challenging to recover if compromised.
3. **Adoption Barrier**: The technical complexity of existing wallets can deter potential users from engaging with blockchain technology, slowing overall adoption.

Tomo provides a universal solution connecting the user wallet and dApps to resolve the above issues. Our solution provides a one-in-all social login solution that helps users smoothly manage assets across platforms and apps.

### Our Solution

Tomo Connect SDK emerges from the widely adopted OAuth model while bracing more cryptographic tools to enhance its security for web3 adoption. Tomo Connect SDK simplifies the user experience and enables key recovery by leveraging familiar social authentication methods like:

* Google OAuth2: Users can log in with their Google account using a simple one-line code integration.
* Twitter OAuth2: Users can log in with their Twitter account easily.
* Email Login: Users can log in via email by sending and verifying a code.

<figure><img src="/files/qDXu2r0GdH1AYjofxqnu" alt="" width="296"><figcaption><p>Tomo Social Login</p></figcaption></figure>

By integrating social login mechanisms, users can create and use an embedded wallet, which provides several key benefits:

1. **Enhanced Usability**: Tomo Connect SDK significantly lowers the entry barrier for new users by allowing them to access their wallets using their social media accounts and mature OAuth infrastructure. This familiar process reduces the need for users to manage complex private keys or seed phrases.
2. **Embedded Wallet UX**: Many users find connecting mobile wallets to decentralized applications (DApps) challenging. An embedded wallet integrated directly within the application removes this barrier, providing a more cohesive and reliable user experience.
3. **Improved Security**: Tomo Connect SDK and underlying wallet incorporate additional layers of security, such as two-factor authentication (2FA), leveraging the robust security frameworks of social media platforms and secure key management frameworks. This multi-layered approach reduces the risk of unauthorized access to your wallet.
4. **Seamless Recovery**: In case of account loss or compromise, our wallet service can offer more straightforward recovery options through the user's social media account, providing a more user-friendly and less stressful recovery process than traditional wallets.

In addition to the Tomo embedded wallet, users can connect their existing wallets through our SDK, and dApp developers can use a unified interface provided by our SDK to interact with all these wallets.

<figure><img src="/files/PoLyno9oQruiO10072xy" alt="" width="291"><figcaption><p>Multi-wallet supports</p></figcaption></figure>

### Demo

We provide a [demo ](https://socialwallet-react-prod.tomo.inc/login)application for users to experience Tomo social login and wallet. Social login in our demo allows you to access the same wallet in other dApps with the same social account.&#x20;


# Solana Integrations

The `SolanaProvider` defined in Tomo Connect SDK contains all the necessary functions to interact with Solana chain. Core functions are:

### Get Wallet Public Key

```javascript
async getPublicKey()
```

### Send SOL

```javascript
async sendSol(to: string, amount: string, mintAddress?: string): Promise<string>
```

### Sign Transaction

```javascript
import { Transaction, VersionedTransaction } from "@solana/web3.js";

async signTransaction<T extends Transaction | VersionedTransaction>(
    transaction: T
): Promise<T>
```

### Sign All Transactions

```javascript
async signAllTransactions<T extends Transaction | VersionedTransaction>(
    transactions: T[]
): Promise<T[]>
```

### Sign and Send Transaction

```javascript
import { 
      Transaction,
      VersionedTransaction,
      SendOptions,
      TransactionSignature
} from "@solana/web3.js";

async signAndSendTransaction<T extends Transaction | VersionedTransaction>(
      transaction: T,
      options?: SendOptions
): Promise<{ signature: TransactionSignature }>
```

### Sign Message

```javascript
async signMessage(message: Uint8Array): Promise<{ signature: Uint8Array }>
```

### Connect

```javascript
async connect(): Promise<void>
```

### Disconnect

```javascript
async disconnect(): Promise<void>
```


# Tomo Telegram SDK

Tomo Telegram (TG) Wallet SDK provides a solution that provides a universal wallet experience to Telegram users. Developers can use the Tomo Telegram SDK to enable a one-click connection from users' Telegram accounts to their unique Tomo wallet.

<img src="/files/NzGP8XaO8DOstaBZ8Rws" alt="Architecture of Tomo Telegram SDK wallet solution" class="gitbook-drawing">

Users can create a Tomo TG SDK wallet by logging in to any Telegram application that integrates with our Telegram SDK. The Tomo TG wallet will create a secure SDK wallet for the user. In addition to the Tomo TG SDK wallet, users can use Wallet Connect and TON Connect to use their OKX wallets, Bitget wallets, or TON Connect wallet.

<img src="/files/gS7SfZJMlrA0Ll70En49" alt="" class="gitbook-drawing">

Once logged in, users can smoothly and [safely ](/overview/tomos-key-management)use the same wallet across different Telegram applications through their Telegram account. Telegram applications can query public information through the Tomo[ API](/tomo-sdk/tomo-telegram-sdk/tomo-apis) or our [SDK](/tomo-sdk/tomo-telegram-sdk/wallet-provider).&#x20;

To sign a message or transaction, the Telegram dApp must query the SDK and trigger the Tomo Telegram SDK wallet for user authentication. The user will need to input the pay pin to confirm the operation. Once the user confirms the request with the pay pin, the Tomo Telegram SDK wallet will request the TEE to sign the required transaction and return it for the Telegram application to send.

<figure><img src="/files/ZSjO4at60ujXp5yXjDRv" alt="" width="188"><figcaption><p>Authenticate Transcation</p></figcaption></figure>

We provide a [demo ](http://t.me/tomowalletbot/tomo_sdk_demo)showing the basic features of the Tomo Telegram SDK wallet support.


# Quick Start

Please check our [demo ](http://t.me/tomowalletbot/tomo_sdk_demo)application to experience what you can do with Tomo Telegram SDK.\
\
We provide some demo examples for you to initiate a project with Tomo SDK:\
1\. [Wagmi](https://github.com/FansTech/rainbow-wagmi-example/blob/main/src/pages/wagmi/index.tsx)\
2\. [Rainbowkit](https://github.com/FansTech/rainbow-wagmi-example/blob/main/src/pages/rainbowkit/index.tsx)

### Installation

Tomo Telegram SDK is published and maintained through NPM. Use the following commands for installing the package.

```sh
npm i @tomo-inc/tomo-telegram-sdk
```

or

```bash
pnpm i @tomo-inc/tomo-telegram-sdk
```

### Initialization

Initiate the SDK with one of the following choices according to your application once in the application.&#x20;

{% code overflow="wrap" %}

```javascript
// Use full features
import { TomoWalletTgSdkV2 } from '@tomo-inc/tomo-telegram-sdk';

// Initiate with UI
new TomoWalletTgSdkV2({ injected: true })

// If you do not want UI, you can use 
new TomoWalletTgSdkV2()
```

{% endcode %}

If you only use EVM providers, you can use the following way to initiate the EVM provider only:

{% code title="" %}

```typescript
import { EthereumProvider } from '@tomo-inc/tomo-telegram-sdk/tomoEvmProvider.esm';

useEffect(() => {
  const ethereumProvider = new EthereumProvider({
    injected: true,
    overrideRpcUrl: {
      // Specify all networks you want to use here.
      // Example:
      // 80084: 'https://bartioXXX.rpc.berachain.com'
    },
  });
}, []);
```

{% endcode %}

### Use the Modal

<img src="/files/QguEl89O6dTRZayKELu7" alt="Modal for user login" class="gitbook-drawing">

Developers need to associate the modal with the login button in the UI so the user can log in through our SDK.

#### React Framework

{% code overflow="wrap" %}

```typescript
import { TomoProvider, CONNECT_MAP, useTomo } from '@tomo-inc/tomo-telegram-sdk';
import '@tomo-inc/tomo-telegram-sdk/dist/styles.css'

// Configure your app with Tomo provider. 
// For example, use the Ton provider only
<TomoProvider
  theme='light'
  supportedProviders={['TON']}
  manifestUrl={'https://d8o5s6z018yzr.cloudfront.net/manifestUrl.json'}
  tomoOptions={{
    metaData: {
        icon:
        'your app icon',
        name: 'your app name',
        url: location.origin + '/testing'
    },
    }}
    overrideTomoRpcUrls={{
      // Please specify all EVM RPC nodes you want to use!
      // 80084: 'https://bartioXXX.rpc.berachain.com'
    } as Record<number, string>}
>
  <YourApp />
</TomoProvider>

const { openConnectModal, providers } = useTomo();

openConnectModal();

// get provider, for example, ton provider
useEffect(() => {
  const tomo_ton = providers.tomo_ton;
  tomo_ton && setTomoTonProvider(tomo_ton);
}, [
  providers.tomo_ton?.connected,
  providers.tomo_ton?.account,
]);

```

{% endcode %}

#### &#x20;pure JavaScript

{% code overflow="wrap" %}

```typescript
import '@tomo-inc/tomo-telegram-sdk/dist/styles.css';
import { initTomoModal, initTomoModalParams, CONNECT_MAP } from '@tomo-inc/tomo-telegram-sdk';

await initTomoModal({
  onConnect: () => {
    console.log('connected!');
  },
  supportedProviders: ['TON'],
  supportedConnects:['CONNECT_MAP.TON_CONNECT']
  manifestUrl: 'https://d8o5s6z018yzr.cloudfront.net/manifestUrl.json', // manifest for ton connect
} as initTomoModalParams);

```

{% endcode %}

#### Connect Other Wallets

Other than the Tomo native provider based on the user's Tomo Telegram SDK Wallet, users can connect to their OKX Telegram wallet/OKX web3 wallet, Bitget Wallet, UXUY wallet, or TON Native Wallet by different connect maps. The developer can control this through the parameters of `supportedConnects` in the `TomoProvider`⁣. More EVM connectors are coming soon.&#x20;

{% code overflow="wrap" %}

```typescript
// react way
<TomoProvider
  ...
  supportedProviders={['EVM']}
  supportedConnects={[CONNECT_MAP.TOMO_MINI_APP, CONNECT_MAP.OKX_CONNECT, CONNECT_MAP.TON_CONNECT,
    CONNECT_MAP.BITGET_WALLET]}
  tomoOptions={{
        metaData: { // this is required by OKX and Bitget wallet
              icon:'your app icon',
              name: 'your app name',
              url: location.origin + '/testing'
        },
    }}
    useEvmChains={chains} // an array of numbers to indicate chained when connecting to OKX and Bitget. OKX and Bitget wallet require this field.
    ...
>

>
  <YourApp />
</TomoProvider>>

// javascript way
await initTomoModal({
 ...
  supportedConnects: [
    CONNECT_MAP.TOMO_MINI_APP,
    CONNECT_MAP.OKX_CONNECT,
    CONNECT_MAP.TON_CONNECT,
    CONNECT_MAP.BITGET_WALLET,
    CONNECT_MAP.UXUY_WALLET, 
  ],
  ...
} as initTomoModalParams);

// Supported CONNECT_MAP and chain type
export enum CONNECT_MAP {
  TOMO_MINI_APP = 'Tomo Mini App',
  OKX_CONNECT = 'OKX Connect',
  TON_CONNECT = 'TON Connect',
  BITGET_WALLET = 'Bitget Wallet',
  UXUY_WALLET = 'UXUY',
}

export const ChainIdWithConnectsMap = {
  SOL: [CONNECT_MAP.TOMO_MINI_APP],
  TON: [CONNECT_MAP.TOMO_MINI_APP, CONNECT_MAP.OKX_CONNECT, CONNECT_MAP.TON_CONNECT],
  EVM: [CONNECT_MAP.TOMO_MINI_APP, CONNECT_MAP.OKX_CONNECT, CONNECT_MAP.BITGET_WALLET, CONNECT_MAP.UXUY_WALLET],
};
```

{% endcode %}

We unify the providers' interfaces into `providers` across all different wallet solutions so you can use them transparently.

### Connect/Disconnect Wallet Providers

You can connect wallet providers for the chain you want to use. Currently, our SDK supports the EVM chains, Sui, Solana, and TON networks, and we plan to add support for BTC soon.

<pre class="language-typescript"><code class="lang-typescript">// get provider 
const tomo_ton = window.tomo_ton
<strong>
</strong><strong>// connect wallet
</strong><strong>await tomo_ton?.connectWallet();
</strong><strong>
</strong>// disconnect wallet
await tomo_ton?.disconnect();
</code></pre>

#### GetWalletInfo

After connecting the wallet, we can use `getWalletInfo()`to get which wallet user used.&#x20;

```typescript
import { getWalletInfo } from '@tomo-inc/tomo-telegram-sdk';

getWalletInfo()

// return value contains:
// {
//    name: 'wallet name',
//    icon: 'url to icon',
//    type: CONNECT_MAP,
// }

```

In react framework, you can directly fetch the wallet info:

```typescript
const {openConnectModal, providers, walletInfo} = useTomo();
```


# Wallet Provider

This guide demonstrates how to integrate the Tomo Wallet into your Telegram mini-application (mini app) using the Tomo Telegram SDK.

The integration enables users to connect their Tomo Wallet on Telegram and perform multi-chain transactions seamlessly.


# Bitcoin Provider (Beta)

The Tomo Telegram SDK provides a Bitcoin Provider for sending transactions. Below are methods that developers can use with our Bitcoin provider.

```typescript
// get provider
const bitcoin = window.tg_tomo_btc;
```

Currently, Bitcoin provider supports the following address type

<pre class="language-typescript"><code class="lang-typescript">type BTCNetworkType = 'MAINNET' | 'TESTNET' | 'SIGNET';
<strong>type IBtcAddressType = 'bitcoinP2Wpkh' | 'bitcoinP2Sh' | 'bitcoinP2Tr' | 'bitcoinP2Pkh';
</strong>const btcAddressTypeMaps: IBtcAddressType[];
</code></pre>

## Connect with the Wallet[​](https://docs.uxuy.com/uxuy-connect/guide/#isconnected) <a href="#isconnected" id="isconnected"></a>

Before using the provider, the user needs to log in to the wallet through the modal by following the method:

```typescript
// connect wallet
await bitcoin?.connectWallet();
```

### Signing Methods[​](https://docs.uxuy.com/uxuy-connect/guide/#signing-methods) <a href="#signing-methods" id="signing-methods"></a>

The Tomo Telegram SDK supports two signing methods:

* `btc_signMessage`
* `btc_signTransaction`

`btc_signMessage` method is used for siging a transaction that only record a message on-chain through `OP_RETURN` operation.&#x20;

```javascript
 const res = await bitcoin.request({
  method: 'btc_signMessage',
  params: [
    {
      addressType: btcAddressTypeMaps[2],
      message: 'btc sign message',
    },
  ],
});
    return res;
```

`btc_signPsbt` allows the user to sign a transaction with hex, and the return value is the signed transaction in hex.

```javascript
 const res = await bitcoin.request({
  method: 'btc_signPsbt',
  params: [
    {
      network:'SIGNET',
      addressType: btcAddressTypeMaps[2],
      psbtHex: '0200000000010145430f279a5e63a9bda3761efbf9f49b9ee4d428f5fe4b2bfeae2e7b54ca83f90000000000fdffffff01bdd5070000000000160014a3213c72757d86a33543010ff748f203a544a2810247304402200134cddfacc47b1c84cd64c2f88d8aa0a3384f42c8ec659bb70dcc4ce4571b650220554c085d85aee0f09f45993dfd485d5ca3df3feba49f9195dfbc4e045694ee88012102d207a562f7466bd1be96be8b35c9ca481a907d8cbf4b1e131b072a4878c1178600000000'
    },
  ],
});
    return res;
```

### Send Transaction[​](https://docs.uxuy.com/uxuy-connect/guide/#isconnected) <a href="#isconnected" id="isconnected"></a>

Using  `btc_sendTx` , the developer can create a simple transfer transaction for the user to authorize and send to a specified network: &#x20;

```typescript
import { btcAddressTypeMaps } from 'tomo-tg-wallet-sdk';

const res = await bitcoin.request({
  method: 'btc_sendTx',
  params: [
    {
      network: 'SIGNET',
      addressType: btcAddressTypeMaps[2],
      toAddress: toAddr2,
      amount: toValue2,
    },
  ],
});
```


# EVM Provider

The Tomo Telegram SDK implements the Ethereum provider, allowing seamless integration with existing Ethereum-compatible DApps.

To use the EVM provider in your application, you need to first install the SDK and get the wallet provider:

```typescript
// get provider 
const ethereum = window.ethereum;
```

Below are methods that developers can use with our EVM provider.

## Wallet Connect <a href="#isconnected" id="isconnected"></a>

Before using the provider, the user needs to log in to the wallet through the modal by [`eth_requestAccounts` ](#supported-methods)method. The `isConnected` method returns a boolean value indicating whether the wallet is connected or not.

```javascript
ethereum.isConnected(): boolean
```

## Query Methods[​](https://docs.uxuy.com/uxuy-connect/guide/#request-method) <a href="#request-method" id="request-method"></a>

The `request` method is used to make an RPC request to the connected wallet. For detailed information on JSON-RPC methods, refer to:

* [MetaMask JSON-RPC API](https://docs.metamask.io/wallet/reference/json-rpc-api/)
* [Ethereum.org JSON-RPC API](https://ethereum.org/developers/docs/apis/json-rpc/)

We provide some frequently used methods as below:[​](https://docs.uxuy.com/uxuy-connect/guide/#supported-methods)

### **Get accounts**[**​**](https://docs.uxuy.com/uxuy-connect/guide/#eth_requestaccounts) **address** <a href="#supported-methods" id="supported-methods"></a>

Connects to the wallet and returns the address of the connected wallet. In Tomo, the return value is the first address in the response.

{% code overflow="wrap" %}

```typescript
const accounts = await ethereum.request({
  method: 'eth_requestAccounts',
  params: [],
});
```

{% endcode %}

Or you can use the `eth_accounts` method to fetch the previous read address from the cache. If missed, it will return an empty array; use it with care!&#x20;

```typescript
const accounts = await ethereum.request({
  method: 'eth_accounts',
  params: [],
});
```

### **Get chain ID**

Returns the chain ID of the connected wallet.

```javascript
const chainId = await ethereum.request({ method: 'eth_chainId' });
```

### Get balance

Returns the mainnet balance of ETH in wei of hex format.

```typescript
// eth_getBalance
const hexAmount= await window.ethereum.request({
  method: 'eth_getBalance',
  params: [addr, 'latest'],
});


const weiAmount = BigInt(hexAmount);

// const ethAmount = weiAmount / BigInt(10 ** 18);
const ethDecimal = Number(weiAmount) / 1e18;
const weiString = weiAmount.toString();
```

## **Sign Message**

The Tomo Telegram SDK supports signing messages through the request method under the Metamask standard:

* `personal_sign`
* `eth_signTypedData`
* `eth_signTypedData_v3`
* `eth_signTypedData_v4`

The return value is the signature data. For detailed usage, refer to:

* [Signing Data](https://docs.metamask.io/wallet/how-to/sign-data/#signing-data-with-metamask)
* [Signing Transaction](https://docs.metamask.io/wallet/how-to/send-transactions/)
* [eth-sig-util](https://github.com/MetaMask/eth-sig-util)

Example of⁣`personal_sign`:

```javascript
const accounts = await ethereum.request({ method: 'eth_accounts' });
const chainId =  await ethereum.request({ method: 'eth_chainId' });

const signature = await ethereum.request({
  method: 'personal_sign',
  params: ['Hello, Tomo!', accounts[0]]
});

```

Example of⁣`eth_signTypedData_v4`:

```javascript
const accounts = await ethereum.request({ method: 'eth_accounts' });
const chainId = await ethereum.request({ method: 'eth_chainId' });

const msgParams = {
  domain: {
    chainId: chainId,
    name: "Ether Mail",
    verifyingContract: "0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC",
    version: "1",
  },
  message: {
    contents: "Hello, Bob!",
    from: {
      name: "Cow",
      wallets: [
        "0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826",
        "0xDeaDbeefdEAdbeefdEadbEEFdeadbeEFdEaDbeeF",
      ],
    },
    to: [
      {
        name: "Bob",
        wallets: [
          "0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB",
          "0xB0BdaBea57B0BDABeA57b0bdABEA57b0BDabEa57",
          "0xB0B0b0b0b0b0B000000000000000000000000000",
        ],
      },
    ],
    attachment: "0x",
  },
};

const signatureV4 = await ethereum.request({
  method: "eth_signTypedData_v4",
  params: [accounts[0], JSON.stringify(msgParams)],
});
```

## Sign Transaction

`eth_signTransaction` method will return a response with a signed transaction. Or you can use `eth_sendTransaction` it to send the signed transaction directly to the RPC node you specified in the provider. If you specify the `chainId` in `params`, the transaction will be sent to that network. Otherwise, it will be sent to the network you switched to using `wallet_switchEthereumChain` the method.

For users to verify the transaction contents, we only support passing parameters to the SDK and letting the user decide whether to sign the created transaction.&#x20;

### Transfer transaction

```typescript
// Simple transfer transaction
const response1 = await ethereum.request({
  method: 'eth_signTransaction', // or eth_sendTransaction
  params: [
    {
      from: addr,
      to: toAddr1,
      value: hexString,
      gas: hexString,
      gasPrice: hexString,
      nonce: hexString,
      chainId: hexString,
    },
  ],
});
```

### Contract call transaction

```javascript
// Transaction call contract
const response2 = await ethereum.request({
  method: 'eth_signETHTransaction', // or eth_sendTransaction
  params: [
    {
      from: addr,
      to: contractAddr,
      value: int,
      chainId: hexString,
      data: hexData,
    },
  ],
});
```

For example, below is the demo for sending ERC20 tokens:

```typescript
import { ethers } from 'ethers';

// Example of ERC20 transfer
const abi = [
  {
    inputs: [
      {
        internalType: 'address',
        name: 'to',
        type: 'address',
      },
      {
        internalType: 'uint256',
        name: 'amount',
        type: 'uint256',
      },
    ],
    name: 'transfer',
    outputs: [
      {
        internalType: 'bool',
        name: '',
        type: 'bool',
      },
    ],
    stateMutability: 'nonpayable',
    type: 'function',
  },
];

// Check the decimal of the ERC20 token, assume 6 for USDT
const val = Number(amount) * 10 ** 6;
const iface = new ethers.utils.Interface(abi);
const data = iface.encodeFunctionData('transfer', [to, val.toString()]);

const response = await ethereum.request({
  method: 'eth_signETHTransaction', // or eth_sendTransaction
  params: [
    {
      from: from,
      to: contract_address,
      value: '0x0', // Value in hexadecimal
      chainId: chainId,
      data: data,
    },
  ],
});
```

Check [this doc](https://docs.ethers.org/v5/api/utils/abi/interface/) for more usages.

## Send Signed Transaction

To send a signed transaction, the user must use another library, like

```typescript
const provider = new Web3.providers.HttpProvider('url for rpc nodes');
const web3 = new Web3(provider);

try {
  const res = await web3.eth.sendSignedTransaction(serializedTx);
  console.log('Result:', res);
} catch (error) {
  console.error('Error:', error);
  return;
}
```

## Switch Ethereum Chain​

Switches the connected wallet to the specified chain ID.&#x20;

```javascript
try {
  await ethereum.request({
    method: 'wallet_switchEthereumChain',
    params: [{ chainId: '0xf00' }],
  });
} catch (switchError) {
  // Handle the error here
  console.error('Error switching Ethereum chain:', switchError);
}
```

## Event Listeners[​](https://docs.uxuy.com/uxuy-connect/guide/#event-listeners) <a href="#event-listeners" id="event-listeners"></a>

The SDK emits events for account and network changes.

### **accountsChanged**[**​**](https://docs.uxuy.com/uxuy-connect/guide/#accountschanged)

```javascript
ethereum.on('accountsChanged', (accounts) => {//error handle };
```

### **chainChanged**[**​**](https://docs.uxuy.com/uxuy-connect/guide/#chainchanged)

```typescript
ethereum.on('chainChanged', (chainId) => {//error handle });
```

To remove listeners:

```javascript
ethereum.removeListener('accountsChanged', handleAccountsChanged);
// or remove all listeners
ethereum.removeAllListeners();
```


# Solana Provider

The Tomo Telegram SDK provides a Solana Provider for querying and sending SOL and SPL tokens.&#x20;

```typescript
// get provider 
const sol = window.tomo_sol;
```

## Connect with the Wallet[​](https://docs.uxuy.com/uxuy-connect/guide/#isconnected) <a href="#isconnected" id="isconnected"></a>

Before using the provider, the user needs to log in to the wallet through the modal by following the method:

```typescript
// connect wallet
await sol?.connectWallet();
```

## Query Methods

Solana providers support two query methods:

* `getAddress`
* `getBalance`

<pre class="language-typescript"><code class="lang-typescript"><strong>const address = sol.getAddress();
</strong>const balance = await sol.getBalance(address);
</code></pre>

## Signing Methods

In Solana providers, we provide four signing methods:

* `signMessage`
* `signTransaction`
* `signTransactions`
* `signTokenTransaction`

### Sign message

`signMessage` the method will create an offchain signature for one message and return the signed transaction in hex.

```typescript
 const response = await sol.signMessage(signMsg);
```

To verify the signature, you need to add the header "\xffsolana offchain" before the \`signMsg\`

### SOL transfer transaction

`signTransaction` is typically used to send SOL to another address and return the signed transaction. You can also use `signTransactions` it to pass an array of transactions for signing.

```typescript
const response = await sol.signTransaction({
  from: 8y9wmwVhban5Mrp8j68fQv1Kceeifeowt5Yw1DjwXoxk,
  to: 646rZ228LDcYecNvoBGNysJ9pGLc7gBeTrnSgZ476rBp,
  value: 0.01,
});
```

### SPL token transaction

and `signTokenTransaction` supports signing transactions for sending SPL tokens. You need to provide a mint address for this transaction.

```typescript
const response = await sol.signTokenTransaction({
  from: '8y9wmwVhban5Mrp8j68fQv1Kceeifeowt5Yw1DjwXoxk',
  to: '646rZ228LDcYecNvoBGNysJ9pGLc7gBeTrnSgZ476rBp',
  value: val,
  chainId: 501,
  contract: 'Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB',
});
```

## Sending Methods

After signing transactions, you can use `sendTransaction` it to send the transaction. The return value is the transaction hash:

```typescript
const res = await sol.sendTransaction(response);
```


# Sui Provider (Beta)

The Tomo Telegram SDK provides the SUI provider for getting addresses, signing, and sending transactions.&#x20;

```typescript
// get provider 
const sui= window.tomo_sui;
```

## Connect with the Wallet[​](https://docs.uxuy.com/uxuy-connect/guide/#isconnected) <a href="#isconnected" id="isconnected"></a>

Before using the provider, the user needs to log in to the wallet through the modal by following the method:

```typescript
// connect wallet
await sui?.connectWallet();
```

## Query Address

You can get the address of the user by one cal

```typescript
const address = sui.getAddress();
```

## Signing Methods

In Solana providers, we provide three signing methods:

* `signMessage`
* `signTransaction`
* `signAndExecuteTransaction`

### Sign message

`signMessage` method will create a simple signed transaction for one message and return the signed transaction in hex.

```typescript
 const response = await sui.signMessage(signMsg);
```

### Sign transaction

`signTransaction` supports signing arbitrary PTB transactions if they are well formed. Please check [this ](https://docs.sui.io/guides/developer/sui-101/building-ptb)for the general construction of transactions. We provide two examples:

<pre class="language-typescript"><code class="lang-typescript"><strong>// define transaction body
</strong><strong>export const getSendSuiCoinTx = async ({
</strong>  fromAddress,
  toAddress,
  amount,
  coinType,
}: {
  fromAddress: string;
  toAddress: string;
  amount: string;
  coinType?: string;
}): Promise&#x3C;{ transaction: string; bytes: Uint8Array } | null> => {
  const suiClient = getSuiClient();
  const txb = new Transaction();
  
  txb.transferObjects(
    [coinWithBalance({ balance: Number(amount), type: coinType || undefined })],
    toAddress
  );
  
  try {
    txb.setSender(fromAddress);
    const transaction = (await txb.toJSON({ client: suiClient })).toString();
    const bytes = await txb.build({ client: suiClient });
    console.log('bytes', transaction, bytes);
    return { transaction, bytes };
  } catch (e) {
    console.warn(e);
    return null;
  }
};

// create transaction body for concrete transaction
const res = await getSendSuiCoinTx({
  fromAddress: addr,
  toAddress: toAddr2,
  amount: +toValue2 * 10 ** 6 + '',
  coinType: contractAddr,
});

// create transaction
const { transaction, bytes } = res || {};

const input = {
  transactionBlock: transaction,
  chain: 'sui:mainnet',
  txBytes: bytes,
  options: {
    showEffects: true,
  },
};

// sign transaction
const signed transaction= await sui.signTransaction(input);

// or you can use sign and send transaction at the same time

const res = await sui.signAndExecuteTransaction(input);
</code></pre>

After signing the transaction, you can send it to your client or add other signatures. In addition, you can use `signAndExecuteTransaction` the method to send the signed transaction directly.


# TON Provider

The Tomo Telegram SDK provides a TON Provider for querying account data and sending transactions.

## Connect with the Wallet[​](https://docs.uxuy.com/uxuy-connect/guide/#isconnected) <a href="#isconnected" id="isconnected"></a>

Before using the provider, the user needs to log in to the wallet through the modal by following the method:

```typescript
// connect wallet
await ton?.connectWallet();
```

We also support connecting through TON proof:

```typescript
// the tonProof must be a hex string
const res = await tomo_ton.connect({
  tonProof: Buffer.from('your challenge', 'utf8').toString('hex'),
});

//At the dapp backend, check the tonProof res
const { tonProof } = res;
```

We also support connecting to the TON testnet as follows:

```typescript
// You must use the Tomo TON provider to connect the testnet.
// Other wallet providers through TON Connect do not work.
const res = await tomo_ton.connect({
  network: 'testnet'
});
```

## Query Methods

TON provider supports two query methods:

* `getAddress`
* `getBalance`

<pre class="language-typescript"><code class="lang-typescript"><strong>const address = ton.getAddress();
</strong><strong>
</strong>const balance = await ton.getBalance(address);
</code></pre>

## Sending Methods

In TON providers, we provide one send methods:

* `sendTransaction`

This method allows signing and sending transactions in one call. The input for this method is `TonTxParams,` defined as the following:

```typescript
export interface TonTxParams {
  valid_until?: number | bigint;
  validUntil?: number | bigint;
  network?: string;
  from?: string;
  messages: {
    address: string;
    amount: string; // nanoTon,  e.g. toNano('0.1').toString()
    stateInit?: string;
    payload?: string;
  }[];
}
// !amount must be nanoTon, 
```

You can construct your payload as a BOC(Bag of Cells) in the same way as the standard one.\
Then, convert it into a **base64 string** or **hexadecimal string** and pass it to `sendTx` method.

```typescript
tomo_ton.sendTransaction(txParam: TonTxParams)
```

### Payload for TON transaction

You can create a general [payload ](https://docs.ton.org/v3/guidelines/ton-connect/guidelines/preparing-messages)using `@ton/core`

```typescript
import { beginCell, toNano, Address } from '@ton/core';
const createPayloadByTonCoreCell = async (tokenAmount, recipientAddress: string) => {
    const destinationAddress = Address.parse(recipientAddress);

    const body = beginCell()
    .storeUint(0xf8a7ea5, 32) // Operation code for transferring
    .storeUint(0, 64) // / Query ID (can be any unique identifier)
    .storeCoins(tokenAmount) // Amount of tokens to send
    .storeAddress(destinationAddress) // destination
    .storeAddress(destinationAddress) // response_destination
    .storeBit(false) // null custom_payload
    .storeCoins(toNano('0.000001'))
    .storeBit(false) // false for empty forward payload
    .endCell();

    return body.toBoc().toString('base64');
};
```

Or `tonweb:`

```typescript
import TonWeb from 'tonweb';
const createPayloadByTonWebCell = async (tokenAmount, recipientAddress) => {
    const tonWeb = new TonWeb(new TonWeb.HttpProvider());
    const cell = new tonWeb.boc.Cell();

    cell.bits.writeUint(0xf8a7ea5, 32); // Operation code for transferring tokens
    cell.bits.writeUint(0, 64); // Query ID (can be any unique identifier)
    cell.bits.writeCoins(tokenAmount); // Amount of tokens to send
    cell.bits.writeAddress(new TonWeb.utils.Address(recipientAddress)); // recipient address
    cell.bits.writeAddress(new TonWeb.utils.Address(recipientAddress)); // response address
    cell.bits.writeBit(false);  // null custom_payload
    cell.bits.writeCoins(TonWeb.utils.toNano('0.0001')); // forwardAmount
    cell.bits.writeBit(false); // empty forward payload

    return Buffer.from(await cell.toBoc()).toString('base64');
};
```

### Payload for Jetton transaction

Below is an example use `JettonWallet` under `tonweb` for transferring jetton:

```typescript
const createJettonTransferPayload = async (
    tokenAmount,
    recipientAddress,
  ) => {
    const tonWeb = new TonWeb(new TonWeb.HttpProvider());
    const jettonWallet = new TonWeb.token.jetton.JettonWallet(
        tonWeb.provider,
        {}
    );
    const transferBody = await jettonWallet.createTransferBody({
        queryId: 0,
        jettonAmount: tokenAmount,
        toAddress: new TonWeb.utils.Address(recipientAddress),
        forwardAmount: TonWeb.utils.toNano('0.0001'),
        responseAddress: new TonWeb.utils.Address(recipientAddress),
    });
    const uint8 = await transferBody.toBoc();
    return Buffer.from(uint8).toString('base64');
};
```


# Tomo APIs

Tomo APIs provide various functions for developers to interact with open market information.&#x20;

### getTokenByName

Retrieves detailed information about the token of a given token name.

**Request Parameters:**

* `tokenName` (string, required): The name of the token to query.&#x20;

```javascript
const tokenDetails = async () => {
  return await fetch('https://apis.tomo.inc/sky/api/socialLogin/teleGram/getByName?tokenName=BTC', {
    method: 'GET'
  }).then(res => res.json());
};
```

### getTokenDetails

Fetches detailed metadata for a token, including its name, symbol, price, and additional information like social links. This is useful for users who want comprehensive data about a particular token.

**Request Parameters:**

* `address` (string, query, required): The contract address of the token.
* `chain` (string, query, required): The blockchain on which the token resides (e.g., "eth" for Ethereum).

**Example Request:**

```javascript
const queryTokenDetails = async () => {
  return await fetch('https://apis.tomo.inc/cloud/v4/memes-overview?address=0x8290333cef9e6d528dd5618fb97a76f268f3edd4&chain=eth', {
    method: 'GET'
  }).then(res => res.json());
};
```

### getAllTokens

Searches and retrieves all tokens available in the market. The result can be big and take time. Developers can cache it locally for operations like different sorting of all tokens.&#x20;

```javascript
const allTokens= async () => {
  return await fetch('https://apis.tomo.inc/sky/api/socialLogin/teleGram/wallet/tokens', {
    method: 'GET'
  }).then(res => res.json());
};
```

### getMainstreamTokens

Fetches detailed information about mainstream tokens like BTC, ETH, SOL, etc.&#x20;

```javascript
const getSelectedTokens = async () => {
  return await fetch('https://apis.tomo.inc/sky/api/socialLogin/teleGram/wallet/selectedTokens', {
    method: 'GET'
  }).then(res => res.json());
};

```

### getTrendingTokens

Fetches the trending tokens based on chain activity and user interactions.

```javascript
const trendingTokens = async () => {
  return await fetch('https://apis.tomo.inc/sky/api/socialLogin/teleGram/wallet/trendingTokens', {
    method: 'GET'
  }).then(res => res.json());
};
```

### searchToken

This API allows users to search for tokens' details in a fuzzy way by providing the keywords in the token name or contract address.

**Request Parameters:**

* `content` (string, query, required): Search keywords such as the address of the token or token name.
* `chain` (string, query, optional): The blockchain network on which the token resides (e.g., Ethereum, BSC). If omitted, it will search across all supported chains.

```javascript
const searchTokens = async () => {
  return await fetch('https://apis.tomo.inc/sky/api/socialLogin/teleGram/wallet/tokens/search?content="&chain=eth', {
    method: 'GET'
  }).then(res => res.json());
};
```

### getOHLCV

Retrieves OHLCV (Open, High, Low, Close, Volume) chart data for a specific token. Used for drawing the K-line of the token.

**Request Parameters:**

* `tokenName` (string, path, required): The name of the token for which the OHLCV data is requested.
* `interval` (string, query, required): The time interval for each OHLCV data point. Possible values include:
  * `minute`
  * `five_minute`
  * `fifteen_minute`
  * `hour`
  * `four_hour`


# Partners

Below are our partners that have already integrated Tomo Telegram SDK. You can experience them with the following TMA bots:

1. AILayer ([@ailayer\_eco\_bot](https://t.me/ailayer_eco_bot))
2. Satori ([@SatoriFinanceBot](https://t.me/SatoriFinanceBot))
3. Catch the Duck ([@catchItGame\_bot](https://t.me/catchItGame_bot))
4. Duckchain ([@DuckChain\_bot](https://t.me/DuckChain_bot))


# Tomo Enterprise SDK


# For Babylon

The Tomo Connect SDK Lite aims to define an easy-to-integrate and highly compatible Blockchain Provider API for dApps. This API allows dApps to easily connect to all kinds of wallets (including extension wallets, hardware wallets, and mobile wallets), retrieve account asset data, and sign messages and transactions (especially Babylon staking related transactions).

## Extension Wallet Integration

If you are a extension wallet provider looking to integrate with Tomo Connect, please refer to the following documentation.

{% content-ref url="/pages/kcqt731nGmcUcsPcwvPO" %}
[Integrate Extension Wallet](/tomo-sdk/tomo-enterprise-sdk/for-babylon/integrate-extension-wallet)
{% endcontent-ref %}

## Mobile Wallet Integration

If you are a mobile wallet provider looking to integrate with Tomo Connect, please refer to the following documentation.

{% content-ref url="/pages/tNWzlx3cbSCart9v7dyL" %}
[Integrate Mobile Wallet](/tomo-sdk/tomo-enterprise-sdk/for-babylon/integrate-mobile-wallet)
{% endcontent-ref %}


# Install the SDK

## Adding the SDK

First, you need to add Tomo Connect SDK in to your project dependency:

```sh
npm install @tomo-inc/wallet-connect-sdk
```

## Adding the Context Provider

Then initialize the UI view and context provider

```javascript
import {
  TomoContextProvider,
  useTomoModalControl,
  useTomoWalletConnect
} from '@tomo-inc/wallet-connect-sdk'

export default function Demo() {
  return (
    <TomoContextProvider
      // optional
      style={{
        rounded: 'medium',
        theme: 'light',
        primaryColor: '#FF7C2A'
      }}
    >
      <ChildComponent />
    </TomoContextProvider>
  )
}

type ChildProps = {
  style: TomoProviderSetting['style']
  setStyle: (v: TomoProviderSetting['style']) => void
}
export function ChildComponent(props: ChildProps) {
  const tomoModal = useTomoModalControl()
  const tomoWalletConnect = useTomoWalletConnect()

  return (
    <div style={{ textAlign: 'right' }}>
      <button
        onClick={async () => {
          await tomoModal.open('connect')
        }}
      >
        Connect Wallet
      </button>
      <button
        onClick={async () => {
          await tomoWalletConnect.disconnect()
        }}
      >
        Disconnect Wallet
      </button>
    </div>
  )
}
```

Using the above code in your dApp, you can easily open Tomo BTC connect modal and interact with the supported Bitcon & Cosmos wallets.&#x20;


# Tomo Wallet Provider

Tomo wallet provider defines the top level functions, which can be used in all the wallet provider implementations, such as Bitcoin provider, Cosmos provider, etc.

```javascript
export abstract class WalletProvider {
  chains: TomoChain[]
  option: ProviderOption
  constructor(option: ProviderOption) {
    this.chains = option.chains
    this.option = option
  }
  /**
   * Connects to the wallet and returns the instance of the wallet provider.
   * @returns A promise that resolves to an instance of the wrapper wallet provider in babylon friendly format.
   * @throws An error if the wallet is not installed or if connection fails.
   */
  abstract connectWallet(): Promise<this>

  /**
   * Gets the address of the connected wallet.
   * @returns A promise that resolves to the address of the connected wallet.
   */
  abstract getAddress(): Promise<string>

  /**
   * Gets the network of the current account.
   * @returns A promise that resolves to the network of the current account.
   */
  abstract getNetwork(): Promise<string>

  /**
   * Gets the name of the wallet provider.
   * @returns Name of the wallet provider.
   */
  abstract getWalletProviderName(): Promise<string>

  /**
   * Gets the icon URL of the wallet provider.
   * @returns Icon URL of the wallet provider.
   */
  abstract getWalletProviderIcon(): Promise<string>
}
```


# Bitcoin Provider

## Using the BTC Provider API

Once you connect the wallet, you can use the following way to interact with the connected wallet:

```javascript
import {
  useTomoProviders,
  useTomoModalControl,
  useTomoWalletConnect,
  useTomoWalletState,
  useWalletList
} from '@tomo-inc/wallet-connect-sdk'

// Open BTC connection modal
const tomoModal = useTomoModalControl();
tomoModal.open("bitcoin"); 
// tomoModal.open('cosmos'); to open Cosmos wallets connection modal

// Check wallet connection status
const tomowalletState = useTomoWalletState();
const connected = tomowalletState.isConnected;

// Check all the supported wallets
const supportedWallets = useWalletList();

// Get provider
const providers = useTomoProviders();
const provider = providers.bitcoinProvider;

// Disconnect
const tomoWalletConnect = useTomoWalletConnect();
tomoWalletConnect.disconnect();
```

All the provider APIs are as follows:

```javascript
export type Fees = {
  // fee for inclusion in the next block
  fastestFee: number
  // fee for inclusion in a block in 30 mins
  halfHourFee: number
  // fee for inclusion in a block in 1 hour
  hourFee: number
  // economy fee: inclusion not guaranteed
  economyFee: number
  // minimum fee: the minimum fee of the network
  minimumFee: number
}

// UTXO is a structure defining attributes for a UTXO
export interface UTXO {
  // hash of transaction that holds the UTXO
  txid: string
  // index of the output in the transaction
  vout: number
  // amount of satoshis the UTXO holds
  value: number
  // the script that the UTXO contains
  scriptPubKey: string
}

// supported networks
export enum Network {
  MAINNET = 'mainnet',
  TESTNET = 'testnet',
  SIGNET = 'signet'
}

export interface InscriptionResult {
  list: Inscription[]
  total: number
}

export interface Inscription {
  output: string
  inscriptionId: string
  address: string
  offset: number
  outputValue: number
  location: string
  contentType: string
  contentLength: number
  inscriptionNumber: number
  timestamp: number
  genesisTransaction: string
}

export abstract class BTCProvider extends WalletProvider {
  abstract connectWallet(): Promise<this>
  abstract getAddress(): Promise<string>
  abstract getPublicKeyHex(): Promise<string>
  abstract signPsbt(psbtHex: string): Promise<string>
  abstract signPsbts(psbtsHexes: string[]): Promise<string[]>
  abstract getNetwork(): Promise<Network>
  abstract signMessage(message: string, type: type: 'ecdsa' | 'bip322-simple'): Promise<string>
  abstract on(eventName: string, callBack: () => void): void
  abstract off(eventName: string, callBack: () => void): void
  abstract switchNetwork(network: Network): Promise<void>
  abstract sendBitcoin(to: string, satAmount: number): Promise<string>
  abstract getNetworkFees(): Promise<Fees>
  abstract pushTx(txHex: string): Promise<string>
  abstract getUtxos(address: string, amount?: number): Promise<UTXO[]>
  abstract getBTCTipHeight(): Promise<number>
  abstract getBalance(): Promise<number>
  abstract getInscriptions(cursor?: number, size?: number): Promise<InscriptionResult>
}

```


# Cosmos Provider

## Using Cosmos wallet provider

Cosmos wallet provider api is as below:

```javascript
import { TomoCosmosInjected, WalletProvider } from from '@tomo-inc/tomo-wallet-provider';
import { AminoSignResponse, BroadcastMode, KeplrSignOptions, StdSignature, StdSignDoc } from '@keplr-wallet/types';
import { OfflineAminoSigner, OfflineDirectSigner } from '@keplr-wallet/types/src/cosmjs';
import { SigningStargateClient } from '@cosmjs/stargate';

export declare class CosmosProvider extends WalletProvider {
    provider: TomoCosmosInjected;
    offlineSigner?: OfflineAminoSigner & OfflineDirectSigner;
    clientPromise?: Promise<SigningStargateClient>;
    constructor(chains: any[], provider: TomoCosmosInjected);
    connectWallet(): Promise<this>;
    /**
     * get @cosmjs/stargate SigningStargateClient
     */
    getSigningStargateClient(): Promise<SigningStargateClient>;
    getBalance(searchDenom: string): Promise<bigint>;
    /**
     * Gets the bech32Address of the connected wallet.
     * @returns A promise that resolves to the address of the connected wallet.
     */
    getAddress(): Promise<string>;
    /**
     * get the chainId of the connected wallet
     */
    getNetwork(): Promise<string>;
    signAmino(signerAddress: string, signDoc: StdSignDoc, signOptions?: KeplrSignOptions): Promise<AminoSignResponse>;
    signArbitrary(signer: string, data: string | Uint8Array): Promise<StdSignature>;
    sendTx(tx: Uint8Array, mode: BroadcastMode): Promise<Uint8Array>;
    getOfflineSigner(): Promise<OfflineAminoSigner & OfflineDirectSigner>;
    getPublicKeyHex(): Promise<string>
}
```

And after connected to wallet, cosmos wallet provider could be used as follows:

```javascript
<TomoContextProvider
  chainTypes={['cosmos', 'bitcoin']} // can be removed, we support both by default
  cosmosChains={[
    {
      id: 2,
      name: 'Cosmos',
      type: 'cosmos',
      network: 'cosmoshub-4'
      backendUrls:{rpcUrl:"your rpc node url"}
    }
  ]}
  providerOptions={{  // optional, support customized window object context
    getWindow() {
      return window.parent
    }
  }}
  ...
>
  <ChildComponent />
</TomoContextProvider>

// after connected, providers could be used
export function ChildComponent(props: ChildProps) {
  const providers = useTomoProviders()

  const signCosmos = async (address: string, amount: string) => {
    const curChainId = providers.cosmosProvider.getChainId()
    const key = await providers.cosmosProvider.provider.getKey(curChainId)  

    // construct your signDoc
    ...
    
    const { signed, signature } = await providers.cosmosProvider.signAmino(
      key.bech32Address,
      signDoc
    )
  }

  return (
    <div>
      <TomoSocial />
    </div>
  )
}
```

## Using customized SigningStargateClient

<pre class="language-javascript"><code class="lang-javascript">const providers = useTomoProviders()

providers.cosmosProvider!.initSigningStargateClient(
    await SigningStargateClient.connectWithSigner(
        rpcUrl,
        providers.cosmosProvider!.offlineSigner!,
        options
<strong>    )
</strong>);
</code></pre>


# Multiple Connection Mode

### Multiple Connection Mode

You can configure `chainTypes`  property of **TomoContextProvider** to support multi-network mode. In this mode, wallets from various networks are accessible through separate tabs, allowing you to select and establish connections with them. Once connected, providers facilitate interactions with these wallets across different networks. Currently, support is extended to both Bitcoin and Cosmos networks.

<figure><img src="/files/zHjpYZfPszrEJopjL9iZ" alt="" width="375"><figcaption><p>Multiple connection mode</p></figcaption></figure>

## Single Wallet Mode

```javascript
<TomoContextProvider
  chainTypes={['bitcoin']} // only show bitcoin wallets
  ...
>
  <ChildComponent />
</TomoContextProvider>
```

## Multiple Wallets Mode

```javascript
<TomoContextProvider
  chainTypes={['cosmos', 'bitcoin']} // show both bitcoin and cosmos wallets
  ...
>
  <ChildComponent />
</TomoContextProvider>
```


# Integrate Extension Wallet

## Wallet Supported

Currently Tomo Connect SDK supports the following BTC wallet:

* OKX Bitcoin
* Unisat
* Tomo Bitcoin
* OneKey Bitcoin
* Bitget Bitcoin
* Keystone Bitcoin
* Cactus Link
* imToken Mobile Wallet (Mobile)
* Binance Web3 Wallet (Mobile)

And supports the following Cosmos wallet:

* Keplr
* Okx Cosmos
* Cosmostation
* Leap
* OneKey Cosmos
* Station

It is very easy to sort the wallets supported, and you can sort the wallet list, enable or disable it by the following config, customized wallet could be added to the list as well:

<pre class="language-javascript"><code class="lang-javascript"><strong>&#x3C;TomoContextProvider
</strong>  indexWallets={[
    "bitcoin_tomo_auto", // injectable bitcoin mobile wallet
    "cosmos_tomo_auto", // injectable cosmos mobile wallet
    "bitcoin_okx",
    "bitcoin_unisat",
    "bitcoin_tomo",
    "bitcoin_onekey",
    "bitcoin_bitget",
    "bitcoin_cactuslink",
    "bitcoin_imtoken", // injectable imtoken mobile wallet
    "bitcoin_binance", // injectable binance mobile wallet
    "bitcoin_keystone"
    "cosmos_keplr",
    "cosmos_okx",
    "cosmos_cosmostation",
    "cosmos_leap",
    "cosmos_onekey",
    "cosmos_station",
    'xyz',
    'abc'
  ]}
  // You can also customize wallets that don't include in the default list
  additionalWallets={[
    {
      id: 'xyz',
      name: 'XYZ BTC Wallet',
      chainType: 'bitcoin',
      connectProvider: XYZWallet, // XYZWallet should extends BTCProvider
      type: 'extension',
      img: 'https://your wallet logo.svg'
    }, {
      id: 'abc',
      name: 'ABC Cosmos Wallet',
      chainType: 'cosmos',
      connectProvider: ABCWallet, // ABCWallet should extends CosmosProvider
      type: 'extension',
      img: 'https://your wallet logo.svg'
    },
  ]}
  >
&#x3C;/TomoContextProvider>
</code></pre>

When wallet is selected, connection hints will pop up, and the content of the hints could be customized by option 'connectionHints', it could be used as below:

```javascript
<TomoContextProvider
  connectionHints={[
    {
      text: 'Subject to Developer’s compliance with the terms and conditions of this Agreement',
      logo: (
        <img className={'tm-size-5'} src={'https://tomo.inc/favicon.ico'} />
      )
    },
    {
      text: 'I certify that there are no Bitcoin inscriptions tokens in my wallet.'
    },
    {
      isRequired: true,
      text: (
        <span>
          I certify that I have read and accept the updated{' '}
          <a className={'tm-text-primary'}>Terms of Use</a> and{' '}
          <a className={'tm-text-primary'}>Privacy Policy</a>.
        </span>
      )
    }
  ]}
>
  {children}
</TomoContextProvider>
```

## Customize Chain RPC

Customize chain's RPC is possible and it could be done as below:

```javascript
import { tomoBitcoin } from "@tomo-inc/wallet-connect-sdk";

<TomoContextProvider
  chainTypes={['cosmos', 'bitcoin']}
  cosmosChains={[
    {
      id: 2,
      name: 'Cosmos',
      type: 'cosmos',
      network: 'cosmoshub-4',
      modularData: any, // Optional, if current wallet doesn't support this cosmos chain, the sdk will ask the wallet to add support for it.
      backendUrls: {
        rpcUrl: 'https://dark-palpable-bird.cosmos-mainnet.quiknode.pro/xxxxapi_key'
      }
    }
  ]}
  bitcoinChains={[
    {
      ...tomoBitcoin,
      backendUrls: {
        mempoolUrl: 'https://your.mempool.space/api',
        inscriptionUrl: 'https://your.inscription.service/api' // used by inscription feature
      }
    }
  ]}
  ...
>
  <ChildComponent />
</TomoContextProvider>
```

For the above mempool API request and response format, please refer to <https://mempool.space/docs/api/rest>

If you want to support your own Bitcoin wallet into the wallet list, there are two ways described as above.


# Submit Wallet PR

## Submit Wallet PR

Submit a PR to <https://github.com/UnyxTech/tomo-wallet-provider>

The example PR can be found [here](https://github.com/UnyxTech/tomo-wallet-provider/commit/e051ca4d21c1bb8c91f9f5d7ee0a09958e46b15f)

## Implement Your BTC Provider&#x20;

```javascript
import {
  Network,
  WalletInfo,
  BTCProvider
} from '@tomo-inc/tomo-wallet-provider'
import { parseUnits } from '@tomo-inc/tomo-wallet-provider'

export const xyzProvider = 'xyz'

export class XYZWallet extends BTCProvider {
  private xyzWalletInfo: WalletInfo | undefined
  private bitcoinNetworkProvider: any

  constructor() {
    super()
    if (!window[xyzProvider]) {
      throw new Error('XYZ Wallet extension not found')
    }

    this.bitcoinNetworkProvider = window[xyzProvider]
  }

  connectWallet = async (): Promise<this> => {
    const workingVersion = '1.0.0'
    if (!this.bitcoinNetworkProvider) {
      throw new Error('XYZ Wallet extension not found')
    }
    if (this.bitcoinNetworkProvider.getVersion) {
      const version = await this.bitcoinNetworkProvider.getVersion()
      if (version < workingVersion) {
        throw new Error('Please update XYZ Wallet to the latest version')
      }
    }

    let addresses = null
    let pubKey = null
    try {
      addresses = await this.bitcoinNetworkProvider.connectWallet()
      pubKey = await this.bitcoinNetworkProvider.getPublicKey()
      if (!addresses || addresses.length === 0 || !pubKey) {
        throw new Error('BTC is not enabled in XYZ Wallet')
      }
    } catch (error) {
      throw new Error('BTC is not enabled in XYZ Wallet')
    }
    
    this.xyzWalletInfo = {
      publicKeyHex: pubKey,
      address: addresses[0]
    }
    return this
  }

  getWalletProviderName = async (): Promise<string> => {
    return 'XYZ'
  }

  getAddress = async (): Promise<string> => {
    return (await this.bitcoinNetworkProvider.getAccounts())[0]
  }

  getPublicKeyHex = async (): Promise<string> => {
    if (!this.xyzWalletInfo) {
      throw new Error('XYZ Wallet not connected')
    }
    return this.xyzWalletInfo.publicKeyHex
  }

  signPsbt = async (psbtHex: string): Promise<string> => {
    if (!this.xyzWalletInfo) {
      throw new Error('XYZ Wallet not connected')
    }
    return await this.bitcoinNetworkProvider.signPsbt(psbtHex)
  }

  signPsbts = async (psbtsHexes: string[]): Promise<string[]> => {
    if (!this.xyzWalletInfo) {
      throw new Error('XYZ Wallet not connected')
    }
    return await this.bitcoinNetworkProvider.signPsbts(psbtsHexes)
  }

  signMessage = async (message: string, type: 'ecdsa' | 'bip322-simple' = 'ecdsa'): Promise<string> => {
    if (!this.xyzWalletInfo) {
      throw new Error('XYZ Wallet not connected')
    }
    return await this.bitcoinNetworkProvider.signMessage(
      message,
      type
    )
  }

  getNetwork = async (): Promise<Network> => {
    return await this.bitcoinNetworkProvider.getNetwork()
  }

  on = (eventName: string, callBack: () => void) => {
    return this.bitcoinNetworkProvider.on(eventName, callBack)
  }

  off = (eventName: string, callBack: () => void) => {
    return this.bitcoinNetworkProvider.off(eventName, callBack)
  }

  getBalance = async (): Promise<number> => {
    const result = await this.bitcoinNetworkProvider.getBalance()
    return result
  }

  pushTx = async (txHex: string): Promise<string> => {
    return await this.bitcoinNetworkProvider.pushTx(txHex)
  }

  async switchNetwork(network: Network) {
    return await this.bitcoinNetworkProvider.switchNetwork(network)
  }

  async sendBitcoin(to: string, satAmount: number) {
    const result = await this.bitcoinNetworkProvider.sendBitcoin(
      to,
      Number(parseUnits(satAmount.toString(), 8))
    )
    return result
  }
}
```

Then you can use it in the wallet context provider

```javascript
<TomoContextProvider
  additionalWallets={[
    {
      id: 'xyz',
      name: 'XYZ BTC Wallet',
      chainType: 'bitcoin',
      connectProvider: XYZWallet, // XYZWallet should extends BTCProvider
      type: 'extension',
      img: 'https://your wallet logo.svg'
    }, {
      id: 'abc',
      name: 'ABC Cosmos Wallet',
      chainType: 'cosmos',
      connectProvider: ABCWallet, // ABCWallet should extends CosmosProvider
      type: 'extension',
      img: 'https://your wallet logo.svg'
    },
  ]}
>
</TomoContextProvider>
```

Submitting a PR makes it more universal, allowing other projects that have integrated Tomo Connect Lite to automatically support your wallet.


# Extend the SDK

Besides, users can also customize their own wallet provider in an easier way. The `BTCProvider` class provides default implementations for most Bitcoin interfaces. What users need to do is compare the interfaces of the target wallet with the default implementations of `BTCProvider`. The `CosmosProvider` class provides default implementations for most Cosmos interfaces. What users need to do is compare the interfaces of the target wallet with the default implementations of `CosmosProvider`.&#x20;

```javascript
import {
  BTCProvider,
  CosmosProvider,
  TomoChain
} from '@tomo-inc/tomo-wallet-provider'

class XYZWallet extends BTCProvider {
  constructor(chains: TomoChain[]) {
    // @ts-ignore
    const bitcoinNetworkProvider = window?.xyzWallet

    if (!bitcoinNetworkProvider) {
      throw new Error('XYZ Wallet not found')
    }
    super(chains, bitcoinNetworkProvider)
  }

  connectWallet = async (): Promise<this> => {
    const accounts = await this.bitcoinNetworkProvider?.requestAccounts()

    const address = accounts[0]
    const publicKeyHex = await this.getPublicKeyHex()

    if (!address || !publicKeyHex) {
      throw new Error('Could not connect to XYZ Wallet')
    }
    return this
  }
}

class ABCWallet extends CosmosProvider {
  constructor(chains: TomoChain[]) {
    // @ts-ignore
    const cosmosProvider = window?.abcCosmos

    if (!cosmosProvider) {
      throw new Error('ABC Wallet not found')
    }
    super(chains, cosmosProvider)
  }
}
```

Then you can use it in the wallet context provider

```javascript
<TomoContextProvider
  additionalWallets={[
    {
      id: 'xyz',
      name: 'XYZ BTC Wallet',
      chainType: 'bitcoin',
      connectProvider: XYZWallet, // XYZWallet should extends BTCProvider
      type: 'extension',
      img: 'https://your wallet logo.svg'
    }, {
      id: 'abc',
      name: 'ABC Cosmos Wallet',
      chainType: 'cosmos',
      connectProvider: ABCWallet, // ABCWallet should extends CosmosProvider
      type: 'extension',
      img: 'https://your wallet logo.svg'
    },
  ]}
>
</TomoContextProvider>
```


# Q & A

Some wallets may have conflicts when using Tomo Connect SDK Lite, thats because they injected conflicted providers into window object.

* OneKey Bitcoin wallet conflicts with Keplr wallet
* Bitget Bitcoin wallet conflicts with Keplr wallet

More details are:

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

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


# Integrate Mobile Wallet

## Mobile Wallet Support

A third-party mobile wallet can easily inject the following object into window object to support all dApps that use the Tomo Connect SDK.

```javascript
export type InjectedTomo = {
  info: {
    name: string
    logo: string
  }
  cosmos?: TomoCosmosInjected
  bitcoin?: TomoBitcoinInjected
}

export type TomoBitcoinInjected =  {
  // connect
  requestAccounts: () => Promise<string[]>
  getAccounts: () => Promise<string[]>
  getPublicKey: () => Promise<string>
  signPsbt: (psbtHex: string) => Promise<string>
  signPsbts: (psbtsHexes: string[]) => Promise<string[]>
  getNetwork: () => Promise<Network>
  signMessage: (message: string, type: 'bip322-simple') => Promise<string>
  switchNetwork: (network: Network) => Promise<void>
  sendBitcoin: (to: string, amount: number) => Promise<string>
  pushTx?: (txHex: string) => Promise<string>
  getBalance?: (address: string) => Promise<number>
  getInscriptions?: (
    cursor?: number,
    size?: number
  ) => Promise<InscriptionResult[]>
  on?: (eventName: string, callBack: () => void) => void
  off?: (eventName: string, callBack: () => void) => void
}
```

For TomoCosmosInjected, please refer to the [Keplr](https://www.npmjs.com/package/@keplr-wallet/types?activeTab=code).

If your wallet already supports Bitcoin and Cosmos, you can simply use:

```javascript
window.injectedTomo = {
  info: {
    name: 'XYZ Wallet',
    logo: 'https://your.website/wallet.png'
  },
  bitcoin: window.yourBitcoin,
  cosmos: window.yourCosmos
}
```


# Supported Chains

Currently, Tomo SDKs support EVM chains, Solana, Sui (Coming soon), and TON (Telegram SDK only).

For EVM chains, the built-in supported chains are:

* AILayer
* Arbitrum
* Avalanche
* B3
* BNB Chain
* Base
* Bitlayer
* Blast
* Corn
* DuckChain Mainnet
* Ethereum
* Gravity
* Merlin
* Neo X
* Optimism
* Polygon
* Scroll
* Worldchain
* opBNB
* zkSync Era

Some Testnet are also available for development

* Berachain bArtio&#x20;
* Botanix Testnet
* DuckChain Testnet
* Story Odyssey Testnet
* Ton Testnet


# Tomo Wallets

Tomo wallet is an all-in-one Web3 social wallet that helps users safely connect and preserve their digital assets with their keys. Tomo Wallet provided seamless and secure access to numerous blockchain networks like Bitcoin, Ethereum, Solana, Cosmos, BNB Chain, Linea, Blast, Polygon, Scroll, Optimism, Arbitrum, Avalanche, Base, Mantle, B², Merlin, Bounce, Bitlayer, Satoshi, Bitcoin Layer 2, Bob, and MAP Protocol. Tomo wallet provides an advanced, decentralized key management solution to construct a secure multiparty computation (MPC) wallet.&#x20;

### Install Tomo Wallet

* [Chrome Extension Wallet](https://chromewebstore.google.com/detail/tomo-wallet/pfccjkejcgoppjnllalolplgogenfojk)
* [iOS App](https://apps.apple.com/us/app/tomo-inc/id6468010287) // [Android App](https://play.google.com/store/apps/details?id=tomo.app.unyx\&pli=1)

### Multi-Chain Asset Management

Our wallet will support Ethereum Virtual Machine (EVM) compatible chains, Bitcoin (BTC), Solana, BNB Smart Chain, Cosmos, and more in the future. This support ensures users can manage all supported digital assets from one convenient place. Designed for both beginners and experienced users, it features an intuitive user interface and robust security, ensuring your assets are always protected.

### **Multi-Dimensional Candlestick Charts**&#x20;

By integrating advanced TradingView charts (e.g., [BTC/USDT](https://www.tradingview.com/symbols/BTCUSDT/)), we offer real-time candlestick chart support, accurately aggregating global prices and featuring popular indicators to help users efficiently monitor market trends.

### Bitcoin Ecosystem Integrations

With upcoming integrations in the Bitcoin ecosystem, Tomo Wallet will revolutionize how you interact with and benefit from Bitcoin.&#x20;

### Social Login Features

Tomo Wallet allows social login features, namely access with a Google Account or an email.

### dApp Integration

dApps on the supported blockchain can connect to the Tomo wallet using an SDK. A User can authorize transactions and interactions seamlessly within the dApp environment, balancing user experience and on-chain security.

### Where is Tomo Wallet Available?

Available as both Tomo mobile app and browser extension, Tomo Wallet ensures access to your assets anytime, anywhere.


# Mobile Wallet


# Tomo Keys

Evolving from Likes to Social Capital

### Tomo Builds a Transparent Market for Social Capital:

* Keys allow you to fairly price and monetize your attention and network. 
* Keys are a solution against spam and ingenuine requests. 
* Keys remove a need for middlemen to facilitate new connections. 
* Keys enable users to engage in transparent and financially rewarding interactions.

<mark style="color:purple;">**In a digital age, your social capital is as valuable as your financial assets.**</mark>&#x20;

***

### What are Keys?

Keys provide exclusive access to creators' content, direct messages, and group chat with key holders.

Users can buy (sell) keys to gain (give up) exclusive access.

#### Royalty Fees

* Every buy/sell transaction includes a 10% royalty fee.
* Of this, a 5% fee goes to the platform.
* The remaining 5% goes directly to the creator’s balance.

***

### What are Votes?

Even if a creator hasn't yet joined Tomo, users can purchase the creator's votes. These Votes are then converted into keys when the creator registers on the platform.

#### Royalty Fees

* Every buy/sell transaction includes a 10% royalty fee.
* Of this, a 5% fee goes to the platform.
* The remaining 5% is reserved for the creator, who can claim it upon joining.&#x20;
* If the creator did not join within 6 months after the first purchase, the platform's 5% fees are redistributed to the voters. The 5% reserved for the creator remains set aside indefinitely until they join and claim it.


# Bonding Curve Explained

### The Bonding Curve Mechanism

Prices for keys/votes follow a distinct bonding curve, which means prices increase when users buy more keys/votes and decrease when they sell them.

Tomo's bonding curve was designed to benefit early supporters. This mechanism allows users to anticipate pricing impact and ensures there is always sufficient liquidity within the platform, as users trade against smart contracts instead of traditional order books.&#x20;

* **Bonding Curve's Function =>** *f(price) = (supply^2)/43370.*
* **Price** refers to the current ETH rate at which user can purchase the next key/vote.
* **Supply** refers to the outstanding amount of keys/votes that holders currently own.
* **Example calculation =>** for the supply of 209 keys/votes, price equals 1.0072 ETH.

<figure><img src="/files/55RkZ9w0l4L0c9kenwDe" alt=""><figcaption><p>          Visualization - Tomo's Bonding Curve</p></figcaption></figure>

<br>


# How to: Tomo Keys

### How to: Buy Keys & Votes

1. Open [pro.tomo.inc](https://pro.tomo.inc) or Tomo mobile app
2. Open the Keys tab and explore the keys (you can sort based on price/volume)
3. Choose a key you like the most, and press continue.

<div align="left"><figure><img src="/files/jvvgthLSjnKzye2EHya8" alt="" width="375"><figcaption></figcaption></figure></div>


# Tomo Launchpad

ERC-404 Launchpad for Memes and Art

### Tomoji is an ERC-404 Meme & Art Launchpad on Base

Tomoji Launchpad addresses the technical complexity of creating a new token, which limits creative expression for many individuals. With Tomoji, users can create their own ERC-404 collections by choosing a picture, name, supply, and mint price, while the smart contract is automatically generated. Half of the tokens are locked in liquidity pools, ensuring market stability. Open minting facilitates fair distribution.&#x20;

### ERC-404 Tokens

The ERC-404 token standard merges the unique qualities of NFTs (ERC-721) with the liquidity of ERC20 tokens, making it ideal for launching art and meme collections. It introduces fractional ownership, allowing more people to own parts of a digital asset. This increases participation and improves trading flexibility compared to traditional NFTs.

Tokens can be traded on Uniswap and listed as NFTs on Opensea and OKX.

### Interactive Utility Within Tomo

In addition to their value as digital collectibles, tokens have a practical function within the Tomo app, serving as emojis. They can be used as an interactive way to respond to stories, adding an enjoyable and interactive layer to the app experience. Tomojis can also be sent as gifts or tips during chats, reflecting their monetary value. This feature introduces an element of fun and interaction and allows for earning opportunities and the transfer of value in a meaningful way.


# Managing your Tomoji NFT

*Here, we explore how ERC-404 works and the important considerations for managing these assets, especially when it comes to transferring tokens and retaining linked NFTs.*

### The Relationship Between $LONG Tokens and LONG NFTs

Contrary to what some might assume, there is no direct one-to-one correspondence between $LONG tokens (ERC20) and LONG NFTs (Non-Fungible Tokens). Instead, their <mark style="color:purple;">**relationship is managed under a "First In, First Out" (FIFO) mechanism orchestrated by the Tomoji smart contracts**</mark><mark style="color:purple;">.</mark> This approach dictates the outcomes for receiving and sending the NFTs.

#### **Ownership:**&#x20;

* A whole ERC20 $LONG token in your wallet = LONG NFT in your wallet
* A fraction of ERC20 $LONG token in your wallet = no ownership of LONG NFT
* A new NFT will be minted upon stacking a whole $LONG token in the wallet.

#### **Transferring:**&#x20;

* Transferring a whole ERC20 $LONG token = transferring one LONG NFT
* Transferring a fractional amount will burn the NFT,&#x20;
* A new NFT will be minted upon stacking a whole $LONG token in the wallet.

### Case Study 1: The Impact of Transferring $LONG

#### **Consider a hypothetical scenario:**

* Total $LONG supply of 4 tokens<br>
* Alice owns 2 $LONG tokens and 2 LONG NFTs labeled ID=1 and ID=2.
* Bob owns 2 $LONG tokens and 2 LONG NFTs labeled ID=3 and ID=4.
* John has zero balance.<br>
* Alice transfers 0.5 $LONG to John, which will burn her ID=1 LONG NFT (assuming ID=1 arrived in her wallet before ID=2).
* Subsequently, Bob transfers 0.5 $LONG to John. Similar to Alice's transaction, this results in the burning of his ID=3 LONG NFT (assuming ID=3 arrived before ID=4).<br>
* As a result of the above transactions, John accumulates 1 $LONG token and receives a LONG NFT.
* Due to the "First In, First Out" rule, John received an NFT labeled ID=1 because ID=1 was burned earlier than ID=2. Next, when someone stacks another whole $LONG token, they will receive an NFT labeled ID=2.

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

### Case Study 2: Changing your LONG NFT

#### **Want another LONG NFT to replace the one you currently have?**

1. Send 0.5 $LONG (ERC20) to another wallet that belongs to you. This will initiate a burn of your existing NFT on your initial wallet.&#x20;
2. Send 0.5 $LONG (ERC20) back to your initial wallet. A new NFT will be minted in your wallet.

<figure><img src="/files/22OlSGSzKJXAnK4EvRwT" alt=""><figcaption></figcaption></figure>

### Important Reminder for NFT Reveal Events

Holders of $LONG tokens and LONG NFTs must understand that transferring any portion of their $LONG tokens could lead to the burning of their NFTs. As these events can significantly affect the value and composition of their digital assets, awareness and careful management are essential. <mark style="color:purple;">**Holders need to ensure they transfer the entire NFT rather than just the tokens if they wish to retain their pictorial representations.**</mark>

<br>


# How to: Tomoji

### **Creating a new Tomoji**

*<mark style="color:purple;">Creating new ERC-404 tokens is only available via web version</mark>* [*<mark style="color:purple;">pro.tomo.inc</mark>*](https://pro.tomo.inc)

1. Open the Tomoji tab and navigate to Create.
2. Choose a name, description, and max supply.
3. Choose the initial sale price.
4. Upload an image of your Tomoji (preferably in square format).
5. When uploaded, press Confirm and Create.

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

### **Minting an existing Tomoji**

1. Open the Tomoji tab and navigate to Launchpad.
2. Explore the Tomojis and pick the one you would like to mint.
3. Press Mint, choose the amount, and press Continue.
4. Check the costs involved and press Confirm.

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

### **Buying a Tomoji**

1. Open the Tomoji tab and navigate to Trading.
2. Explore the Tomojis and pick the one you would like to buy.
3. Press Buy and choose the quantity.
4. Check the costs involved and press Confirm.

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


# TomoID

Link-In-Bio Tool with Permissionless Affiliate Capabilities

TomoID is a multifunctional social wallet designed for social media users, content creators and businesses, combining a link-in-bio tool with referral capabilities and direct monetization. Users can place their unique TomoID in their social media bios, linking to a page with their profiles across all social platforms.&#x20;

A key feature is its affiliate program, which enables creators to earn crypto commissions from referrals and helps businesses attract new users. Commissions from purchases via TomoID go directly to the user's Tomo Wallet, aiding in monetizing online presence and managing affiliates.

***


# How to: TomoID

## Creating TomoID

1. Download the [<mark style="color:blue;">IOS</mark>](https://apps.apple.com/us/app/tomo-inc/id6468010287) or [<mark style="color:blue;">Android</mark>](https://play.google.com/store/apps/details?id=tomo.app.unyx) app and sign up for Tomo.
2. Open the TomoID tab; here, you can manage your TomoID page.
3. Add links to your social media as well as custom links with descriptions.
4. Edit your TomoID link the way you like it.
5. Now, you can preview and share or copy your TomoID link.&#x20;

<div align="left"><figure><img src="/files/8keopgMUk9fjyOrnvXGk" alt="" width="563"><figcaption></figcaption></figure></div>


# How to: Connect Instagram

### Connecting Your Instagram

1. Go to the \[Profile] page -> \[Setting] in the top right corner.

<div align="left"><figure><img src="/files/KWJhaqhNtGXEpXG4ox96" alt="" width="172"><figcaption></figcaption></figure></div>

2. \[Connect Instagram] -> \[Copy IG code] -> \[Go to Tomo’s official IG].

<div align="left"><figure><img src="/files/rcqwGSWx9wzPmibxBlPC" alt="" width="375"><figcaption></figcaption></figure></div>

3. Send the code (DM) to Tomo’s official IG account.
4. And you are all set with IG-Key appearing on your profile.

#### **The Tomo profile page IG connected will serve as a pass to Tomo events.** ![](/files/zWIt2hA1Ga9RGwhKIfHi)


# Extension Wallet


# Developer Manual

[Tomo Extension Wallet ](https://chromewebstore.google.com/detail/tomo-wallet/pfccjkejcgoppjnllalolplgogenfojk)is a multi-chain social wallet for the BTC ecosystem. It enhances your decentralized trading experience and supports numerous chains, emphasizing the Bitcoin ecosystem, including Bitcoin PoW and Bitcoin L2s. The wallet also supports Ethereum, Base, Linea, Optimism, Arbitrum, BNB, and Cosmos chains, with more coming soon. Designed for both beginners and experienced users, it features an intuitive user interface and robust security, ensuring your assets are always protected. With Tomo Wallet, you can manage assets across multiple chains. Users can easily log in using your email, thanks to the easy social login feature. The wallet utilizes Multi-Party Computation (MPC) technology to encrypt seed phrases, storing them in a sharded manner across multiple points, including your local environment and cloud storage. The interface is simple and intuitive for all users, making it user-friendly.

Currently Tomo extension wallet support the following chains:

* EVM chains, such as Ethereum, Linea, Arbitrum, Base, Optimism, and BNB Smart chain. Users can add any EVM compatible chain into the wallet easily.
* Bitcoin chains, it supports Bitcoin mainnet, signet and testnet, and Bitcoin assets such as BRC20 tokens.
* Cosmos chains
* And more to come soon...

This document shows how dApps integrates with Tomo extension wallet.


# EVM Integration

Tomo Extension Wallet injects `tomo_evm` into the window object in your browser. dApp can easily interact with the wallet via `window.tomo_evm`. The following demo code shows how it works:

```javascript
const example = async () => {
    // connect to tomo wallet and get accounts
    const accounts = await window.tomo_evm.request({ method: 'eth_requestAccounts' })
    
    // the first account is the selected account
    const account = accounts[0]
        
    // get chain id
    const chainId = await window.tomo_evm.request({ method: 'eth_chainId' });
    
    const txParams = {
        nonce: '0x0',
        gasPrice: '0x3e95ba80', // set by user from dApp
        gas: '0x2710', // set by user from dApp
        to: '0x0000000000000000000000000000000000000000',
        from: account,
        value: '0x2386f26fc10000',
        chainId: chainId,
    };
    
    const txHash = await window.tomo_evm.request({
      method: 'eth_sendTransaction',
      params: [txParams],
    });
}

const handleAccountsChanged = async (accounts) => {
    // do something when account changed
}

window.tomo_evm.on('accountsChanged', handleAccountsChanged);

const handleChainChanged = async (chainId) => {
    // do something when chain changed
}
window.tomo_evm.on('chainChanged', handleChainChanged)
```

Tomo extension wallet support the following standard JSON-RPC API:

* eth\_requestAccounts
* eth\_accounts
* wallet\_addEthereumChain
* wallet\_switchEthereumChain
* wallet\_watchAsset
* eth\_sign
* personal\_sign
* eth\_signTypedData\_v4
* eth\_chainId
* eth\_gasPrice
* eth\_getBalance
* eth\_call
* eth\_sendTransaction
* ...


# Bitcoin Integration

Tomo Extension Wallet injects `tomo_btc` into the window object in your browser. dApp can easily interact with the wallet via `window.tomo_btc`. The following demo code shows how it works:

```javascript
const example = async () => {
    // connect to tomo wallet and get accounts
    const accounts = await window.tomo_btc.requestAccounts()
    
    // the first account is the selected account
    const account = accounts[0]
        
    const signature = await window.tomo_btc.signMessage('Hello Tomo', 'bip322-simple')
    // do something about the signature
}
```

Tomo extension wallet follows the [wallet adaptor interface](https://github.com/babylonchain/simple-staking/blob/main/src/utils/wallet/wallet_provider.ts) defined by [Babylon](https://babylonchain.io/) chain. Any Bitcoin ecosystem dApps can use the following Tomo implementation.

```javascript
import { WalletProvider, Network, Fees, UTXO, WalletInfo } from "./wallet_provider";
import {
  getAddressBalance,
  getTipHeight,
  getFundingUTXOs,
  getNetworkFees,
  pushTx
} from "../mempool_api";

export class TOMOWallet extends WalletProvider {
  private tomoWalletInfo: WalletInfo | undefined;

  constructor() {
    super();
  }

  connectWallet = async (): Promise<this> => {
    const workingVersion = "1.1.1";
    if (!window.tomo_btc) {
      throw new Error("Tomo extension wallet not found");
    }

    const tomowallet = window.tomo_btc;
    let result = null;
    try {
      result = await tomowallet?.requestAccounts();
    } catch (error) {
      throw new Error("Bitcoin is not enabled in Tomo wallet");
    }

    let compressedPublicKey = null;
    try {
      compressedPublicKey = await tomowallet?.getPublicKey();
    } catch (error) {
      throw new Error("Bitcoin is not enabled in Tomo wallet");
    }

    if (compressedPublicKey && result[0]) {
      this.tomoWalletInfo = {
        publicKeyHex: compressedPublicKey,
        address: result[0],
      };
      return this;
    } else {
      throw new Error("Failed to connect to Tomo wallet");
    }
  };

  getWalletProviderName = async (): Promise<string> => {
    return "Tomo";
  };

  getAddress = async (): Promise<string> => {
    if (!this.tomoWalletInfo) {
      throw new Error("Tomo wallet not connected");
    }
    return this.tomoWalletInfo.address;
  };

  getPublicKeyHex = async (): Promise<string> => {
    if (!this.tomoWalletInfo) {
      throw new Error("Tomo wallet not connected");
    }
    return this.tomoWalletInfo.publicKeyHex;
  };

  signPsbt = async (psbtHex: string): Promise<string> => {
    if (!this.tomoWalletInfo) {
      throw new Error("Tomo wallet not connected");
    }
    return await window?.tomo_btc?.signPsbt(psbtHex);
  };

  signPsbts = async (psbtsHexes: string[]): Promise<string[]> => {
    if (!this.tomoWalletInfo) {
      throw new Error("Tomo wallet not connected");
    }
    return await window?.tomo_btc?.signPsbts(psbtsHexes);
  };

  signMessageBIP322 = async (message: string): Promise<string> => {
    if (!this.tomoWalletInfo) {
      throw new Error("TOMO Wallet not connected");
    }
    return await window?.tomo_btc?.signMessage(
      message,
      "bip322-simple",
    );
  };

  getNetwork = async (): Promise<Network> => {
    return "testnet";
  };

  on = (eventName: string, callBack: () => void) => {
    if (!this.tomoWalletInfo) {
      throw new Error("TOMO Wallet not connected");
    }
    if (eventName === "accountChanged") {
      return window.tomo_btc.on(eventName, callBack);
    }
  };

  getBalance = async (): Promise<number> => {
    return await getAddressBalance(await this.getAddress());
  };

  getNetworkFees = async (): Promise<Fees> => {
    return await getNetworkFees();
  };

  pushTx = async (txHex: string): Promise<string> => {
    return await pushTx(txHex);
  };

  getUtxos = async (address: string, amount: number): Promise<UTXO[]> => {
    return await getFundingUTXOs(address, amount);
  };

  getBTCTipHeight = async (): Promise<number> => {
    return await getTipHeight();
  };
}
```

## Address Type

Tomo extension wallet supports the following Bitcoin wallet type:

* Legacy (P2PKH)
* Nested SegWit (P2SH)
* Native SegWit (P2WPKH)
* Taproot (P2TR)

## Message Signing

Tomo extension wallet support the ECDSA signature of the above four wallet types.

## PSBT Signing

Tomo extension wallet supports the PSBT signing of the following wallet types:

* Nested SegWit (P2SH)
* Native SegWit (P2WPKH)
* Taproot (P2TR)


# Example of User Flows

This section provides an example of the user flow for using the Tomo extension wallet to stake BTC for Babylon.


# Claiming Signet BTC

### 1. Switch your Tomo Wallet to Bitcoin Signet

* Open network selection (top right corner)
* Choose Bitcoin Signet in the Testnet tab

<figure><img src="/files/rBPXlPdcKhGDdhiDIQMm" alt="" width="563"><figcaption></figcaption></figure>

### 2. Connect your Tomo Wallet to [Tomo Faucet](https://faucet.tomo.inc/)

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

### 3. Press Send to claim Signet BTC on [Tomo Faucet](https://faucet.tomo.inc/)

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


# Staking at Testnet

### 1. Switch your Tomo Wallet to Bitcoin Signet

* Open network selection (top right corner)
* Choose Bitcoin Signet in the Testnet tab

<figure><img src="/files/rBPXlPdcKhGDdhiDIQMm" alt="" width="563"><figcaption></figcaption></figure>

### 2. Connect Your Tomo Wallet to Babylon's Page

* Navigate to Connect Wallet on Babylon's page
* Choose Tomo Wallet and press Connect

<figure><img src="/files/7em1PmRfh8fH2UOhcxdA" alt="" width="375"><figcaption></figcaption></figure>

### 3. Stake Your Signet BTC

* IMPORTANT: Wait before your balance on the Babylon page is updated
* Choose the finality provider you like&#x20;
* Enter Signet BTC Amount of 0.0005 and press Preview

<figure><img src="/files/PGxugLqy0RvHs5682JJo" alt="" width="563"><figcaption></figcaption></figure>

*Please note that the BTC balance displayed on the Babylon staking dApp represents the total amount of available UTXOs, whereas the Tomo wallet shows the balance of all UTXOs, including unconfirmed ones. Therefore, the wallet balance might be larger than what is shown on the staking dApp.*

* Review the details in the preview window, and press Stake.

<figure><img src="/files/cXIULxs7z6mOGJODvZTf" alt="" width="563"><figcaption></figcaption></figure>

* You can see the transaction status in Staking History on Babylon's page.

<figure><img src="/files/fS0NkcT70CoqQsJf2QwX" alt="" width="563"><figcaption></figcaption></figure>


# Telegram Wallet

Tomo Telegram wallet is one of Tomo's wallet services, allowing Telegram users to access the Web3 ecosystem with their social credentials smoothly.&#x20;

Tomo Telegram wallet is designed for:

1. Providing a smooth experience for managing and using cryptocurrencies in Telegram.
2. Improves the experience while exploring the web3 Telegram applications.


# Quick Start

To begin your journey with Tomo Telegram Wallet, follow the user guide below.

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

### Step 1: Search for Tomo Telegram Wallet and Launch the Mini App

Join us [here](https://t.me/tomowalletbot) or search "Tomo Wallet" in Telegram. Once you have found the Tomo Wallet bot, tap the “Start” button to proceed. Tap the “Launch” button to enter when the mini app interface pops up.

### Step 2: Registration Process

<figure><img src="/files/bXgsFxLKRYAfEEb2QM2c" alt=""><figcaption><p>Set Pay PIN</p></figcaption></figure>

1. Set Pay PIN: If you log in for the first time, you must set a Pay PIN for safety. The Pay PIN can be used to sign transactions and verify logins if you switch devices.
2. Add a recovery Email: Please link your email address to your account. If you forget your Pay PIN, you can retrieve it via email verification.

<figure><img src="/files/7JBUXpnS3RcVq3tNYLTX" alt=""><figcaption><p>Add recovery email</p></figcaption></figure>

After the registration, you can log in directly via Pay PIN.

Following these steps will begin a smooth and secure social login experience with Tomo Telegram Wallet. Enjoy managing your assets safely with Tomo!


# Chains/Networks

Currently, the Tomo TG wallet supports Bitcoin, EVM chains,  Sui, TON, and Solana.

For EVM chains, the built-in supported chains are:

* AILayer
* Arbitrum One
* Avalanche
* B2 Network
* B3
* Base
* Bitlayer
* Blast
* BNB Chain
* DuckChain
* Ethereum
* Gravity
* Linea
* Optimism
* Polygon
* Scroll
* World Chain
* zkSync Era

The following test nets are also available:

* Ton
* Story Network
* Berachain bArtio
* Botanix
* DuckChain

We will soon be able to support Cosmos and more EVM chains.


# User Manual

This manual introduces the functions and features of the Tomo Telegram wallet.


# Account Security

Beyond basic [private key management ](/overview/tomos-key-management)security, Tomo has an accounting system that protects your assets with our best effort.

#### Telegram Login

<figure><img src="/files/gPrxHpPjCFzXSLAy6s7F" alt="" width="375"><figcaption></figcaption></figure>

A Tomo Telegram wallet is connected to your Telegram account. If you control your Telegram account, you can access your wallet from the Tomo Wallet bot @tomowalletbot. This social login feature reduces the complexity of your account management with different wallets and 2FA settings.

#### Pay Pin

If malicious attackers can access your Telegram Account, we use a pay pin to verify that only you can use your asset in the wallet. The pay pin is a mandatory setting for using the Tomo Telegram wallet; please do not share it with anyone else.

<figure><img src="/files/I8oqijSuMstc0HKbAxSl" alt="" width="277"><figcaption></figcaption></figure>

&#x20;The pay pin can only be tried five times per day, so you should have enough time to regain control of your Telegram account. &#x20;

#### Recovery Email

We strongly recommend setting up a backup email if you forget your pay pin or lose your Telegram account forever. In this case, you can connect with Tomo's Team, and we can use your backup email to verify you and help you claim your wallet case by case.

#### Export Key

In the future, we will provide the feature of exporting private keys or seed phrases for experts to back up the private or manage your assets yourself. Please only do this if you clearly understand how to manage keys and what will happen if it gets leaked.


# Gift feature

The Tomo Gift is designed to seamlessly integrate with Telegram’s social ecosystem. With Tomo Telegram Wallet, you can send crypto gifts directly to your Telegram contacts, turning each transaction into a fun, engaging activity.&#x20;

### Step 1: Launch the Tomo Telegram Wallet

If this is your first time using Tomo Telegram Wallet, please follow the [quick start ](/tomo-wallet/telegram-wallet/quick-start)to ensure your wallet's security. Once you enter the wallet page, tap "gift" to get started and select the token you'll send.

### Step 2: Choose Gift Type

You have two options for sending a gift: Equal Share and Random Amount. Equal share distributes the same amount to each recipient. Enter the number of recipients and the amount each person will receive.Random Amount allows for varied gift amounts. Simply enter the number of recipients and the total amount you'd like to share.

### Step 3: Create and Share the Gift

Create the gift and share it with your Telegram contacts. Feel free to personalize the message with your own wishes before forwarding it to your friends.

<figure><img src="/files/2sfP88zzpqIFtGj9ySbM" alt=""><figcaption><p>Send a gift</p></figcaption></figure>

### Step 4: How to claim the gift

Each gift is available in a limited quantity, so make sure to quickly encourage your friends to claim their rewards! Recipients simply need to click the link, be redirected to Tomo Telegram Wallet and tap "claim"--all with no gas fees involved. Once successful, you'll see their assets on the wallet page.

<figure><img src="/files/GCnxQuD8cegYv8AeqhtL" alt=""><figcaption><p>Claim the gift</p></figcaption></figure>


# FAQ

### TELEGRAM WALLET FAQ

❓How do I start using Tomo Wallet in Telegram?

🗨️To get started, click [here](https://t.me/tomowalletbot) to launch Tomo Telegram Wallet.For the latest updates, check out Tomo Announcements channel [here](https://t.me/tomo_hub).Join our community for more information: <https://t.me/tomoinc>

❓How do I send crypto to other Telegram users?

🗨️Direct Send Method:

* Launch Tomo Telegram Wallet
* Tap \[Send]
* Select your token
* Paste the recipient's address
* Confirm the transaction

Gift Method (no address needed):

* Launch Tomo Telegram Wallet
* Tap \[Gift]
* Select your tokens
* Choose gift type: Random amount or Equal share
* Enter quantity and amount
* Create the gift
* Share the link or QR code with Telegram users

❓Can I send crypto to someone who doesn't have Tomo Wallet?

🗨️Yes, just fill in their address to proceed or send a gift to the chatbox.

❓How do I check my wallet balance in Telegram?

🗨️Open Tomo Telegram Wallet, and your total assets will be displayed as your wallet balance. Tap the network icon in the top-right corner to switch between networks and view assets on different chains.

❓Can I send crypto in Telegram group chats?

🗨️Yes! You can send crypto using the \[Gift] feature in group chats. Choose your gift type:

**Random Amount**:

* Group members will claim gifts with varying amounts

**Equal Share**:

* Every recipient claims the same amount

\
🗨️How to send gifts:

* Launch Tomo Telegram Wallet
* Tap \[Gift]
* Select your tokens
* Choose gift type (Random amount/Equal share)
* Enter quantity and amount
* Create the gift
* Share the link or QR code with Telegram users

🗨️Unclaimed gifts:

* Gifts not claimed within 3 days can be retrieved
* Go to \[Gift History] section
* Click \[Claimable]
* Get back the remaining crypto

❓Can I trade crypto directly in Telegram?

🗨️Yes, Tomo Telegram Wallet allows you to send, receive, and swap crypto directly. You can also use our on-ramp feature, powered by Alchemy Pay, to convert fiat to crypto.

❓What should I do if the Telegram bot is not responding?

🗨️If the bot is not responding, please send your Telegram username along with any screenshots or screen recordings to <support@tomo.inc>. Providing more details will help our development team resolve the issue faster.

❓How do I view my transaction history in Telegram?

🗨️You can view your transaction history by tapping the top-right icon on the Wallet tab. You can also check the swap history on the swap tab.

<figure><img src="/files/NghwefHTp61KvctLywcm" alt=""><figcaption><p>transaction history</p></figcaption></figure>

❓How do I enable biometric authentication?

🗨️The integration of biometric verification has simplified the crypto payment process. On the main Telegram Wallet page, click your name, then go to “Security Settings,” and select “Biometric Authentication” to enable it.

## MOBILE APP FAQ

❓How do I download and install the Tomo Wallet app?

🗨️It's easy! You can download the [Android](https://play.google.com/store/apps/details?id=tomo.app.unyx) and [iOS](https://apps.apple.com/us/app/tomo-inc/id6468010287) versions of the Tomo app on your phone. Once installed, you can sign up with your Email, Gmail, Apple ID, X(formerly Twitter), KakaoTalk or your Telegram.

❓What devices/operating systems are supported?

🗨️We currently support iOS and Android systems on mobile devices. You can also [download APK on our website](https://tomo.inc/).Stay tuned for future updates if you're looking for support on other platforms!

❓How do I create a new wallet in the app?

🗨️When you sign in for the first time, Tomo Wallet app automatically creates a Tomo Social EOA Wallet for you. Just tap on the \[social wallet] tab to start managing your wallet.

❓How do I import my existing crypto wallet?

🗨️Go to the \[social wallet] tab on the wallet page, name your wallet, and input your 12- or 24-word seed phrase.

❓What are the log in options?

🗨️You can get started with your email address. You can also log in with your Gmail, Apple ID, Telegram, X and KakaoTalk.Pro Tip: If you log in with your Telegram handle, your Tomo Telegram Wallet address will sync automatically to provide a seamless cross-platform experience.<br>

❓How do I connect to different chains?

🗨️As a multichain wallet, Tomo has integrated multiple EVM-compatible chains, Bitcoin, Ton, Tron, and Solana, and is continuously expanding. If you need to switch to a different chain, simply go to the \[market] tab and click the network icon to select your preferred network.<br>

❓How do I add custom tokens to my wallet?

🗨️Head to the crypto bar on the wallet tab, tap the \[Manage Assets] icon, and click \[+custom]. Select your network, then fill in the contract address, token symbol, and decimal precision.

❓How do I connect to DApps through the app?

🗨️Navigate to the \[Rewards] page to access the DApp Center. Swipe to browse supported DApps or use the search bar to find what you need instantly.

❓How do I back up my wallet on the app?

🗨️Security is our priority. Every time you open the app, you’ll need to re-enter your phone password.**Tip:** Bind your email for extra protection. In case you forget the pay PIN, your backup email can help recover it. However, please note that if you lose access to your Telegram account, you won’t be able to log in to your wallet. Therefore, make sure to save your mnemonic phrase promptly.

❓What security features does the app offer?

🗨️For wallet security, Tomo enables users to export seed phrases to protect digital assets powered by Cubist.For account security, Tomo encourages users to bind their backup email to get a verification code when users forget their PIN.

❓How do I recover my wallet if I lose access?

🗨️**App Recovery**

* **With social login**: If you signed up using social accounts and lose access, you can recover your wallet through your social accounts.

🗨️**Telegram Wallet Recovery**

* **Tied to Telegram Account**: Your wallet is linked to your Telegram account. If you lose access to your Telegram account and don’t have your seed phrase, you lose access to your wallet.
* **Recovery Email**: This is currently limited to resetting your 6-digit PIN. It does not recover your wallet or seed phrase.
* **Exporting Seed Phrase**:
  * **Telegram Wallet**: Exporting the seed phrase is possible and requires a 48-hour waiting period

<figure><img src="/files/mlW4m11bIv0vS00GnFST" alt=""><figcaption><p>Export seed phrase in Tomo Telegram Wallet</p></figcaption></figure>

* **App Wallet:** The app now supports exporting seed phrase.

<figure><img src="/files/RZD8q5xuo1dWQadzIBSg" alt=""><figcaption><p>Export seed phrase in Tomo Wallet App</p></figcaption></figure>

**Security Measures**

* **Transactions and Transfers**: PIN or Face authentication is mandatory and cannot be omitted.
* **Password Retrieval**: Resetting your transaction password is done via the registered email address.

**Important Note**

* **Seed Phrase Is Critical**: Always export and securely store your seed phrase as soon as it becomes available (Telegram Wallet only).

❓How do I contact support?

🗨️Please send email to <support@tomo.inc>.

### Staying Connected With Tomo

❓How can I access Tomo?

🗨️You can download the [Android](https://play.google.com/store/apps/details?id=tomo.app.unyx) and [iOS](https://apps.apple.com/us/app/tomo-inc/id6468010287) versions of the Tomo app on your phone and start using it. You can easily create an account on Tomo with your Gmail, Apple ID, X, or Instagram handle.

❓ Will there be a web version of the app?

🗨️We don’t yet have a web version of Tomo. But our developer team is working hard to launch the web version of our app very soon.

❓ What to do if I can’t connect my X account to Tomo?

🗨️If you haven’t connected your X handle when opening an account on Tomo, you can do it later as well. Go to Settings and click on ‘Connect X’. Enter your X login credentials (email/username and password) and connect your Tomo account with X.

❓ If I change my X handle, will it affect my Tomo account and Chat Room accessibility?

🗨️Your Tomo account and Chat Room will remain intact even if you change your X handle. However, users who will follow your new X handle won’t be able to join your old Chat Room.

We’re currently working on supporting X handle changes for a seamless transition and will soon launch the feature on our app.&#x20;

❓ Do you have a Discord server or Telegram group?

🗨️ Please go to our [**Telegram Group**](https://t.me/tomoinc) for customer support matters. The good thing is our team is currently working on developing a built-in server inside the Tomo app. This will help the Tomo community to stay connected with each other within the app.&#x20;

❓ Where can I get all the latest updates about Tomo?

🗨️You can follow us on X at [tomo\_social](https://twitter.com/tomo_social) and on Instagram at [Tomoinc](https://www.instagram.com/tomoinc/) for all the latest updates about Tomo.

### Tomo User Interface

❓ How does Tomo’s in-app economy work?

🗨️Tomo uses a Key-based Proof-of-Support system to build direct connections between content creators and followers. Simply put, the app uses tokens to prove that a follower supports a creator and creates new revenue-generation opportunities for everyone.

❓ What is a Key?

🗨️A Key is Tomo’s in-app tool to get exclusive access to a creator’s content and chatroom. Fans and followers can purchase the keys to follow influencers and creators who are already using Tomo. A bonding curve determines the price of a Key.&#x20;

❓ How does a bonding curve determine Key prices?

🗨️A bonding curve initially sets Key prices at a minimum value and then keeps increasing as more users buy the Keys. This benefits early buyers as they can sell it later to make profits and help creators increase their royalty share.&#x20;

❓ Can I use Tomo without purchasing a Key?

🗨️If you’re a content creator, you can use Tomo without purchasing any Key or crypto. Each Key transaction has a 10% royalty fee and 5% directly goes to the creator’s crypto balance. Thus, content creators can use this balance to activate their wallets and use Tomo. Please note that this is a V2 feature and is not available in the first version of Tomo.&#x20;

❓ Can I withdraw my funds from Tomo? How can I withdraw it?

🗨️Yes, you can withdraw your funds from Tomo anytime.

In Tomo V2, you can automatically withdraw your funds to the Linea Mainnet Receival Address. Make sure to select an ETH amount that is not more than your Tomo in-app balance and keep a buffer to pay the gas fees.

❓ How can I earn points on Tomo?

🗨️You can earn Tomo points if your friends use your Referral code and complete certain tasks on the Tomo app. You can also earn more points if you use your friend’s referral code and complete the steps.

### Tomo’s Account Abstraction (ERC-4337) Wallets \[Advanced Level FAQs]

❓What are ERC-4337 wallets?

🗨️ERC-4337 wallets are programmable smart contracts that function as non-custodial wallets. These wallets can initiate and execute transactions independently. In 2023, an Ethereum update introduced the ERC-4337 or account abstraction standard which offers a user-friendly wallet interface and doesn’t require a seed phrase.

❓What is a private key?

🗨️A private key is a random string of characters that wallet holders use to sign or authorize transactions. Whoever has access to a wallet’s private key can access the wallet’s funds. A private key is somewhat like a credit card PIN number that enables you to make transactions.\
\
If someone loses their private key, they can only generate it with their seed phrase.

❓Can I export or back up the private key of my Tomo wallet? If yes, how can I do that?

🗨️Yes, you can export or back up the private key of your Tomo wallet. You need to go to the app’s Settings page and save the private key for easy recovery.

But you must note that currently, the private key is incompatible with other EOA wallets. Our team is working on EOA wallet compatibility and the private key will soon be integrated with OKX wallet.

❓What is the difference between Externally Owned Accounts (EOAs) and account-abstracted wallets?

🗨️Externally owned accounts (EOAs) are seed phrase-enabled wallets like MetaMask. These wallets use a seed phrase and private key to sign transactions.

Account-abstracted wallets don’t need any seed phrase to sign transactions. They’re independent, programmable smart contracts that initiate and sign transactions on their own.

❓Do I need to create my own wallet on Tomo? How can I do it?

🗨️Tomo users don’t have to create a web3 wallet on their own. When you open an account on Tomo, we automatically create a non-custodial wallet for you in the backend, thanks to account abstraction and ERC-4337.&#x20;

❓How do you benefit from ERC-4337 wallets?

🗨️Tomo can easily set up your wallets as they don’t require any seed phrase or private key. You also benefit from Tomo wallets’ additional security like two-factor authentication (password, lock pattern, fingerprint) to confirm your own identity and deny unauthorized access.

Additionally, you can smoothly recover your wallet and take a backup in case your phone is lost. With ERC-4337 wallets, you will also enjoy flexible gas payment and can pay transaction fees in any ERC-20 token, stablecoin, and fiat currency apart from ETH.

❓Can I use an EOA wallet for my Tomo account?

🗨️Tomo automatically sets up an ERC-4337 wallet for you in the backend. You can use an EOA wallet like MetaMask to deposit ETH into your Tomo wallet. Our protocol offers automated bridging and will bridge funds to Linea if someone uses an EOA.

❓Can I use fiat currency like the US dollar for my Tomo account?

🗨️Yes, you can use fiat money and deposit it into your Tomo wallet to purchase Keys. This feature will go live in Tomo V2.

### Tomo Safety Features

❓Is logging into Tomo with my Gmail, Apple, X, or Instagram account safe?

🗨️Yes, it is safe to log in to Tomo with your personal Gmail, Apple, X, or Instagram handle. We don’t store any of your login information or private data.

❓What steps has Tomo taken to ensure user safety?

🗨️The third-party Salus audit ensures that our protocol is safe for everyone. Besides the unbiased audit report, our in-house team is continuously working on improving our security features.

We aim to introduce end-to-end message encryption, screenshot prevention, and ‘burn after reading’ features in the upcoming versions of our app. &#x20;

### Troubleshooting Tomo

❓What to do if I send my tokens from a non-Ethereum chain to Tomo’s Ethereum address?

🗨️You needn’t worry as your funds won’t be lost. The Tomo team is equipped to help you recover your assets quickly. Please send an email to us at <support@tomo.inc> with your registration details and transaction hash. The recovery processing time can be around 3 days.

❓What can I do if I send my tokens from a non-Linea chain to Tomo’s Linea address?

🗨️The Tomo team is here to assist you in the quick recovery of your assets.  Please send an email to us at <support@tomo.inc> with your registration details and transaction hash.

The recovery processing time might take 1-2 months, depending on the blockchain compatibility with our ERC-4337 wallet. We will of course do our best to recover your funds but we cannot guarantee it in this case.&#x20;

❓Can I restore my Tomo account if I accidentally delete it? How to do it?

🗨️Yes, you can restore your Tomo account if you delete it. Please send an email to us at <support@tomo.inc> with your registration details. Our support team will help you to recover your account.

You can also take a backup of your private key and use it to restore your Tomo account.

### Tomo’s New Updates&#x20;

❓How can I view a Story on Tomo?

🗨️Tomo has three separate ‘Story’ pages. There is a Public Story feed (shows recommended content), a Following feed (shows the users/creators you follow), and a Keys feed (shows the users/creators you own keys of).\
\
You can tap left to view the previous story, tap right for the next one, and swipe up to see the next recommended story.

❓Can I react or comment on a Story like I do it on Instagram?

🗨️No, you cannot react or comment on a story yet.

However, you can directly send a message to the user who posted the Story. You need to buy the creator’s Key to send messages.

❓How can I publish/put up a Story?

🗨️You have to click on the center ‘New’ button to put up public Stories and private Feeds.

❓Can I bookmark/save a user profile?

🗨️Yes, you can bookmark a content creator’s profile or share their link with your friends. Each profile shows the creator’s public Story and private Feed.

❓What new features are coming on the Chat Room?

🗨️The Chat Room admins can now mute everyone, appoint or remove managers, and delete other members’ messages. The Chat Room participants can also reply to and tag other users. They can delete or edit their own messages as well.

❓What can I do on the DM page?

🗨️You can now send voice messages, pictures, and videos on the DM page. Moreover, you can edit or delete your own messages even after sending them.

❓Are there any changes on the Keys page?

🗨️Yes, we have introduced multiple changes on the Keys page. Now Tomo shows all the Keys together, sorted by price, 24-hour volume, and holding value. You can choose if you want to show your holding value within the app. We also have a separate page for users to keep track of the creator’s Keys they hold.

❓Can I connect with local content creators?

🗨️Yes, you can connect with local content creators. We have a Local page that sorts users by distance. This will help you to find influencers and creative personalities who live near you and can possibly connect with you in virtual and real life.\
\
In Tomo V2, we use the Local Keys feature to set a fixed distance of 200 kilometers. When both creators and followers activate their location from their Tomo profiles, they can connect with nearby profiles.

<br>


# Transaction

Tomo Telegram Wallet can allow users to send assets to addresses.

## **How to Send to a Crypto Address**

### Step 1 Launch Tomo Telegram Wallet and select send tokens

1. Log into [Tomo Telegram Wallet](https://t.me/tomowalletbot) using a passkey or Pay PIN. On the wallet page, you can switch networks by tapping the network icon.
2. In order to send tokens to an external address, tap \[send] to enter the transfer page.
3. Select send tokens and network to proceed.

### Step 2 Add receiving address and confirm amount

1. In the \[Receiving Address] field, enter the crypto address where you want to send the assets.
2. After confirming the address, you will be taken to the \[Sent] page. Enter the amount you want to transfer.
3. Once you’ve double-checked everything, tap \[Confirm]. Your transaction will be completed successfully!

<figure><img src="/files/MlIx3oAJOmMw50hiqOb7" alt=""><figcaption><p>how to send your crypto</p></figcaption></figure>

## How to receive crypto

1. On the wallet page, tap \[receive] to get your address.
2. Select currency you will receive and remember to switch network.
3. Copy the address or share the QR code.

<figure><img src="/files/914b04lWIRHREwIGFJnk" alt=""><figcaption><p>how to receive crypto</p></figcaption></figure>


# Swap

With features like cross-chain swaps, Tomo enables users to manage assets across blockchains, making it simple to explore decentralized finance without complicated processes.

**How to Swap Tokens on the Tomo Telegram Wallet**

1. **Launch Tomo Telegram Wallet and Tap \[Swap]:** Access \[Swap] on the wallet tab or at the bottom.
2. **Select Network and Tokens:** On the \[Swap] tab, select the network. Tomo Telegram Wallet supports Bitcoin, Ethereum, BNB Chain, Arbitrum One, Base, Blast, Avalanche, Polygon, Scroll, Optimism, Linea, B3, DuckChain Testnet, Solana, TON, and TRON. Then choose the tokens to swap, e.g., swapping ETH on Base to USDT on Linea.
3. **Enter the Swap Amount and Review Details:** Check the estimated gas fee, transaction time, slippage, quote route, and provider. Slide \[Slide to Confirm] to proceed. Tomo offers optimized default settings but also supports custom provider and slippage options.
4. **Review Swap History:** Check completed transactions in \[Swap History] or \[Wallet] > \[Activity].
5. **Wait for Optimal Route:** If \[Slide to Confirm] remains gray, please wait while the system finds the best route.

<figure><img src="/files/H6U7sBmEX6ejopnNQEmR" alt=""><figcaption><p>cross-chain swap</p></figcaption></figure>


# Tomo Pro (Web Version)

### <mark style="color:purple;">Tomo Pro is in BETA</mark>

[Tomo Pro](https://pro.tomo.inc) is a web version of Tomo, tailored for crypto-native users familiar with EOA wallets as well as how to deposit and operate them. It's designed for those interested in exploring the social capital market of Tomo Keys and launching, minting, or buying ERC404 art and meme collections via Tomoji.  \
\
Please note that Tomo Pro requires a sign-up via your EOA wallet; the account is separate from the mobile Tomo app.


# Brand Assets

## Tomo Brand Guidelines

***

#### Tomo Logo with Text

* [**Primary (Color)**](https://drive.google.com/drive/folders/10x08Xp1mC8-F0dsi_aKYMJeNpYrWG0Ed)

#### Tomo Logo without Text

* [**Primary (Color)**](https://drive.google.com/drive/folders/1BpK2miU5cbFjjjGi2_L5Kapa0HHKecfC)

**Formats:** PNG \
**Clear Space:** Maintain padding around all logos.

***

### 2. Brand Colors

| Color Name | HEX Code |
| ---------- | -------- |
| Hot Pink   | #FE3C9C  |
| White      | #FFFFFF  |
| Black      | #000000  |

***

### 3. Typography

* **Font:** Kumbh Sans
* **Usage:** For all headings and body text.

***

For any questions, contact <milena@tomo.inc>.


# Privacy Policy

Tomo Wallet Privacy Policy

Tomo Wallet, operated by Tomo Inc. (hereinafter referred to as “we,” “us,” or “Tomo Wallet”), is a multi-chain cryptocurrency wallet platform that provides users with services, including cryptocurrency transactions, swaps, and more. This Privacy Policy outlines how we collect, use, and protect your personal information when you use Tomo Wallet and its services (“Services”).

By accessing and using Tomo Wallet, you agree to the terms outlined in this Privacy Policy. We may update this Privacy Policy from time to time, and the updated version will be posted on our platform. Any changes will be effective immediately upon being posted. Your continued use of Tomo Wallet after any updates constitutes your acceptance of the revised Privacy Policy.

If you do not accept this Privacy Policy, please refrain from using Tomo Wallet and its services.

### **I. Information We Collect**

We collect the following types of information from you to provide and improve our Services. We are committed to protecting your privacy, and we collect personal data in a lawful, legitimate, and necessary manner. You are not required to provide certain information; however, failure to provide necessary information may affect your ability to use certain features of Tomo Wallet.&#x20;

Below chart details the categories of Personal Data that we collect and have collected over the past 12 months.

| **Category of Personal Data** | **Description**                                                                                                                                                         | **Examples of Personal Data We Collect**                       |
| ----------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------- |
| Account Information           | We collect basic account information such as your email address, username, and profile details from the respective service providers to create your wallet account.     | Gmail, Twitter, Telegram, Apple ID, KakaoTalk                  |
| Transaction Information       | We collect information related to your cryptocurrency transactions, including transaction history, wallet addresses, and related metadata from the blockchain system.   | <p>Transaction history, wallet addresses<br></p>               |
| Device and Usage Data         | We collect data related to your device and how you interact with Tomo Wallet, including usage statistics, app interactions, and transaction activities.                 | <p>Mobile device information, browser type, IP address<br></p> |
| Security Information          | We collect information for security purposes, such as device authentication data when you log in, including the use of biometrics if you choose to enable this feature. | <p>Face or fingerprint recognition<br></p>                     |

### **II**. **Information we never collect**

Your seed phrase and mnemonic phrase on Tomo Wallet are never stored or synchronized on our servers. We do not offer services to recover your wallet seed phrase or mnemonic phrase.

Additionally, when using specific features of Tomo Wallet, we will provide a clear reminder before collecting any personal information from you. We prioritize transparency and ensure your data privacy.

### **III. How We Use Your Information**

We use your personal data to manage, provide, improve, and personalize our services while complying with our legal and regulatory obligations. Additionally, we may use this data to communicate with you about other products or services offered by Tomo Wallet and/or its partners, addressing any concerns or complaints you may have.

1. **To Provide Services**

• To facilitate cryptocurrency transactions, swaps, and related operations.

• To enable social login through Gmail, Twitter, Telegram, Apple ID, KakaoTalk, and other third-party services.

• To verify your identity and secure your account.

2. **To Improve Services**

• To conduct data analysis and internal research to improve the performance and user experience of Tomo Wallet.

• To send you important notices, updates, and notifications related to the Services, including updates to this Privacy Policy.

3. **For Security**

• To monitor, detect, and prevent security incidents and fraud and to maintain the safety and integrity of the Services.

• To ensure compliance with applicable laws, regulations, and our internal policies.

4. **For Communication**

• To respond to your inquiries, feedback, and customer support requests.

• To send you promotional information and updates related to new features, services, or other matters that may interest you.

### **IV. Account Information and Security**

At Tomo Wallet, we prioritize the security of your account and personal data by using strong protection measures. When you log in with social media accounts (like Gmail, Twitter, Telegram, etc.), rest assured that we will not misuse your private information. We only use the data shared for providing our Services and ensure its confidentiality.

To protect your account, please use strong login credentials and log out after accessing your account. While we take steps to secure your data, no online method is completely risk-free.

We retain personal data as long as you have an active account or as needed to comply with legal obligations or resolve disputes. Some information may be kept in anonymous or aggregated form without identifying you.<br>

### **V. How You Manage Your Information**

Tomo Wallet gives you the ability to control and manage your personal information. You may:

1. **Access and Modify Information**

   You can view and update your wallet information, including profile details, transaction history, and other personal data via the “Settings” section of the app.
2. **Security Settings**

   In the “Security settings” section, you can enable or disable features like biometric authentication, Pay PIN, and backup email for added security.
3. **Request Data Deletion**

   You can request to delete your personal information by contacting our support team. Upon such a request, we will remove your personal data from our systems, except as required for legal or business purposes.

### **VI. How We Protect Your Information**

We take data security seriously and employ appropriate technical and organizational measures to protect your personal information from unauthorized access, use, disclosure, or destruction.

1. **Encryption**

   We use encryption protocols to safeguard your sensitive data, including transaction details, login information, and account data.
2. **Access Controls**

   We restrict access to your personal information to only those employees and service providers who need it to perform their duties.
3. **Monitoring and Auditing**

   We regularly monitor our systems and conduct security audits to ensure the integrity and confidentiality of your data.

### **VII. Sharing Your Information**

Tomo will not release Personal Information to third parties except under the following conditions:

1. **For Legal Compliance**

   We may share your personal information if required by law to comply with legal processes or to protect the rights, property, or safety of Tomo Wallet, its users, or others.
2. **With Your Consent**

   We may share your information with third parties if you give us explicit consent to do so.

### **VIII. Third-Party Links and Websites**

Tomo Wallet may contain links to third-party websites, dApps, or services. This Privacy Policy does not apply to these third-party services. We are not responsible for the privacy practices or content of third-party websites. You should review the privacy policies of these third parties before interacting with them.

### **IX. Children’s Privacy**

Tomo Wallet is not intended for use by individuals under the age of 18. We do not knowingly collect personal information from children. If we become aware that we have inadvertently collected personal information from a child, we will take steps to delete that information as quickly as possible.

### **X. Changes to This Privacy Policy**

We may update this Privacy Policy from time to time. Any changes will be posted on our platform, and the updated version will be effective immediately upon posting. We encourage you to review this Privacy Policy periodically for any updates.

### **XI. Contact Us**

If you have any questions or concerns about this Privacy Policy or the use of your personal information, please contact us:  **<support@tomo.inc>**

By using Tomo Wallet, you acknowledge that you have read and understood this Privacy Policy and agree to its terms.


