@usebutr/core 1.1.0 → 2.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md ADDED
@@ -0,0 +1,213 @@
1
+ # @usebutr/core
2
+
3
+ ## 2.0.1
4
+
5
+ ### Patch Changes
6
+
7
+ - [#179](https://github.com/pedroapfilho/usebutr/pull/179) [`bc5b58c`](https://github.com/pedroapfilho/usebutr/commit/bc5b58cd87601be38dbb77a14e16eaaa36e8f012) Thanks [@pedroapfilho](https://github.com/pedroapfilho)! - Include package READMEs, MIT licenses, and documentation and issue links on npm.
8
+
9
+ ## 2.0.0
10
+
11
+ ### Major Changes
12
+
13
+ - 9b1caa2: Correctness pass across the storage, hydration and connector layers. Several of
14
+ these change observable behaviour; the ones worth knowing about before upgrading:
15
+
16
+ **Breaking**
17
+
18
+ - `SuiWallet.signTransaction` now returns `{ bytes, signature }` instead of
19
+ `Uint8Array`. Sui's `executeTransactionBlock` needs both, and each connector
20
+ previously returned a different half, so the old value could not be broadcast
21
+ and a consumer could not tell which half they held. SVM and Bitcoin keep their
22
+ single-`Uint8Array` shape.
23
+ - `@usebutr/svm`'s `sendTx` returns the signature base58-encoded, matching the
24
+ WalletConnect namespace, the Ledger app, Solana explorers and
25
+ `getSignatureStatuses`. It previously returned base64.
26
+ - `@usebutr/sui`'s feature input types drop the `string` arm from
27
+ `transaction`; wallets only ever accepted the `toJSON()` form. Strings and BCS
28
+ bytes are now wrapped for you, so `sendTx` accepts strictly more than before.
29
+
30
+ **Behaviour fixes**
31
+
32
+ - `WalletStorage.setPool` and `removePoolEntry` could self-deadlock on a corrupt
33
+ pool payload, leaving `connectWallet` unresolved and every later pool write
34
+ jammed for the page's life. Both are fixed, and `readWalletSnapshot` now shares
35
+ one codec with `WalletStorage` so the server and client decodes cannot drift.
36
+ - A seeded (SSR) entry whose silent reconnect failed used to stay in the pool
37
+ backed by a placeholder connector forever, so `useSigner`/`useBalance`
38
+ reported an error and `useConnectionStatus` reported `"reconnecting"`
39
+ permanently. Those entries are now dropped.
40
+ - `useSigner` and `useBalance` stay `idle` for a wallet that is still
41
+ reconnecting instead of surfacing a placeholder rejection as `status: "error"`.
42
+ - `useConnectionStatus` lets a live `"connecting"`/`"error"` take precedence over
43
+ the derived `"reconnecting"`, so an in-flight attempt and a connection error
44
+ are no longer hidden. New `useIsReconnecting(connectorId?)` answers the
45
+ per-wallet question directly.
46
+ - A background restore no longer writes the connect-attempt status or steals
47
+ `activeConnectorId`, and a superseded `CONNECT_FAILED` no longer overwrites the
48
+ current attempt.
49
+ - An externally-disconnected connector is now torn down, not just dropped from
50
+ the pool, so a cached adapter is not reused while still holding a session.
51
+ - EVM: a malformed provider response is treated as absent rather than `""`, which
52
+ previously produced chain `eip155:0`, zero-length signatures, empty transaction
53
+ hashes and a confident `0 ETH`. `switchChain` gained the same-chain
54
+ short-circuit `sendTxToChain` already had.
55
+ - WalletConnect: accounts carry their own chain instead of all being stamped with
56
+ the active one, so a multi-chain session no longer returns a wrong-chain
57
+ address. One pairing now covers every configured namespace, the pairing URI
58
+ survives a reconnect, and concurrent connects share one pairing.
59
+ - Bitcoin: the sats-connect (Xverse) adapter honours `silent`, so a reload no
60
+ longer triggers an unsolicited approval prompt, and exposes the payment address
61
+ as its single account instead of also presenting the ordinals address as
62
+ spendable.
63
+ - Polkadot: the injected adapter actually delivers events to subscribers,
64
+ `switchChain` notifies like its Wallet Standard sibling, and chain resolution
65
+ prefers the mainnets rather than whatever the wallet listed first.
66
+ - Ledger: the device session is committed atomically, so a locked device no
67
+ longer leaves an open transport that reports itself connected, and concurrent
68
+ connects open one transport.
69
+ - SVM: `sendTxToChain` submits to the chain you asked for instead of the
70
+ adapter's current one, and rejects a chain the wallet does not advertise.
71
+ - `@usebutr/svm`'s `switchChain` capability now counts only `solana:` chains, so
72
+ a multi-namespace wallet no longer advertises a method that always throws.
73
+
74
+ **Testing**
75
+
76
+ - `createFakePersistence` is now the real `WalletStorage` over memory drivers
77
+ rather than a parallel implementation, so it inherits upsert semantics,
78
+ validation and JSON round-tripping. Two divergences are fixed as a result:
79
+ `setPool` upserts rather than replaces, and `clearAll` leaves the
80
+ user-disconnected flag alone.
81
+ - `createFakeConnectedWallet` rejects being given both an `adapter` and explicit
82
+ `addresses`/`accounts`, a combination whose halves could disagree.
83
+
84
+ ## 1.1.0
85
+
86
+ ### Minor Changes
87
+
88
+ - 8ecaf89: Close five gaps that made multi-chain integration harder than it needed to be.
89
+
90
+ **Group wallets by platform without writing the loop yourself.**
91
+ `groupByPlatform(items, getPlatform)` in `@usebutr/core` buckets any list into
92
+ a `Map<ChainPlatform, T[]>` keyed in `CHAIN_PLATFORMS` order with empty
93
+ platforms omitted, and `@usebutr/react` adds
94
+ `useDiscoveredWalletsByPlatform()` / `useConnectedWalletsByPlatform()` on top.
95
+ A multi-chain wallet announces one adapter per platform, so every app hitting
96
+ more than one chain was writing this bucketing by hand.
97
+
98
+ **`autoDiscovery` takes an allowlist array, and says something when it's empty.**
99
+ `autoDiscovery(["evm", "svm"])` now works alongside the object form and reads
100
+ as the allowlist it is. An options value that enables no platforms logs a
101
+ warning instead of silently discovering nothing: a list built at runtime that
102
+ comes back empty was otherwise indistinguishable from "no wallets installed".
103
+ The bare `autoDiscovery()` everything-path is unchanged and stays silent.
104
+
105
+ **`createFakeConnectedWallet` in `@usebutr/testing`.** Builds the
106
+ `{ account, accounts, connector }` pool entry that UI tests actually render,
107
+ with accounts constructed through `buildAccount` so the `<chain>:<address>` id
108
+ format is never restated in a fixture. Defaults to the platform's mainnet chain
109
+ and a deterministic address; pass `adapter` to wrap a connector you already
110
+ built.
111
+
112
+ **The icon sanitization contract is now on the type.** `Connector.icon` is
113
+ already run through `sanitizeIcon` at discovery, so it is a trimmed non-empty
114
+ string or `undefined`, safe to hand to `next/image` with no second call and no
115
+ `icon !== ""` guard. `ConnectorMeta.icon` documents the opposite: it is
116
+ consumer-supplied and not sanitized.
117
+
118
+ **`createSignInFlow` in `@usebutr/core`.** Wraps the nonce, capability gate,
119
+ signature, base64 encoding, and verification handshake that every wallet-auth
120
+ app writes identically. Solana wallets advertising `solana:signIn` take the
121
+ SIWS path automatically. It deliberately does not define a message format: pass
122
+ `buildMessage` to match your backend. Also re-exports the SVM SIWS types
123
+ (`SolanaSignInFeature`, `SolanaSignInInput`, `SolanaSignInOutput`) from
124
+ `@usebutr/svm`, which were defined but not exported.
125
+
126
+ ## 1.0.0
127
+
128
+ ### Major Changes
129
+
130
+ - f0a5116: **Breaking:** the `platform` field is gone from the `PlatformDiscoverer` type in `@usebutr/core`, and from the `evmDiscoverer`, `svmDiscoverer`, `suiDiscoverer`, `bitcoinDiscoverer` and `polkadotDiscoverer` objects that implement it. Nothing read it: the aggregator keys discoverers by `ChainPlatform` in its own registry, so the field only restated the key.
131
+
132
+ Migration: read the platform from the `KNOWN_DISCOVERERS` key in `@usebutr/wallets` (`Object.entries(KNOWN_DISCOVERERS)`), or from `adapter.chainPlatform` on a discovered adapter. Custom `PlatformDiscoverer` implementations must drop the `platform` property; keeping it is now an excess-property error.
133
+
134
+ - f0a5116: **Breaking:** the deprecated `Wallet` type alias is removed from `@usebutr/core`.
135
+
136
+ Migration: import `WalletBase` instead (`type Wallet = WalletBase` was all the alias ever was), or the per-platform surface you actually mean: `EvmWallet`, `SvmWallet`, `SuiWallet`, `BitcoinWallet`, `PolkadotWallet`.
137
+
138
+ ### Minor Changes
139
+
140
+ - 7887cf0: Add `bytesToBase58` and `base58ToBytes` to the shared encoding module, alongside the existing hex and base64 helpers. Base58 was hand-rolled in eight places across the connector packages and the demo apps; a single tested implementation removes the drift surface on Solana addresses and signatures.
141
+
142
+ ### Patch Changes
143
+
144
+ - 7887cf0: Split the 497-line `types/wallet.ts` into focused modules (platform, account, capabilities, connector, wallet, manager) behind the same barrel. Pure file motion: every exported name and type is unchanged.
145
+
146
+ ## 0.5.0
147
+
148
+ ### Minor Changes
149
+
150
+ - 4467a5e: Compare the adapter instance in `walletEqual` instead of `connector.id`, so selectors re-render when hydration swaps a shadow adapter for the live one. Previously an SSR consumer stayed pinned to the placeholder whose methods throw `ShadowConnectorError`.
151
+
152
+ `isShadowAdapter` and `ShadowConnectorError` are now exported from the package root.
153
+
154
+ ## 0.4.2
155
+
156
+ ### Patch Changes
157
+
158
+ - c1309ee: Validate persisted wallet data and WalletConnect responses with shared Zod schemas.
159
+
160
+ ## 0.4.1
161
+
162
+ ### Patch Changes
163
+
164
+ - 937dfae: Bump runtime dependency floors (`@wallet-standard/app` 1.1.1, `@ledgerhq/*` latest minors, `@walletconnect/universal-provider` 2.23.10) and modernize public type declarations from method signatures to property function types (oxlint `method-signature-style`). Type-level only — no runtime behavior change.
165
+
166
+ ## 0.4.0
167
+
168
+ ### Minor Changes
169
+
170
+ - b5322ae: Add shared byte-encoding utilities (`bytesToHex`, `bytesToHexPrefixed`,
171
+ `hexToBytes`, `base64ToBytes`, `bytesToBase64`) and consolidate the per-connector
172
+ copies onto them. Behavior preserved: prefixed (`0x`) and bare hex are distinct
173
+ variants so each chain keeps its existing output.
174
+
175
+ ### Patch Changes
176
+
177
+ - d5f32c7: Fix Polkadot wallet connections failing to persist and reconnect on reload.
178
+ The storage validators' chain-platform allowlist was missing `polkadot`, so
179
+ Polkadot pool entries were rejected on write — and because the write rejects
180
+ the whole batch, a co-connected sibling (e.g. Solana) could be dropped too.
181
+ The allowlist is now derived from a single `CHAIN_PLATFORMS` source of truth
182
+ shared with the `ChainPlatform` type, so the runtime checks can't drift from
183
+ the type again.
184
+ - a46eecd: Ship unminified ESM so downstream bundlers (Vite/esbuild dep pre-bundling) process the package correctly; fixes a ReferenceError in consumer dev servers. The consuming app minifies once at its own build.
185
+
186
+ ## 0.3.0
187
+
188
+ ### Minor Changes
189
+
190
+ - 886ee1d: Add Polkadot/Substrate support. New `@usebutr/polkadot` package discovers wallets via injectedWeb3 (polkadot-js, Talisman, SubWallet, Nova, Enkrypt) with a Wallet Standard `polkadot:*` fallback. `ChainPlatform` widens to include `"polkadot"`; `autoDiscovery({ polkadot: true })` and `CHAINS_BY_PLATFORM` now cover it. Message signing works via the injected `signer.signRaw`; transaction signing is delegated to the consumer through `getSigner()` (e.g. polkadot-api), matching butr's no-RPC posture.
191
+
192
+ ## 0.2.2
193
+
194
+ ### Patch Changes
195
+
196
+ - db5d7e9: Fix intermittent wallet disconnect on page reload. Two storage-write bugs caused a remembered connection to be erased:
197
+
198
+ - An external `disconnected` event (EIP-1193 emits `accountsChanged: []`) fired on a simple wallet **auto-lock**, not just on permission revocation — and the store persisted the resulting empty pool, wiping the saved connection on every lock. The store now mirrors the disconnect into reducer state (so the UI hides the wallet) but leaves storage untouched; the next hydrate retries and self-heals once the wallet is unlocked. Explicit `disconnectWallet` still evicts via `removePoolEntry`.
199
+ - A transient `eth_accounts: []` during eager restore (a locked wallet) was treated as a permanent failure and the storage entry was deleted. Hydration now preserves storage on a failed restore and reports it as `dropped` for telemetry only, so a reload retries.
200
+
201
+ Additionally, `WalletStorage.setPool` is now **additive** and serialized through an internal mutation queue, so concurrent fire-and-forget writes can't interleave their read-modify-write phases and clobber each other's entries. `connectWallet` / `disconnectWallet` now await their storage writes so callers can trust persistence has landed on the next line.
202
+
203
+ ## 0.2.1
204
+
205
+ ### Patch Changes
206
+
207
+ - f846e77: Wallet-announced icons are trimmed of surrounding whitespace on ingestion. Some wallets ship data-URI icons with a leading newline, which strict consumers reject — Next.js's `<Image>` throws because `src` must not start with a control character. `@usebutr/core` exports a `sanitizeIcon` helper; the EIP-6963 and Wallet Standard adapters apply it, and an all-whitespace icon now resolves to `undefined` rather than a blank string.
208
+
209
+ ## 0.2.0
210
+
211
+ ### Minor Changes
212
+
213
+ - b77a477: Persisted pool entries now require the `accounts` field. Entries written by older versions without it are dropped on read with a warning.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Pedro Filho
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,40 @@
1
+ # @usebutr/core
2
+
3
+ Core types, store, storage, and discovery seam for butr. No React, no protocols.
4
+
5
+ Part of [butr](https://www.usebutr.com), a multi-chain wallet discovery and
6
+ connection-state library. Your application owns the picker UI and chain client.
7
+
8
+ ## Install
9
+
10
+ ```bash
11
+ npm install @usebutr/core zustand
12
+ ```
13
+
14
+ The store works outside React. Add a discovery source or your own connector factory when wiring real wallets.
15
+
16
+ ## Usage
17
+
18
+ ```tsx
19
+ import { createWalletStore } from "@usebutr/core";
20
+
21
+ export const store = createWalletStore({
22
+ connectors: [],
23
+ createConnector: () => null,
24
+ });
25
+
26
+ // Read state from a non-React host.
27
+ const wallets = store.getState().pool;
28
+ console.log(wallets.size);
29
+ ```
30
+
31
+ ## Documentation
32
+
33
+ - [Package reference](https://docs.usebutr.com/api/core)
34
+ - [Getting started](https://docs.usebutr.com/getting-started/quickstart)
35
+ - [Examples and source](https://github.com/pedroapfilho/usebutr)
36
+ - [Report an issue](https://github.com/pedroapfilho/usebutr/issues)
37
+
38
+ ## License
39
+
40
+ [MIT](./LICENSE), copyright 2026 Pedro Filho.