# 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>
  )
}

```


---

# Agent Instructions: Querying This Documentation

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

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

```
GET https://docs.tomo.inc/tomo-sdk/tomo-web-sdk/solana-provider.md?ask=<question>
```

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

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