Solana Provider
After setting up your wallet, you can have access to the Solana provider:
// react
const { providers } = useTomo()
const { solanaProvider } = providers;
// pure js
const solanaProvider = window.tomo_sol
Get Solana Address
the Solana address from the wallet state or provider. In React framework:
// 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:
/** pure js */
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()
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.
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
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.
// 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)
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.
// 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)
Example
We provide an example of a SOL transfer transaction as follows:
React
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>
)
}
Pure 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>
)
}
Last updated