Conversation
|
Hey @PhearZero! Heads up: v5.0.0 stable is shipping shortly. Since this exploration predates the adapter-package split and the I know a lot has changed since this work was done. Leaving it open as a draft for post-5.0 discussion. |
|
Sounds good @drichar, I will take a look at the latest and get this back up and running 🕺. It should be largely non-breaking even though the surface touches a bit of everything. |
ed8fb96 to
7861a68
Compare
|
I thought I was going to create a new PR but decided to push back to this thread since the changes were not as drastic as I had thought. This PR simplifies it a bit more by not touching any adapters for now. As adapters adopt new account shapes, they will be resolved "automagically" to the user once they opt-in to the inferred types or explicit generics during construction. It's the pattern I've run into for ages, same one we are using in our Provider abstraction. (Astro has some really good examples as well for the inferred types in different areas of the framework) Amazing work on v5!! I am loving it!! |
feat: generic account types
Makes the account type generic across the stack: wallet state, store, manager, and the framework
hooks. Wallet adapters are untouched; every generic defaults to
WalletAccount, so existing appscompile and behave exactly as before. New capabilities are opt-in.
What
Generic wallet state (
packages/core/src/wallets/base.ts,types.ts):WalletState<T>andBaseWallet<TOptions, TType>carry the account type, withWalletAccountas the default.Adapters can adopt a custom account type later via the second type parameter.
Generic store (
packages/core/src/store.ts):State<T>,PersistedState<T>, and allmutations (
addWallet,setAccounts, ...) are generic over the account type. Mutations and theWalletStateMap/PersistedStatetypes are exported from the package root.Injectable store (
packages/core/src/manager.ts):new WalletManager({ options: { store } })adopts an externally created TanStack
Storeinstead of creating a private one. Each writer ownsits wallet keys: external entries survive hydration and stale-wallet cleanup, live entries win
over stale persisted ones, and construction order does not matter.
Typed manager:
WalletManager<TAccount>carries the union of its adapters' account types.WalletManager.create({ wallets })infers that union from the adapter configs (directconstruction cannot; TypeScript fixes the class parameter on the first array element), and
classic
new WalletManager<PQAccount | ClassicAccount>({ ... })declares it explicitly.Register(wagmi-style): each framework package (React, Vue, Solid, Svelte) exposes aRegisterinterface, the same pattern wagmi uses to link its config type to its hooks. An appdeclares its manager type once, next to where the manager is created, and every bare
useWallet()infers the account union with no generics or casts at the call site:Apps that don't register keep the base
WalletAccountdefault. The hooks take no typeparameter; the declaration is the single source of truth. The Vue plugin also accepts an
existing manager instance (
app.use(WalletManagerPlugin, manager)) sotypeof managerworksthere too.
Why
classic ones). Consumers need the full union statically visible so each account narrows through
a type guard instead of a cast.
entries without being overwritten.