diff --git a/packages/starter/example/src/components/SendLegacyTransaction.tsx b/packages/starter/example/src/components/SendLegacyTransaction.tsx new file mode 100644 index 000000000..bb9fe915d --- /dev/null +++ b/packages/starter/example/src/components/SendLegacyTransaction.tsx @@ -0,0 +1,72 @@ +import { Button } from '@mui/material'; +import { useConnection, useWallet } from '@solana/wallet-adapter-react'; +import type { TransactionSignature } from '@solana/web3.js'; +import { TransactionMessage, VersionedTransaction } from '@solana/web3.js'; +import { PublicKey } from '@solana/web3.js'; +import type { FC } from 'react'; +import React, { useCallback } from 'react'; +import { useNotify } from './notify'; + +export const SendLegacyTransaction: FC = () => { + const { connection } = useConnection(); + const { publicKey, sendTransaction, wallet } = useWallet(); + const notify = useNotify(); + const supportedTransactionVersions = wallet?.adapter.supportedTransactionVersions; + + const onClick = useCallback(async () => { + if (!publicKey) { + notify('error', 'Wallet not connected!'); + return; + } + + if (!supportedTransactionVersions) { + notify('error', "Wallet doesn't support versioned transactions!"); + return; + } else if (!supportedTransactionVersions.has('legacy')) { + notify('error', "Wallet doesn't support legacy transactions!"); + return; + } + + let signature: TransactionSignature = ''; + try { + const { + context: { slot: minContextSlot }, + value: { blockhash, lastValidBlockHeight }, + } = await connection.getLatestBlockhashAndContext(); + + const message = new TransactionMessage({ + payerKey: publicKey, + instructions: [ + { + data: Buffer.from('Hello, from the Solana Wallet Adapter example app!'), + keys: [], + programId: new PublicKey('MemoSq4gqABAXKb96qnH8TysNcWxMyWCqXgDLGmfcHr'), + }, + ], + recentBlockhash: blockhash, + }); + + const transaction = new VersionedTransaction(message.compileToLegacyMessage()); + + signature = await sendTransaction(transaction, connection, { minContextSlot }); + notify('info', 'Transaction sent:', signature); + + await connection.confirmTransaction({ blockhash, lastValidBlockHeight, signature }); + notify('success', 'Transaction successful!', signature); + } catch (error: any) { + notify('error', `Transaction failed! ${error?.message}`, signature); + return; + } + }, [publicKey, notify, connection, sendTransaction, supportedTransactionVersions]); + + return ( + + ); +}; diff --git a/packages/starter/example/src/components/SendV0Transaction.tsx b/packages/starter/example/src/components/SendV0Transaction.tsx new file mode 100644 index 000000000..1cb33ef10 --- /dev/null +++ b/packages/starter/example/src/components/SendV0Transaction.tsx @@ -0,0 +1,89 @@ +import { Button } from '@mui/material'; +import { useConnection, useWallet } from '@solana/wallet-adapter-react'; +import type { TransactionSignature } from '@solana/web3.js'; +import { PublicKey, TransactionMessage, VersionedTransaction } from '@solana/web3.js'; +import type { FC } from 'react'; +import React, { useCallback } from 'react'; +import { useNotify } from './notify'; + +export const SendV0Transaction: FC = () => { + const { connection } = useConnection(); + const { publicKey, sendTransaction, wallet } = useWallet(); + const notify = useNotify(); + const supportedTransactionVersions = wallet?.adapter.supportedTransactionVersions; + + const onClick = useCallback(async () => { + if (!publicKey) { + notify('error', 'Wallet not connected!'); + return; + } + + if (!supportedTransactionVersions) { + notify('error', "Wallet doesn't support versioned transactions!"); + return; + } else if (!supportedTransactionVersions.has(0)) { + notify('error', "Wallet doesn't support v0 transactions!"); + return; + } + + let signature: TransactionSignature = ''; + try { + /** + * This lookup table only exists on devnet and can be replaced as + * needed. To create and manage a lookup table, use the `solana + * address-lookup-table` commands. + */ + const { value: lookupTable } = await connection.getAddressLookupTable( + new PublicKey('F3MfgEJe1TApJiA14nN2m4uAH4EBVrqdBnHeGeSXvQ7B') + ); + if (!lookupTable) { + notify('error', "Address lookup table wasn't found!"); + return; + } + + const { + context: { slot: minContextSlot }, + value: { blockhash, lastValidBlockHeight }, + } = await connection.getLatestBlockhashAndContext(); + + const message = new TransactionMessage({ + payerKey: publicKey, + instructions: [ + { + data: Buffer.from('Hello, from the Solana Wallet Adapter example app!'), + keys: lookupTable.state.addresses.map((pubkey, index) => ({ + pubkey, + isWritable: index % 2 == 0, + isSigner: false, + })), + programId: new PublicKey('MemoSq4gqABAXKb96qnH8TysNcWxMyWCqXgDLGmfcHr'), + }, + ], + recentBlockhash: blockhash, + }); + + const lookupTables = [lookupTable]; + const transaction = new VersionedTransaction(message.compileToV0Message(lookupTables)); + + signature = await sendTransaction(transaction, connection, { minContextSlot }); + notify('info', 'Transaction sent:', signature); + + await connection.confirmTransaction({ blockhash, lastValidBlockHeight, signature }); + notify('success', 'Transaction successful!', signature); + } catch (error: any) { + notify('error', `Transaction failed! ${error?.message}`, signature); + return; + } + }, [publicKey, notify, connection, sendTransaction, supportedTransactionVersions]); + + return ( + + ); +}; diff --git a/packages/starter/example/src/pages/index.tsx b/packages/starter/example/src/pages/index.tsx index 78bb33d3f..249b5ae2e 100644 --- a/packages/starter/example/src/pages/index.tsx +++ b/packages/starter/example/src/pages/index.tsx @@ -23,6 +23,8 @@ import pkg from '../../package.json'; import { useAutoConnect } from '../components/AutoConnectProvider'; import { RequestAirdrop } from '../components/RequestAirdrop'; import { SendTransaction } from '../components/SendTransaction'; +import { SendLegacyTransaction } from '../components/SendLegacyTransaction'; +import { SendV0Transaction } from '../components/SendV0Transaction'; import { SignMessage } from '../components/SignMessage'; const Index: NextPage = () => { @@ -119,6 +121,17 @@ const Index: NextPage = () => { + + + + + + + + + + + );