Skip to content

Commit

Permalink
feat: implement web-solana-ui library
Browse files Browse the repository at this point in the history
  • Loading branch information
beeman committed Dec 4, 2023
1 parent 22664ea commit 3986454
Show file tree
Hide file tree
Showing 51 changed files with 1,034 additions and 746 deletions.
5 changes: 4 additions & 1 deletion libs/anchor/target/idl/counter.json
Original file line number Diff line number Diff line change
Expand Up @@ -91,5 +91,8 @@
]
}
}
]
],
"metadata": {
"address": "5t7i8rFcWxrBhf7PYbxBQudXYQLnJW4zBS4xiknaFuCv"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { Button, Stepper, Switch } from '@mantine/core'
import { modals } from '@mantine/modals'
import { ellipsify, Identity, IdentityProvider } from '@pubkey-stack/sdk'
import { useIdentitySolana } from '@pubkey-stack/web-identity-data-access'
import { WalletButton } from '@pubkey-stack/web-solana-ui'
import { toastError, UiStack, UiWarning } from '@pubkey-ui/core'
import { WalletMultiButton } from '@pubkeyapp/wallet-adapter-mantine-ui'
import { useWallet } from '@solana/wallet-adapter-react'
Expand Down Expand Up @@ -74,7 +75,7 @@ export function WebUiIdentitySolanaLinkWizard({ identities }: { identities: Iden
</UiStack>
) : (
<UiStack>
<WalletMultiButton size="lg" />
<WalletButton size="lg" />
</UiStack>
)
) : (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { Button, Stepper, Switch } from '@mantine/core'
import { modals } from '@mantine/modals'
import { ellipsify, Identity, IdentityProvider } from '@pubkey-stack/sdk'
import { useIdentitySolana } from '@pubkey-stack/web-identity-data-access'
import { WalletButton } from '@pubkey-stack/web-solana-ui'
import { toastError, UiStack, UiWarning } from '@pubkey-ui/core'
import { WalletMultiButton } from '@pubkeyapp/wallet-adapter-mantine-ui'
import { useWallet } from '@solana/wallet-adapter-react'
Expand Down Expand Up @@ -46,7 +47,7 @@ export function WebUiIdentitySolanaVerifyWizard({ identity, refresh }: { identit
description={connected ? `Connected to ${ellipsify(publicKey?.toBase58())}` : 'Select Wallet'}
>
<UiStack>
<WalletMultiButton size="lg" />
<WalletButton size="lg" />
</UiStack>
</Stepper.Step>
<Stepper.Step
Expand Down
26 changes: 5 additions & 21 deletions libs/web/shell/feature/src/lib/use-guarded-routes.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
import { Group } from '@mantine/core'
import { UserRole, UserStatus } from '@pubkey-stack/sdk'
import { AuthGuard, UserRoleGuard, UserStatusGuard } from '@pubkey-stack/web-auth-data-access'
import { UiFull, UiHeaderProfile } from '@pubkey-stack/web-ui-core'
import { UiError, UiHeader, UiLayout, UiLoader, UiWarning } from '@pubkey-ui/core'
import { WalletMultiIcon } from '@pubkeyapp/wallet-adapter-mantine-ui'
import { UiFull } from '@pubkey-stack/web-ui-core'
import { UiError, UiLoader, UiWarning } from '@pubkey-ui/core'

import { Navigate, Outlet, RouteObject, useRoutes } from 'react-router-dom'
import { WebShellLayout } from './web-shell-layout'

export function useGuardedRoutes({
admin,
Expand Down Expand Up @@ -33,24 +32,9 @@ export function useGuardedRoutes({
{
// This adds the main layout to the routes
element: (
<UiLayout
header={
<UiHeader
links={[
{ link: '/dashboard', label: 'Dashboard' },
{ link: '/solana', label: 'Solana' },
]}
profile={
<Group>
<WalletMultiIcon />
<UiHeaderProfile />
</Group>
}
/>
}
>
<WebShellLayout>
<Outlet />
</UiLayout>
</WebShellLayout>
),
children: [
{
Expand Down
41 changes: 41 additions & 0 deletions libs/web/shell/feature/src/lib/web-shell-layout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import { Group } from '@mantine/core'
import {
SolanaUiAccountBalanceButton,
SolanaUiAccountChecker,
SolanaUiClusterChecker,
SolanaUiClusterSelect,
WalletIcon,
} from '@pubkey-stack/web-solana-ui'
import { UiHeaderProfile } from '@pubkey-stack/web-ui-core'
import { UiHeader, UiLayout } from '@pubkey-ui/core'
import { useWallet } from '@solana/wallet-adapter-react'
import { ReactNode } from 'react'

export function WebShellLayout({ children }: { children: ReactNode }) {
const { publicKey } = useWallet()
return (
<UiLayout
header={
<UiHeader
links={[
{ link: '/dashboard', label: 'Dashboard' },
{ link: '/solana', label: 'Solana' },
]}
profile={
<Group gap="xs">
{publicKey && <SolanaUiAccountBalanceButton address={publicKey} />}
{publicKey && <SolanaUiClusterSelect />}
<WalletIcon />
<UiHeaderProfile />
</Group>
}
/>
}
>
<SolanaUiClusterChecker>
<SolanaUiAccountChecker />
</SolanaUiClusterChecker>
{children}
</UiLayout>
)
}
3 changes: 2 additions & 1 deletion libs/web/solana/data-access/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
export * from './lib/solana-explorer-link'
export * from './lib/create-transaction'
export * from './lib/toast-signature-link'
export * from './lib/use-account'
export * from './lib/web-cluster-provider'
export * from './lib/web-solana-provider'
50 changes: 50 additions & 0 deletions libs/web/solana/data-access/src/lib/create-transaction.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import {
Connection,
LAMPORTS_PER_SOL,
PublicKey,
SystemProgram,
TransactionMessage,
VersionedTransaction,
} from '@solana/web3.js'

export async function createTransaction({
publicKey,
destination,
amount,
connection,
}: {
publicKey: PublicKey
destination: PublicKey
amount: number
connection: Connection
}): Promise<{
transaction: VersionedTransaction
latestBlockhash: { blockhash: string; lastValidBlockHeight: number }
}> {
// Get the latest blockhash to use in our transaction
const latestBlockhash = await connection.getLatestBlockhash()

// Create instructions to send, in this case a simple transfer
const instructions = [
SystemProgram.transfer({
fromPubkey: publicKey,
toPubkey: destination,
lamports: amount * LAMPORTS_PER_SOL,
}),
]

// Create a new TransactionMessage with version and compile it to legacy
const messageLegacy = new TransactionMessage({
payerKey: publicKey,
recentBlockhash: latestBlockhash.blockhash,
instructions,
}).compileToLegacyMessage()

// Create a new VersionedTransaction which supports legacy and v0
const transaction = new VersionedTransaction(messageLegacy)

return {
transaction,
latestBlockhash,
}
}
Original file line number Diff line number Diff line change
@@ -1,35 +1,14 @@
import { useCluster } from '@pubkey-stack/web-solana-data-access'
import { toastError, toastSuccess } from '@pubkey-ui/core'
import { toastError } from '@pubkey-ui/core'
import { TOKEN_2022_PROGRAM_ID, TOKEN_PROGRAM_ID } from '@solana/spl-token'
import { useConnection, useWallet } from '@solana/wallet-adapter-react'
import {
Connection,
LAMPORTS_PER_SOL,
PublicKey,
SystemProgram,
TransactionMessage,
TransactionSignature,
VersionedTransaction,
} from '@solana/web3.js'
import { LAMPORTS_PER_SOL, PublicKey, TransactionSignature } from '@solana/web3.js'
import { useMutation, useQuery } from '@tanstack/react-query'

export function transactionToast(signature: string) {
toastSuccess({
title: 'Transaction sent',
message: `
<div>
<div>
Transaction ${signature} sent
</div>
<a href="https://explorer.solana.com/tx/${signature}" target="_blank" rel="noopener noreferrer">
View on Solana Explorer
</a>
</div>`,
})
}
import { createTransaction } from './create-transaction'
import { toastExplorerLink } from './toast-signature-link'
import { useCluster } from './web-cluster-provider'

export function useAccount({ address }: { address: PublicKey }) {
const { cluster } = useCluster()
const { cluster, getExplorerUrl } = useCluster()
const { connection } = useConnection()

const wallet = useWallet()
Expand Down Expand Up @@ -76,7 +55,7 @@ export function useAccount({ address }: { address: PublicKey }) {
return signature
},
onSuccess: (signature) => {
transactionToast(signature)
toastExplorerLink({ link: getExplorerUrl(`tx/${signature}`), label: 'View Transaction' })
return Promise.all([getBalance.refetch(), getSignatures.refetch()])
},
})
Expand Down Expand Up @@ -109,7 +88,7 @@ export function useAccount({ address }: { address: PublicKey }) {
},
onSuccess: (signature) => {
if (signature) {
transactionToast(signature)
toastExplorerLink({ link: getExplorerUrl(`tx/${signature}`), label: 'View Transaction' })
}
return Promise.all([getBalance.refetch(), getSignatures.refetch()])
},
Expand All @@ -127,45 +106,3 @@ export function useAccount({ address }: { address: PublicKey }) {
transferSol,
}
}

async function createTransaction({
publicKey,
destination,
amount,
connection,
}: {
publicKey: PublicKey
destination: PublicKey
amount: number
connection: Connection
}): Promise<{
transaction: VersionedTransaction
latestBlockhash: { blockhash: string; lastValidBlockHeight: number }
}> {
// Get the latest blockhash to use in our transaction
const latestBlockhash = await connection.getLatestBlockhash()

// Create instructions to send, in this case a simple transfer
const instructions = [
SystemProgram.transfer({
fromPubkey: publicKey,
toPubkey: destination,
lamports: amount * LAMPORTS_PER_SOL,
}),
]

// Create a new TransactionMessage with version and compile it to legacy
const messageLegacy = new TransactionMessage({
payerKey: publicKey,
recentBlockhash: latestBlockhash.blockhash,
instructions,
}).compileToLegacyMessage()

// Create a new VersionedTransaction which supports legacy and v0
const transaction = new VersionedTransaction(messageLegacy)

return {
transaction,
latestBlockhash,
}
}
6 changes: 2 additions & 4 deletions libs/web/solana/data-access/src/lib/web-solana-provider.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import { AnchorProvider } from '@coral-xyz/anchor'
import { WalletModalProvider, WalletMultiButton } from '@pubkeyapp/wallet-adapter-mantine-ui'
import { WalletModalProvider } from '@pubkeyapp/wallet-adapter-mantine-ui'
import { WalletError } from '@solana/wallet-adapter-base'
import { PhantomWalletAdapter } from '@solana/wallet-adapter-phantom'
import {
AnchorWallet,
ConnectionProvider,
useConnection,
useWallet,
WalletProvider,
} from '@solana/wallet-adapter-react'
import { PhantomWalletAdapter } from '@solana/wallet-adapter-phantom'
import { SolflareWalletAdapter } from '@solana/wallet-adapter-solflare'
import { ReactNode, useCallback, useMemo } from 'react'
import { ClusterProvider, toWalletAdapterNetwork, useCluster } from './web-cluster-provider'
Expand Down Expand Up @@ -42,8 +42,6 @@ export function SolanaProvider({ autoConnect = true, children }: { autoConnect?:
)
}

export const WalletButton = WalletMultiButton

export function useAnchorProvider() {
const { connection } = useConnection()
const wallet = useWallet()
Expand Down
22 changes: 13 additions & 9 deletions libs/web/solana/feature/src/lib/account/account-detail-feature.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,18 @@
import { Group } from '@mantine/core'
import { ellipsify } from '@pubkey-stack/sdk'
import {
SolanaUiAccountBalance,
SolanaUiAccountButtons,
SolanaUiAccountTokens,
SolanaUiAccountTransactions,
SolanaUiExplorerLink,
} from '@pubkey-stack/web-solana-ui'
import { UiPage, UiStack } from '@pubkey-ui/core'
import { PublicKey } from '@solana/web3.js'
import { useMemo } from 'react'

import { useParams } from 'react-router-dom'

import { ExplorerLink } from '../cluster/cluster-ui'

import { AccountBalance, AccountButtons, AccountTokens, AccountTransactions, ellipsify } from './account-ui'

export default function AccountDetailFeature() {
const params = useParams()
const address = useMemo(() => {
Expand All @@ -27,17 +31,17 @@ export default function AccountDetailFeature() {

return (
<UiPage
title={<AccountBalance order={2} address={address} />}
title={<SolanaUiAccountBalance order={2} address={address} />}
rightAction={
<Group>
<ExplorerLink path={`account/${address}`} label={ellipsify(address.toString())} />
<AccountButtons address={address} />
<SolanaUiExplorerLink path={`account/${address}`} label={ellipsify(address.toString())} />
<SolanaUiAccountButtons address={address} />
</Group>
}
>
<UiStack>
<AccountTokens address={address} />
<AccountTransactions address={address} />
<SolanaUiAccountTokens address={address} />
<SolanaUiAccountTransactions address={address} />
</UiStack>
</UiPage>
)
Expand Down
12 changes: 10 additions & 2 deletions libs/web/solana/feature/src/lib/account/account-list-feature.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import { WalletButton } from '@pubkey-stack/web-solana-data-access'
import { Group } from '@mantine/core'
import { WalletButton } from '@pubkey-stack/web-solana-ui'
import { UiPage } from '@pubkey-ui/core'
import { useWallet } from '@solana/wallet-adapter-react'
import { Navigate } from 'react-router-dom'

Expand All @@ -9,5 +11,11 @@ export default function AccountListFeature() {
return <Navigate to={publicKey.toString()} replace />
}

return <WalletButton />
return (
<UiPage title="Connect your wallet to continue">
<Group justify="center">
<WalletButton size="xl" />
</Group>
</UiPage>
)
}
Loading

0 comments on commit 3986454

Please sign in to comment.