Skip to content
This repository has been archived by the owner on Jun 15, 2024. It is now read-only.

Solid reactivity work #10

Open
wants to merge 2 commits into
base: solid-adapter
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions examples/solid-ts/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,12 @@
"@txnlab/use-wallet-solid": "workspace:*",
"@walletconnect/modal": "^2.6.2",
"@walletconnect/sign-client": "^2.10.2",
"algosdk": "^2.6.0",
"solid-js": "^1.8.7"
"algosdk": "^2.7.0",
"solid-js": "^1.8.11"
},
"devDependencies": {
"typescript": "^5.2.2",
"vite": "^5.0.8",
"vite-plugin-solid": "^2.8.0"
"vite": "^5.0.12",
"vite-plugin-solid": "^2.8.2"
}
}
56 changes: 50 additions & 6 deletions examples/solid-ts/src/Connect.tsx
Original file line number Diff line number Diff line change
@@ -1,22 +1,42 @@
import { NetworkId } from '@txnlab/use-wallet-js'
import { useWallet } from '@txnlab/use-wallet-solid'
import { For, Show } from 'solid-js'
import encoding from 'algosdk'

export function Connect() {
const { wallets } = useWallet()
const {
activeNetwork,
setActiveNetwork,
activeWallet,
activeWalletId,
walletStateMap,
activeWalletAccounts,
activeWalletAddresses,
activeWalletState,
activeAccount,
activeAddress,
algodClient,
manager
} = useWallet()

return (
<div>
<For each={wallets()}>
<For each={manager().wallets}>
{(wallet) => (
<div>
<p>{wallet.id}</p>
<h4>
{wallet.metadata.name}{' '}
<Show when={wallet.isActive} fallback="">
<Show when={wallet.id === activeWalletId()} fallback="">
[active]
</Show>
</h4>
<div class="wallet-buttons">
<button type="button" onClick={() => wallet.connect()} disabled={wallet.isConnected}>
<button
type="button"
onClick={() => wallet.connect()}
disabled={!!walletStateMap()[wallet.id]?.accounts.length}
>
Connect
</button>
<button
Expand All @@ -29,13 +49,15 @@ export function Connect() {
<button
type="button"
onClick={() => wallet.setActive()}
disabled={!wallet.isConnected || wallet.isActive}
disabled={
!walletStateMap()[wallet.id]?.accounts.length || wallet.id === activeWalletId()
}
>
Set Active
</button>
</div>

<Show when={wallet.isActive && wallet.accounts.length > 0}>
<Show when={wallet.id === activeWalletId() && wallet.accounts.length}>
<div>
<select
onChange={(event) => {
Expand All @@ -47,11 +69,33 @@ export function Connect() {
{(account) => <option value={account.address}>{account.address}</option>}
</For>
</select>
<p>wallet.id: {wallet.id}</p>
<p>wallet.metadata: {wallet.metadata.name}</p>
<span>wallet.icon: </span>
<img src={wallet.metadata.icon} height={24} width={24} />
<p>wallet.activeAccount: {wallet.activeAccount?.name}</p>
<p>wallet.accounts: {JSON.stringify(wallet.accounts)}</p>
</div>
</Show>
</div>
)}
</For>
<button onClick={() => setActiveNetwork(NetworkId.MAINNET)}>Set Mainnet</button>
<button onClick={() => setActiveNetwork(NetworkId.TESTNET)}>Set Testnet</button>
<p>activeNetwork: {activeNetwork()().toString()}</p>
<p>activeWalletId: {activeWalletId()}</p>
<p>activeWallet: {activeWallet()?.metadata.name}</p>
<p>activeWalletAccounts: {JSON.stringify(activeWalletAccounts())}</p>
<p>activeWalletAddresses: {activeWalletAddresses()?.join(', ')}</p>
<p>activeWalletState: {JSON.stringify(activeWalletState())}</p>
<p>activeAccount: {JSON.stringify(activeAccount())}</p>
<p>activeAddress: {activeAddress()}</p>
<p>algodClient int encoding: {algodClient().getIntEncoding()}</p>
<button onClick={() => algodClient().setIntEncoding(encoding.IntDecoding.SAFE)}>
Set Int encoding
</button>
<p>walletStateMap: {JSON.stringify(walletStateMap())}</p>
{/* <pre>manager: {JSON.stringify(manager(), null, 2)}</pre> */}
</div>
)
}
2 changes: 1 addition & 1 deletion packages/use-wallet-solid/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@
"devDependencies": {
"@solidjs/testing-library": "^0.8.5",
"algosdk": "^2.6.0",
"solid-js": "^1.8.8",
"solid-js": "^1.8.11",
"tsup": "^8.0.0",
"tsup-preset-solid": "^2.2.0",
"typescript": "^5.2.2"
Expand Down
123 changes: 73 additions & 50 deletions packages/use-wallet-solid/src/useWallet.ts
Original file line number Diff line number Diff line change
@@ -1,75 +1,69 @@
import { useStore } from '@tanstack/solid-store'
import { createMemo } from 'solid-js'
import { useWalletManager } from './WalletProvider'
import type { WalletAccount, WalletId, WalletMetadata } from '@txnlab/use-wallet-js'
import type { NetworkId, WalletAccount, WalletId, WalletMetadata } from '@txnlab/use-wallet-js'
import type algosdk from 'algosdk'

export interface Wallet {
id: string
metadata: WalletMetadata
accounts: WalletAccount[]
activeAccount: WalletAccount | null
isConnected: boolean
isActive: boolean
id: () => string
metadata: () => WalletMetadata
accounts: () => WalletAccount[]
activeAccount: () => WalletAccount | null
isConnected: () => boolean
isActive: () => boolean
connect: () => Promise<WalletAccount[]>
disconnect: () => Promise<void>
setActive: () => void
setActiveAccount: (address: string) => void
}

export function useWallet() {
const manager = useWalletManager()
// Good
const manager = createMemo(() => useWalletManager())

const algodClient: algosdk.Algodv2 = manager.algodClient

const walletStateMap = useStore(manager.store, (state) => {
// Good
const walletStateMap = useStore(manager().store, (state) => {
console.log('Running walletStateMap callback...', state.wallets)
return state.wallets
})
const activeWalletId = useStore(manager.store, (state) => {

// Good
const activeWalletId = useStore(manager().store, (state) => {
console.log('Running activeWalletId callback...', state.activeWallet)
return state.activeWallet
})

const wallets = createMemo(() => {
console.log('Recomputing wallets...')
const walletsMap = walletStateMap()
const activeId = activeWalletId()

return [...manager.wallets.values()].map((wallet): Wallet => {
const walletState = walletsMap[wallet.id]

const walletObject: Wallet = {
id: wallet.id,
metadata: wallet.metadata,
accounts: walletState?.accounts ?? [],
activeAccount: walletState?.activeAccount ?? null,
isConnected: !!walletState,
isActive: wallet.id === activeId,
connect: () => wallet.connect(),
disconnect: () => wallet.disconnect(),
setActive: () => wallet.setActive(),
setActiveAccount: (addr) => wallet.setActiveAccount(addr)
}

return walletObject
})
})

const activeWallet =
activeWalletId() !== null ? manager.getWallet(activeWalletId() as WalletId) || null : null
// Good
const activeWallet = () =>
activeWalletId() !== null ? manager().getWallet(activeWalletId() as WalletId) || null : null

const activeWalletState =
// Good
const activeWalletState = () =>
activeWalletId() !== null ? walletStateMap()[activeWalletId() as WalletId] || null : null

const activeWalletAccounts = activeWalletState?.accounts ?? null
const activeWalletAddresses = activeWalletAccounts?.map((account) => account.address) ?? null
const activeAccount = activeWalletState?.activeAccount ?? null
const activeAddress = activeAccount?.address ?? null
// Good
const activeWalletAccounts = () => activeWalletState()?.accounts ?? null

// Good
const activeWalletAddresses = () =>
activeWalletAccounts()?.map((account) => account.address) ?? null

// Good
const activeAccount = () => activeWalletState()?.activeAccount ?? null

// Good
const activeAddress = () => activeAccount()?.address ?? null

const activeNetwork = useStore(manager.store, (state) => state.activeNetwork)
const setActiveNetwork = manager.setActiveNetwork
// Good
const activeNetwork = () => useStore(manager().store, (state) => state.activeNetwork) // Check if this needs to be wrapped in a function so it doesn't have to called twice ()()

// Good
const setActiveNetwork = (network: NetworkId) => manager().setActiveNetwork(network)

// TODO: Not reactive when intDecoding is changed
const algodClient = createMemo(() => manager().algodClient)

// TODO: Needs to be set up and tested
const signTransactions = (
txnGroup: algosdk.Transaction[] | algosdk.Transaction[][] | Uint8Array[] | Uint8Array[][],
indexesToSign?: number[],
Expand All @@ -78,27 +72,56 @@ export function useWallet() {
if (!activeWallet) {
throw new Error('No active wallet')
}
return activeWallet.signTransactions(txnGroup, indexesToSign, returnGroup)
return activeWallet()?.signTransactions(txnGroup, indexesToSign, returnGroup)
}

// TODO: Need to be set up and tested
const transactionSigner = (txnGroup: algosdk.Transaction[], indexesToSign: number[]) => {
if (!activeWallet) {
throw new Error('No active wallet')
}
return activeWallet.transactionSigner(txnGroup, indexesToSign)
return activeWallet()?.transactionSigner(txnGroup, indexesToSign)
}

// TODO: Array doesn't react; consider removing
// const wallets = createMemo(() => {
// console.log('Recomputing wallets...')

// return [...manager().wallets.values()].map((wallet) => {
// const walletState = walletStateMap()[wallet.id]

// const walletObject: Wallet = {
// id: () => wallet.id,
// metadata: () => wallet.metadata,
// accounts: () => walletState?.accounts ?? [],
// activeAccount: () => walletState?.activeAccount ?? null,
// isConnected: () => !!walletState?.accounts.length,
// isActive: () => wallet.id === activeWalletId(),
// connect: () => wallet.connect(),
// disconnect: () => wallet.disconnect(),
// setActive: () => wallet.setActive(),
// setActiveAccount: (addr) => wallet.setActiveAccount(addr)
// }

// return walletObject
// })
// })

return {
wallets,
activeWalletId,
walletStateMap,
// wallets,
algodClient,
activeNetwork,
activeWallet,
activeWalletAccounts,
activeWalletAddresses,
activeWalletState,
activeAccount,
activeAddress,
setActiveNetwork,
signTransactions,
transactionSigner
transactionSigner,
manager
}
}
Loading
Loading