@usebutr/evm 1.1.0 → 1.1.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 +177 -0
- package/LICENSE +21 -0
- package/README.md +39 -0
- package/dist/index.d.ts +16 -6
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +26 -19
- package/dist/index.js.map +1 -1
- package/package.json +20 -4
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
# @usebutr/evm
|
|
2
|
+
|
|
3
|
+
## 1.1.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
|
+
- Updated dependencies [[`bc5b58c`](https://github.com/pedroapfilho/usebutr/commit/bc5b58cd87601be38dbb77a14e16eaaa36e8f012)]:
|
|
9
|
+
- @usebutr/core@2.0.1
|
|
10
|
+
|
|
11
|
+
## 1.1.0
|
|
12
|
+
|
|
13
|
+
### Minor Changes
|
|
14
|
+
|
|
15
|
+
- 9b1caa2: Correctness pass across the storage, hydration and connector layers. Several of
|
|
16
|
+
these change observable behaviour; the ones worth knowing about before upgrading:
|
|
17
|
+
|
|
18
|
+
**Breaking**
|
|
19
|
+
|
|
20
|
+
- `SuiWallet.signTransaction` now returns `{ bytes, signature }` instead of
|
|
21
|
+
`Uint8Array`. Sui's `executeTransactionBlock` needs both, and each connector
|
|
22
|
+
previously returned a different half, so the old value could not be broadcast
|
|
23
|
+
and a consumer could not tell which half they held. SVM and Bitcoin keep their
|
|
24
|
+
single-`Uint8Array` shape.
|
|
25
|
+
- `@usebutr/svm`'s `sendTx` returns the signature base58-encoded, matching the
|
|
26
|
+
WalletConnect namespace, the Ledger app, Solana explorers and
|
|
27
|
+
`getSignatureStatuses`. It previously returned base64.
|
|
28
|
+
- `@usebutr/sui`'s feature input types drop the `string` arm from
|
|
29
|
+
`transaction`; wallets only ever accepted the `toJSON()` form. Strings and BCS
|
|
30
|
+
bytes are now wrapped for you, so `sendTx` accepts strictly more than before.
|
|
31
|
+
|
|
32
|
+
**Behaviour fixes**
|
|
33
|
+
|
|
34
|
+
- `WalletStorage.setPool` and `removePoolEntry` could self-deadlock on a corrupt
|
|
35
|
+
pool payload, leaving `connectWallet` unresolved and every later pool write
|
|
36
|
+
jammed for the page's life. Both are fixed, and `readWalletSnapshot` now shares
|
|
37
|
+
one codec with `WalletStorage` so the server and client decodes cannot drift.
|
|
38
|
+
- A seeded (SSR) entry whose silent reconnect failed used to stay in the pool
|
|
39
|
+
backed by a placeholder connector forever, so `useSigner`/`useBalance`
|
|
40
|
+
reported an error and `useConnectionStatus` reported `"reconnecting"`
|
|
41
|
+
permanently. Those entries are now dropped.
|
|
42
|
+
- `useSigner` and `useBalance` stay `idle` for a wallet that is still
|
|
43
|
+
reconnecting instead of surfacing a placeholder rejection as `status: "error"`.
|
|
44
|
+
- `useConnectionStatus` lets a live `"connecting"`/`"error"` take precedence over
|
|
45
|
+
the derived `"reconnecting"`, so an in-flight attempt and a connection error
|
|
46
|
+
are no longer hidden. New `useIsReconnecting(connectorId?)` answers the
|
|
47
|
+
per-wallet question directly.
|
|
48
|
+
- A background restore no longer writes the connect-attempt status or steals
|
|
49
|
+
`activeConnectorId`, and a superseded `CONNECT_FAILED` no longer overwrites the
|
|
50
|
+
current attempt.
|
|
51
|
+
- An externally-disconnected connector is now torn down, not just dropped from
|
|
52
|
+
the pool, so a cached adapter is not reused while still holding a session.
|
|
53
|
+
- EVM: a malformed provider response is treated as absent rather than `""`, which
|
|
54
|
+
previously produced chain `eip155:0`, zero-length signatures, empty transaction
|
|
55
|
+
hashes and a confident `0 ETH`. `switchChain` gained the same-chain
|
|
56
|
+
short-circuit `sendTxToChain` already had.
|
|
57
|
+
- WalletConnect: accounts carry their own chain instead of all being stamped with
|
|
58
|
+
the active one, so a multi-chain session no longer returns a wrong-chain
|
|
59
|
+
address. One pairing now covers every configured namespace, the pairing URI
|
|
60
|
+
survives a reconnect, and concurrent connects share one pairing.
|
|
61
|
+
- Bitcoin: the sats-connect (Xverse) adapter honours `silent`, so a reload no
|
|
62
|
+
longer triggers an unsolicited approval prompt, and exposes the payment address
|
|
63
|
+
as its single account instead of also presenting the ordinals address as
|
|
64
|
+
spendable.
|
|
65
|
+
- Polkadot: the injected adapter actually delivers events to subscribers,
|
|
66
|
+
`switchChain` notifies like its Wallet Standard sibling, and chain resolution
|
|
67
|
+
prefers the mainnets rather than whatever the wallet listed first.
|
|
68
|
+
- Ledger: the device session is committed atomically, so a locked device no
|
|
69
|
+
longer leaves an open transport that reports itself connected, and concurrent
|
|
70
|
+
connects open one transport.
|
|
71
|
+
- SVM: `sendTxToChain` submits to the chain you asked for instead of the
|
|
72
|
+
adapter's current one, and rejects a chain the wallet does not advertise.
|
|
73
|
+
- `@usebutr/svm`'s `switchChain` capability now counts only `solana:` chains, so
|
|
74
|
+
a multi-namespace wallet no longer advertises a method that always throws.
|
|
75
|
+
|
|
76
|
+
**Testing**
|
|
77
|
+
|
|
78
|
+
- `createFakePersistence` is now the real `WalletStorage` over memory drivers
|
|
79
|
+
rather than a parallel implementation, so it inherits upsert semantics,
|
|
80
|
+
validation and JSON round-tripping. Two divergences are fixed as a result:
|
|
81
|
+
`setPool` upserts rather than replaces, and `clearAll` leaves the
|
|
82
|
+
user-disconnected flag alone.
|
|
83
|
+
- `createFakeConnectedWallet` rejects being given both an `adapter` and explicit
|
|
84
|
+
`addresses`/`accounts`, a combination whose halves could disagree.
|
|
85
|
+
|
|
86
|
+
### Patch Changes
|
|
87
|
+
|
|
88
|
+
- Updated dependencies [9b1caa2]
|
|
89
|
+
- @usebutr/core@2.0.0
|
|
90
|
+
|
|
91
|
+
## 1.0.1
|
|
92
|
+
|
|
93
|
+
### Patch Changes
|
|
94
|
+
|
|
95
|
+
- Updated dependencies [8ecaf89]
|
|
96
|
+
- @usebutr/core@1.1.0
|
|
97
|
+
|
|
98
|
+
## 1.0.0
|
|
99
|
+
|
|
100
|
+
### Major Changes
|
|
101
|
+
|
|
102
|
+
- 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.
|
|
103
|
+
|
|
104
|
+
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.
|
|
105
|
+
|
|
106
|
+
### Patch Changes
|
|
107
|
+
|
|
108
|
+
- Updated dependencies [7887cf0]
|
|
109
|
+
- Updated dependencies [7887cf0]
|
|
110
|
+
- Updated dependencies [f0a5116]
|
|
111
|
+
- Updated dependencies [f0a5116]
|
|
112
|
+
- @usebutr/core@1.0.0
|
|
113
|
+
|
|
114
|
+
## 0.2.5
|
|
115
|
+
|
|
116
|
+
### Patch Changes
|
|
117
|
+
|
|
118
|
+
- Updated dependencies [4467a5e]
|
|
119
|
+
- @usebutr/core@0.5.0
|
|
120
|
+
|
|
121
|
+
## 0.2.4
|
|
122
|
+
|
|
123
|
+
### Patch Changes
|
|
124
|
+
|
|
125
|
+
- Updated dependencies [c1309ee]
|
|
126
|
+
- @usebutr/core@0.4.2
|
|
127
|
+
|
|
128
|
+
## 0.2.3
|
|
129
|
+
|
|
130
|
+
### Patch Changes
|
|
131
|
+
|
|
132
|
+
- 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.
|
|
133
|
+
- Updated dependencies [937dfae]
|
|
134
|
+
- @usebutr/core@0.4.1
|
|
135
|
+
|
|
136
|
+
## 0.2.2
|
|
137
|
+
|
|
138
|
+
### Patch Changes
|
|
139
|
+
|
|
140
|
+
- 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.
|
|
141
|
+
- Updated dependencies [b5322ae]
|
|
142
|
+
- Updated dependencies [d5f32c7]
|
|
143
|
+
- Updated dependencies [a46eecd]
|
|
144
|
+
- @usebutr/core@0.4.0
|
|
145
|
+
|
|
146
|
+
## 0.2.1
|
|
147
|
+
|
|
148
|
+
### Patch Changes
|
|
149
|
+
|
|
150
|
+
- Updated dependencies [886ee1d]
|
|
151
|
+
- @usebutr/core@0.3.0
|
|
152
|
+
|
|
153
|
+
## 0.2.0
|
|
154
|
+
|
|
155
|
+
### Minor Changes
|
|
156
|
+
|
|
157
|
+
- db5d7e9: The EIP-6963 adapter's `getBalance` now reads ERC20 balances. Called with no argument it returns the native ETH balance as before; called with a token address (`getBalance(tokenAddress)`) it reads `balanceOf` / `decimals` / `symbol` for the active account on the currently-connected chain via parallel `eth_call`s on the wallet's own provider (no separate RPC needed). Non-standard `bytes32` symbols are decoded best-effort.
|
|
158
|
+
|
|
159
|
+
### Patch Changes
|
|
160
|
+
|
|
161
|
+
- Updated dependencies [db5d7e9]
|
|
162
|
+
- @usebutr/core@0.2.2
|
|
163
|
+
|
|
164
|
+
## 0.1.2
|
|
165
|
+
|
|
166
|
+
### Patch Changes
|
|
167
|
+
|
|
168
|
+
- 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.
|
|
169
|
+
- Updated dependencies [f846e77]
|
|
170
|
+
- @usebutr/core@0.2.1
|
|
171
|
+
|
|
172
|
+
## 0.1.1
|
|
173
|
+
|
|
174
|
+
### Patch Changes
|
|
175
|
+
|
|
176
|
+
- Updated dependencies [b77a477]
|
|
177
|
+
- @usebutr/core@0.2.0
|
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,39 @@
|
|
|
1
|
+
# @usebutr/evm
|
|
2
|
+
|
|
3
|
+
EIP-1193 / EIP-6963 / injected wallet discovery + adapters for butr.
|
|
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/react @usebutr/core @usebutr/evm zustand
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
React 18+ is a peer dependency of the provider. Discovery does not render a connect modal; add your picker as the provider child.
|
|
15
|
+
|
|
16
|
+
## Usage
|
|
17
|
+
|
|
18
|
+
```tsx
|
|
19
|
+
import type { ReactNode } from "react";
|
|
20
|
+
import { createWalletSource } from "@usebutr/core";
|
|
21
|
+
import { discoverEvmAdapters } from "@usebutr/evm";
|
|
22
|
+
import { WalletManagerProvider } from "@usebutr/react";
|
|
23
|
+
|
|
24
|
+
const discovery = createWalletSource(discoverEvmAdapters);
|
|
25
|
+
export const WalletProvider = ({ children }: { children: ReactNode }) => (
|
|
26
|
+
<WalletManagerProvider discovery={discovery}>{children}</WalletManagerProvider>
|
|
27
|
+
);
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## Documentation
|
|
31
|
+
|
|
32
|
+
- [Package reference](https://docs.usebutr.com/api/evm)
|
|
33
|
+
- [Getting started](https://docs.usebutr.com/getting-started/quickstart)
|
|
34
|
+
- [Examples and source](https://github.com/pedroapfilho/usebutr)
|
|
35
|
+
- [Report an issue](https://github.com/pedroapfilho/usebutr/issues)
|
|
36
|
+
|
|
37
|
+
## License
|
|
38
|
+
|
|
39
|
+
[MIT](./LICENSE), copyright 2026 Pedro Filho.
|
package/dist/index.d.ts
CHANGED
|
@@ -1,19 +1,23 @@
|
|
|
1
|
-
import { ChainBase, PlatformDiscoverer, WalletAdapter, WalletCapabilities, bytesToHexPrefixed as bytesToHex, hexToBytes } from "@usebutr/core";
|
|
1
|
+
import { ChainBase, PlatformDiscoverer, WalletAdapter, WalletCapabilities, WalletSigner, bytesToHexPrefixed as bytesToHex, hexToBytes } from "@usebutr/core";
|
|
2
2
|
//#region src/eip1193.d.ts
|
|
3
3
|
/**
|
|
4
4
|
* Declared inline rather than taken from `viem`, which would expand butr's
|
|
5
5
|
* footprint. Loose on purpose: `request(...)` returns `unknown` and the
|
|
6
6
|
* `request*` helpers narrow it at the boundary.
|
|
7
7
|
*/
|
|
8
|
+
type Eip1193Object = {
|
|
9
|
+
[key: string]: Eip1193Value | undefined;
|
|
10
|
+
};
|
|
11
|
+
type Eip1193Value = bigint | boolean | number | string | null | Uint8Array | ReadonlyArray<Eip1193Value> | Eip1193Object;
|
|
8
12
|
type Eip1193RequestArgs = {
|
|
9
13
|
method: string;
|
|
10
|
-
params?: ReadonlyArray<
|
|
14
|
+
params?: ReadonlyArray<Eip1193Value> | Eip1193Object;
|
|
11
15
|
};
|
|
12
|
-
type Eip1193Listener = (...args: ReadonlyArray<
|
|
16
|
+
type Eip1193Listener = (...args: ReadonlyArray<Eip1193Value | undefined>) => void;
|
|
13
17
|
type Eip1193Provider = {
|
|
14
18
|
on: (event: string, listener: Eip1193Listener) => void;
|
|
15
19
|
removeListener: (event: string, listener: Eip1193Listener) => void;
|
|
16
|
-
request: (args: Eip1193RequestArgs) => Promise<
|
|
20
|
+
request: (args: Eip1193RequestArgs) => Promise<Eip1193Value | undefined>;
|
|
17
21
|
};
|
|
18
22
|
type Eip6963ProviderInfo = {
|
|
19
23
|
/** Data URI or absolute URL pointing at the wallet's icon. */
|
|
@@ -83,9 +87,15 @@ type InjectedDiscoveryOptions = {
|
|
|
83
87
|
settleMs?: number;
|
|
84
88
|
/** Override the global `window` reference (tests, iframes). */
|
|
85
89
|
target?: {
|
|
86
|
-
ethereum?:
|
|
90
|
+
ethereum?: Partial<Eip1193Provider>;
|
|
87
91
|
} | null;
|
|
88
92
|
};
|
|
93
|
+
declare global {
|
|
94
|
+
interface Window {
|
|
95
|
+
ethereum?: Partial<Eip1193Provider>;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
declare const isEip1193Provider: (value: WalletSigner | undefined) => value is Eip1193Provider;
|
|
89
99
|
/**
|
|
90
100
|
* Last-resort path for the long tail of EVM wallets that expose only
|
|
91
101
|
* `window.ethereum` and never announce via EIP-6963. The emitted adapter
|
|
@@ -171,5 +181,5 @@ declare module "@usebutr/core" {
|
|
|
171
181
|
}
|
|
172
182
|
}
|
|
173
183
|
//#endregion
|
|
174
|
-
export { ANNOUNCE_EVENT, EIP6963_RDNS_WITH_REQUEST_ACCOUNTS, EVM_CHAINS, EVM_CHAINS_LIST, type Eip1193Listener, type Eip1193Provider, type Eip1193RequestArgs, type Eip6963AnnounceEvent, type Eip6963CapabilityInput, type Eip6963ProviderDetail, type Eip6963ProviderInfo, GENERIC_INJECTED_ICON, type InjectedDiscoveryOptions, REQUEST_EVENT, buildEvmAdapter, bytesToHex, chainIdDecimalToHex, chainIdHexToDecimal, discoverEvmAdapters, discoverInjectedAdapter, evmDiscoverer, formatEther, hexToBytes, resolveEip6963Capabilities };
|
|
184
|
+
export { ANNOUNCE_EVENT, EIP6963_RDNS_WITH_REQUEST_ACCOUNTS, EVM_CHAINS, EVM_CHAINS_LIST, type Eip1193Listener, type Eip1193Object, type Eip1193Provider, type Eip1193RequestArgs, type Eip1193Value, type Eip6963AnnounceEvent, type Eip6963CapabilityInput, type Eip6963ProviderDetail, type Eip6963ProviderInfo, GENERIC_INJECTED_ICON, type InjectedDiscoveryOptions, REQUEST_EVENT, buildEvmAdapter, bytesToHex, chainIdDecimalToHex, chainIdHexToDecimal, discoverEvmAdapters, discoverInjectedAdapter, evmDiscoverer, formatEther, hexToBytes, isEip1193Provider, resolveEip6963Capabilities };
|
|
175
185
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","names":[],"sources":["../src/eip1193.ts","../src/eip6963.ts","../src/evm-balance.ts","../src/eip6963-adapter.ts","../src/injected.ts","../src/chains.ts","../src/capabilities.ts","../src/discoverer.ts","../src/signer-augmentation.ts"],"mappings":";;;;;;;KAMK;EACH;EACA,SAAS;;
|
|
1
|
+
{"version":3,"file":"index.d.ts","names":[],"sources":["../src/eip1193.ts","../src/eip6963.ts","../src/evm-balance.ts","../src/eip6963-adapter.ts","../src/injected.ts","../src/chains.ts","../src/capabilities.ts","../src/discoverer.ts","../src/signer-augmentation.ts"],"mappings":";;;;;;;KAMK;GAAmB,cAAc;;KACjC,2DAMD,aACA,cAAc,gBACd;KAEC;EACH;EACA,SAAS,cAAc,gBAAgB;;KAGpC,sBAAsB,MAAM,cAAc;KAE1C;EACH,KAAK,eAAe,UAAU;EAC9B,iBAAiB,eAAe,UAAU;EAC1C,UAAU,MAAM,uBAAuB,QAAQ;;KAG5C;;EAEH;;EAEA;;;EAGA;;EAEA;;KAGG;EACH,MAAM;EACN,UAAU;;KAGP,uBAAuB,YAAY;;;cC1ClC;cACA;KAED,mBAAmB,SAAS,eAAe,MAAM;KAEjD;;;;EAIH,SAAS;;;;;;;cAiDL,sBAAmB,WACZ,iBAAe,UACjB;;;cChCL,cAAW;;;cC0BX,sBAAmB;cACnB,sBAAmB;;;;;;cAoDnB,kBAAe,MAAU,qBAAmB,UAAY,oBAAkB;;;;;;;;cCtG1E;KAKD;;;;;;EAMH;;;;;EAKA;;EAEA;IAAW,WAAW,QAAQ;;;QAGxB;YAEI;IACR,WAAW,QAAQ;;;cAIjB,oBAAiB,OAAW,6BAA2B,SAAS;;;;;;cAmBhE,0BAAuB,YACf,SAAS,wBAAsB,UAClC;;;;;;;;cCpDL;;aAEF;aACA;aACA;aACA;;;aAEM;aAAmB;aAAc;aAAqB;;;aACvD;aAAiB;aAAyB;aAAqB;;;aAC1D;aAAgB;aAAkB;aAAqB;;;aACvD;aAAiB;aAAkB;aAAqB;;;aACzD;aAAkB;aAAiB;aAAqB;;;aACxD;aAAuB;aAAiB;aAAqB;;;cAGpE,iBAAiB,cAAc;;;cCpB/B,oCAAkC;KAInC;EAA2B;;cAE1B,6BAA0B,OAAW,2BAAyB;;;;;;;cCC9D,eAAe;;;;;;;;;YCAT;IACR,KAAK"}
|
package/dist/index.js
CHANGED
|
@@ -117,13 +117,24 @@ const readEvmBalance = async (provider, address, tokenAddress) => {
|
|
|
117
117
|
//#region src/eip6963-adapter.ts
|
|
118
118
|
const HEX_PREFIX = "0x";
|
|
119
119
|
const toStringArray = (value) => Array.isArray(value) ? value.filter((item) => typeof item === "string") : [];
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
120
|
+
const toEip1193Value = (value) => {
|
|
121
|
+
if (typeof value === "function") throw new TypeError("EVM transactions cannot contain functions");
|
|
122
|
+
if (Array.isArray(value)) return value.map(toEip1193Value);
|
|
123
|
+
if (value instanceof Uint8Array) return value;
|
|
124
|
+
if (typeof value === "object" && value !== null) {
|
|
125
|
+
const result = {};
|
|
126
|
+
for (const [key, nested] of Object.entries(value)) result[key] = nested === void 0 ? void 0 : toEip1193Value(nested);
|
|
127
|
+
return result;
|
|
128
|
+
}
|
|
129
|
+
return value;
|
|
130
|
+
};
|
|
131
|
+
const withFrom = (tx, from) => {
|
|
132
|
+
if (typeof tx === "string" || tx instanceof Uint8Array) return tx;
|
|
133
|
+
const result = {};
|
|
134
|
+
for (const [key, value] of Object.entries(tx)) result[key] = value === void 0 ? void 0 : toEip1193Value(value);
|
|
135
|
+
if (from !== void 0) result.from = from;
|
|
136
|
+
return result;
|
|
137
|
+
};
|
|
127
138
|
const chainIdHexToDecimal = (hex) => BigInt(hex).toString(10);
|
|
128
139
|
const chainIdDecimalToHex = (dec) => `${HEX_PREFIX}${BigInt(dec).toString(16)}`;
|
|
129
140
|
const buildEvmChain = (chainIdHex, walletName) => {
|
|
@@ -222,7 +233,7 @@ const buildEvmAdapter = (info, provider) => {
|
|
|
222
233
|
}
|
|
223
234
|
},
|
|
224
235
|
async sendTx(tx, account) {
|
|
225
|
-
const txWithFrom =
|
|
236
|
+
const txWithFrom = withFrom(tx, account?.walletAddress);
|
|
226
237
|
const hash = await requestString(provider, {
|
|
227
238
|
method: "eth_sendTransaction",
|
|
228
239
|
params: [txWithFrom]
|
|
@@ -240,7 +251,7 @@ const buildEvmAdapter = (info, provider) => {
|
|
|
240
251
|
});
|
|
241
252
|
cb?.();
|
|
242
253
|
}
|
|
243
|
-
const txWithFrom =
|
|
254
|
+
const txWithFrom = withFrom(tx, account?.walletAddress);
|
|
244
255
|
const hash = await requestString(provider, {
|
|
245
256
|
method: "eth_sendTransaction",
|
|
246
257
|
params: [txWithFrom]
|
|
@@ -323,13 +334,11 @@ const isEip6963AnnounceEvent = (event) => {
|
|
|
323
334
|
if (typeof detail !== "object" || detail === null) return false;
|
|
324
335
|
if (!("info" in detail) || !("provider" in detail)) return false;
|
|
325
336
|
const { info, provider } = detail;
|
|
326
|
-
return typeof info === "object" && info !== null && "rdns" in info && typeof info.rdns === "string" && typeof provider === "object" && provider !== null;
|
|
337
|
+
return typeof info === "object" && info !== null && "icon" in info && typeof info.icon === "string" && "name" in info && typeof info.name === "string" && "rdns" in info && typeof info.rdns === "string" && "uuid" in info && typeof info.uuid === "string" && typeof provider === "object" && provider !== null && "on" in provider && typeof provider.on === "function" && "removeListener" in provider && typeof provider.removeListener === "function" && "request" in provider && typeof provider.request === "function";
|
|
327
338
|
};
|
|
328
|
-
const isEventTarget = (value) => typeof value === "object" && value !== null && "addEventListener" in value && typeof value.addEventListener === "function";
|
|
329
339
|
const resolveTarget = (target) => {
|
|
330
340
|
if (target !== void 0) return target;
|
|
331
|
-
|
|
332
|
-
return isEventTarget(candidate) ? candidate : null;
|
|
341
|
+
return globalThis.window ?? null;
|
|
333
342
|
};
|
|
334
343
|
/**
|
|
335
344
|
* Spec: https://eips.ethereum.org/EIPS/eip-6963. Dedupe is by `info.rdns`
|
|
@@ -364,12 +373,10 @@ const discoverEvmAdapters = (onAdapter, options = {}) => {
|
|
|
364
373
|
*/
|
|
365
374
|
const GENERIC_INJECTED_ICON = "data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSJjdXJyZW50Q29sb3IiIHN0cm9rZS13aWR0aD0iMiIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIj48cGF0aCBkPSJNMjEgMTJWN0g1YTIgMiAwIDAgMSAwLTQgaDE0djQiLz48cGF0aCBkPSJNMyA1djE0YTIgMiAwIDAgMCAyIDJoMTZ2LTVNMjEgMTIgaC0zYTIgMiAwIDAgMC0yIDJ2MGEyIDIgMCAwIDAgMiAyaDN6Ii8+PC9zdmc+";
|
|
366
375
|
const DEFAULT_SETTLE_MS = 150;
|
|
367
|
-
const isEip1193Provider = (value) => typeof value === "
|
|
376
|
+
const isEip1193Provider = (value) => value !== void 0 && "on" in value && typeof value.on === "function" && "removeListener" in value && typeof value.removeListener === "function" && "request" in value && typeof value.request === "function";
|
|
368
377
|
const readEthereum = (target) => {
|
|
369
|
-
const host = target === void 0 ?
|
|
370
|
-
|
|
371
|
-
const eth = host.ethereum;
|
|
372
|
-
return isEip1193Provider(eth) ? eth : null;
|
|
378
|
+
const host = target === void 0 ? globalThis.window : target;
|
|
379
|
+
return isEip1193Provider(host?.ethereum) ? host.ethereum : null;
|
|
373
380
|
};
|
|
374
381
|
/**
|
|
375
382
|
* Last-resort path for the long tail of EVM wallets that expose only
|
|
@@ -462,5 +469,5 @@ const evmDiscoverer = {
|
|
|
462
469
|
};
|
|
463
470
|
|
|
464
471
|
//#endregion
|
|
465
|
-
export { ANNOUNCE_EVENT, EIP6963_RDNS_WITH_REQUEST_ACCOUNTS, EVM_CHAINS, EVM_CHAINS_LIST, GENERIC_INJECTED_ICON, REQUEST_EVENT, buildEvmAdapter, bytesToHex, chainIdDecimalToHex, chainIdHexToDecimal, discoverEvmAdapters, discoverInjectedAdapter, evmDiscoverer, formatEther, hexToBytes, resolveEip6963Capabilities };
|
|
472
|
+
export { ANNOUNCE_EVENT, EIP6963_RDNS_WITH_REQUEST_ACCOUNTS, EVM_CHAINS, EVM_CHAINS_LIST, GENERIC_INJECTED_ICON, REQUEST_EVENT, buildEvmAdapter, bytesToHex, chainIdDecimalToHex, chainIdHexToDecimal, discoverEvmAdapters, discoverInjectedAdapter, evmDiscoverer, formatEther, hexToBytes, isEip1193Provider, resolveEip6963Capabilities };
|
|
466
473
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":["HEX_PREFIX","hexToBytes","bytesToHex","hexToBytes"],"sources":["../src/capabilities.ts","../src/eip1193.ts","../src/evm-balance.ts","../src/eip6963-adapter.ts","../src/eip6963.ts","../src/injected.ts","../src/chains.ts","../src/discoverer.ts"],"sourcesContent":["import type { WalletCapabilities } from \"@usebutr/core\";\n\nconst EIP6963_RDNS_WITH_REQUEST_ACCOUNTS = new Set<string>([\n \"io.metamask\", // MetaMask: verified May 2026\n]);\n\ntype Eip6963CapabilityInput = { rdns: string };\n\nconst resolveEip6963Capabilities = (input: Eip6963CapabilityInput): WalletCapabilities => ({\n getBalance: true,\n getTransactionReceipt: true,\n requestAccounts: EIP6963_RDNS_WITH_REQUEST_ACCOUNTS.has(input.rdns),\n sendTransaction: true,\n signIn: false,\n signMessage: true,\n signTransaction: false,\n subscribe: true,\n switchAccount: false,\n switchChain: true,\n});\n\nexport type { Eip6963CapabilityInput };\nexport { EIP6963_RDNS_WITH_REQUEST_ACCOUNTS, resolveEip6963Capabilities };\n","/**\n * Declared inline rather than taken from `viem`, which would expand butr's\n * footprint. Loose on purpose: `request(...)` returns `unknown` and the\n * `request*` helpers narrow it at the boundary.\n */\n\ntype Eip1193RequestArgs = {\n method: string;\n params?: ReadonlyArray<unknown> | object;\n};\n\ntype Eip1193Listener = (...args: ReadonlyArray<unknown>) => void;\n\ntype Eip1193Provider = {\n on: (event: string, listener: Eip1193Listener) => void;\n removeListener: (event: string, listener: Eip1193Listener) => void;\n request: (args: Eip1193RequestArgs) => Promise<unknown>;\n};\n\ntype Eip6963ProviderInfo = {\n /** Data URI or absolute URL pointing at the wallet's icon. */\n icon: string;\n /** Human-readable wallet name shown in pickers. */\n name: string;\n /** Reverse-DNS identifier: `io.metamask`, `io.rabby`, `app.phantom`.\n * Stable across versions, unique per wallet, used as the pool key. */\n rdns: string;\n /** Per-page UUID generated by the wallet. Not stable across reloads. */\n uuid: string;\n};\n\ntype Eip6963ProviderDetail = {\n info: Eip6963ProviderInfo;\n provider: Eip1193Provider;\n};\n\ntype Eip6963AnnounceEvent = CustomEvent<Eip6963ProviderDetail>;\n\n/** `provider.request` is typed `unknown` by design; these helpers narrow\n * the well-known EVM RPC shapes at the boundary with runtime guards so\n * call sites stay assertion-free. A malformed response is reported as\n * `null` / `[]` rather than a blank value, so call sites that cannot\n * proceed without a real one fail instead of inventing a default. */\nconst requestString = async (\n provider: Eip1193Provider,\n args: Eip1193RequestArgs,\n): Promise<string | null> => {\n const result = await provider.request(args);\n return typeof result === \"string\" ? result : null;\n};\n\nconst requestStringArray = async (\n provider: Eip1193Provider,\n args: Eip1193RequestArgs,\n): Promise<Array<string>> => {\n const result = await provider.request(args);\n return Array.isArray(result)\n ? result.filter((item): item is string => typeof item === \"string\")\n : [];\n};\n\nexport { requestString, requestStringArray };\n\nexport type {\n Eip1193Listener,\n Eip1193Provider,\n Eip1193RequestArgs,\n Eip6963AnnounceEvent,\n Eip6963ProviderDetail,\n Eip6963ProviderInfo,\n};\n","import { hexToBytes } from \"@usebutr/core\";\n\nimport type { Eip1193Provider } from \"./eip1193\";\nimport { requestString } from \"./eip1193\";\n\nconst HEX_PREFIX = \"0x\";\nconst ETH_DECIMALS = 18n;\nconst ERC20_BALANCE_OF_SELECTOR = \"0x70a08231\";\nconst ERC20_DECIMALS_SELECTOR = \"0x313ce567\";\nconst ERC20_SYMBOL_SELECTOR = \"0x95d89b41\";\n\n/** A failed read must not render as a confident zero balance. */\nconst requireHex = (hex: string | null, label: string): string => {\n if (hex === null) {\n throw new Error(`Wallet returned a malformed ${label} response`);\n }\n return hex;\n};\n\nconst formatUnits = (raw: bigint, decimals: number): string => {\n if (decimals === 0) {\n return raw.toString();\n }\n const unit = 10n ** BigInt(decimals);\n const integer = raw / unit;\n const remainder = raw % unit;\n if (remainder === 0n) {\n return integer.toString();\n }\n const fraction = remainder.toString().padStart(decimals, \"0\").replace(/0+$/v, \"\");\n return `${integer}.${fraction}`;\n};\n\nconst formatEther = (wei: bigint): string => formatUnits(wei, Number(ETH_DECIMALS));\n\nconst padAddressForCall = (address: string): string =>\n address.replace(/^0x/v, \"\").toLowerCase().padStart(64, \"0\");\n\nconst decodeAbiString = (hex: string): string => {\n const clean = hex.startsWith(HEX_PREFIX) ? hex.slice(2) : hex;\n if (clean.length === 0) {\n return \"\";\n }\n if (clean.length >= 128) {\n const lengthHex = clean.slice(64, 128);\n const length = Number(BigInt(`0x${lengthHex}`));\n if (length > 0 && clean.length >= 128 + length * 2) {\n return new TextDecoder().decode(hexToBytes(clean.slice(128, 128 + length * 2)));\n }\n }\n const bytes = hexToBytes(clean.slice(0, 64));\n let end = bytes.length;\n while (end > 0 && bytes[end - 1] === 0) {\n end -= 1;\n }\n return new TextDecoder().decode(bytes.subarray(0, end));\n};\n\nconst readEvmBalance = async (\n provider: Eip1193Provider,\n address: string,\n tokenAddress?: string,\n) => {\n if (tokenAddress === undefined || tokenAddress === \"\") {\n const balanceHex = await requestString(provider, {\n method: \"eth_getBalance\",\n params: [address, \"latest\"],\n });\n const value = BigInt(requireHex(balanceHex, \"eth_getBalance\"));\n return {\n decimals: Number(ETH_DECIMALS),\n formatted: formatEther(value),\n symbol: \"ETH\",\n value,\n };\n }\n\n const [balanceHex, decimalsHex, symbolHex] = await Promise.all([\n requestString(provider, {\n method: \"eth_call\",\n params: [\n { data: `${ERC20_BALANCE_OF_SELECTOR}${padAddressForCall(address)}`, to: tokenAddress },\n \"latest\",\n ],\n }),\n requestString(provider, {\n method: \"eth_call\",\n params: [{ data: ERC20_DECIMALS_SELECTOR, to: tokenAddress }, \"latest\"],\n }),\n requestString(provider, {\n method: \"eth_call\",\n params: [{ data: ERC20_SYMBOL_SELECTOR, to: tokenAddress }, \"latest\"],\n }),\n ]);\n const value = BigInt(requireHex(balanceHex, \"balanceOf()\"));\n const decimals = Number(BigInt(requireHex(decimalsHex, \"decimals()\")));\n return {\n decimals,\n formatted: formatUnits(value, decimals),\n symbol: decodeAbiString(symbolHex ?? \"\"),\n value,\n };\n};\n\nexport { formatEther, readEvmBalance };\n","import type { Account, ChainBase, WalletAdapter } from \"@usebutr/core\";\nimport { bytesToHexPrefixed as bytesToHex, hexToBytes, sanitizeIcon } from \"@usebutr/core\";\n\nimport { resolveEip6963Capabilities } from \"./capabilities\";\nimport type { Eip1193Listener, Eip1193Provider, Eip6963ProviderInfo } from \"./eip1193\";\nimport { requestString, requestStringArray } from \"./eip1193\";\nimport { readEvmBalance } from \"./evm-balance\";\n\nconst HEX_PREFIX = \"0x\";\n\nconst toStringArray = (value: unknown): Array<string> =>\n Array.isArray(value) ? value.filter((item): item is string => typeof item === \"string\") : [];\n\n/** Merge a `from` address into a transaction object of unknown shape.\n * butr's `sendTx` accepts `tx: unknown` (viem/ethers/raw all differ);\n * when it's an object we overlay `from`, otherwise pass it through. */\nconst withFrom = (tx: unknown, from: string): unknown =>\n typeof tx === \"object\" && tx !== null ? { ...tx, from } : tx;\n\nconst chainIdHexToDecimal = (hex: string): string => BigInt(hex).toString(10);\nconst chainIdDecimalToHex = (dec: string): string => `${HEX_PREFIX}${BigInt(dec).toString(16)}`;\n\nconst buildEvmChain = (chainIdHex: string, walletName: string): ChainBase => {\n const reference = chainIdHexToDecimal(chainIdHex);\n return {\n id: `eip155:${reference}`,\n name: walletName,\n namespace: \"eip155\",\n reference,\n };\n};\n\nconst buildEvmAccount = (address: string, chain: ChainBase): Account => ({\n chain,\n id: `${chain.id}:${address.toLowerCase()}`,\n walletAddress: address,\n});\n\ntype AccountStateOptions = {\n accounts?: Array<string>;\n chainIdHex?: string;\n};\n\n/** Rejections propagate: `getAccount`/`getAccounts` surface the wallet's\n * own provider error, while the `subscribe` bridge swallows it because a\n * later event retries synchronization. */\nconst readAccountState = async (\n provider: Eip1193Provider,\n walletName: string,\n options: AccountStateOptions = {},\n) => {\n const accounts =\n options.accounts ?? (await requestStringArray(provider, { method: \"eth_accounts\" }));\n if (accounts.length === 0) {\n return null;\n }\n const chainIdHex =\n options.chainIdHex ?? (await requestString(provider, { method: \"eth_chainId\" }));\n if (chainIdHex === null) {\n throw new Error(\"Wallet returned a malformed eth_chainId response\");\n }\n const chain = buildEvmChain(chainIdHex, walletName);\n const builtAccounts = accounts.map((address) => buildEvmAccount(address, chain));\n const account = builtAccounts[0];\n return account === undefined ? null : { account, accounts: builtAccounts };\n};\n\n/**\n * `disconnect` calls `wallet_revokePermissions`, which many wallets don't\n * implement and silently ignore, so their own auto-reconnect may outlive it.\n * `getBalance()` labels the native balance `\"ETH\"` on every EVM chain.\n */\nconst buildEvmAdapter = (info: Eip6963ProviderInfo, provider: Eip1193Provider): WalletAdapter => {\n return {\n capabilities: resolveEip6963Capabilities({ rdns: info.rdns }),\n chainPlatform: \"evm\",\n\n async connect(opts) {\n if (opts?.silent === true) {\n const accounts = await requestStringArray(provider, {\n method: \"eth_accounts\",\n });\n if (accounts.length === 0) {\n throw new Error(\"No authorized accounts for silent reconnect\");\n }\n return;\n }\n await provider.request({ method: \"eth_requestAccounts\" });\n },\n\n async disconnect() {\n try {\n await provider.request({\n method: \"wallet_revokePermissions\",\n params: [{ eth_accounts: {} }],\n });\n } catch {\n // Many wallets don't implement wallet_revokePermissions yet;\n // not a failure.\n }\n },\n\n async getAccount() {\n const state = await readAccountState(provider, info.name);\n return state?.account ?? null;\n },\n\n async getAccounts() {\n const state = await readAccountState(provider, info.name);\n return state?.accounts ?? [];\n },\n\n async getBalance(mint) {\n const accounts = await requestStringArray(provider, { method: \"eth_accounts\" });\n const first = accounts[0];\n if (first === undefined) {\n throw new Error(\"No connected account\");\n }\n return readEvmBalance(provider, first, mint);\n },\n\n getSigner: () => Promise.resolve(provider),\n\n async getTransactionReceipt(tx) {\n const receipt = await provider.request({\n method: \"eth_getTransactionReceipt\",\n params: [tx],\n });\n if (receipt === null || typeof receipt !== \"object\" || !(\"status\" in receipt)) {\n return { status: \"Pending\" };\n }\n return { status: receipt.status === \"0x1\" ? \"Success\" : \"Error\" };\n },\n\n icon: sanitizeIcon(info.icon),\n id: info.rdns,\n name: info.name,\n\n async requestAccounts() {\n try {\n await provider.request({\n method: \"wallet_requestPermissions\",\n params: [{ eth_accounts: {} }],\n });\n } catch (error: unknown) {\n const outerCode =\n typeof error === \"object\" && error !== null && \"code\" in error ? error.code : undefined;\n const errData =\n typeof error === \"object\" && error !== null && \"data\" in error ? error.data : undefined;\n const originalError =\n typeof errData === \"object\" && errData !== null && \"originalError\" in errData\n ? errData.originalError\n : undefined;\n const innerCode =\n typeof originalError === \"object\" && originalError !== null && \"code\" in originalError\n ? originalError.code\n : undefined;\n const isMethodNotSupported =\n outerCode === 4200 || // EIP-1474 \"method not supported\"\n outerCode === -32_601 || // JSON-RPC \"method not found\"\n outerCode === -32_603 || // JSON-RPC \"internal error\" (Coinbase wraps -32604 here)\n innerCode === 4200 ||\n innerCode === -32_601 ||\n innerCode === -32_604; // Coinbase's custom \"method not supported\"\n if (isMethodNotSupported) {\n await provider.request({ method: \"eth_requestAccounts\" });\n return;\n }\n throw error;\n }\n },\n\n async sendTx(tx, account) {\n const txWithFrom = account ? withFrom(tx, account.walletAddress) : tx;\n const hash = await requestString(provider, {\n method: \"eth_sendTransaction\",\n params: [txWithFrom],\n });\n if (hash === null) {\n throw new Error(\"Wallet returned no transaction hash\");\n }\n return hash;\n },\n\n async sendTxToChain(tx, targetChainIdDecimal, account, cb) {\n const current = await requestString(provider, { method: \"eth_chainId\" });\n const targetHex = chainIdDecimalToHex(targetChainIdDecimal);\n if (current?.toLowerCase() !== targetHex.toLowerCase()) {\n await provider.request({\n method: \"wallet_switchEthereumChain\",\n params: [{ chainId: targetHex }],\n });\n cb?.();\n }\n const txWithFrom = account ? withFrom(tx, account.walletAddress) : tx;\n const hash = await requestString(provider, {\n method: \"eth_sendTransaction\",\n params: [txWithFrom],\n });\n if (hash === null) {\n throw new Error(\"Wallet returned no transaction hash\");\n }\n return hash;\n },\n\n async signMessage(msg, account) {\n let signer = account?.walletAddress;\n if (signer === undefined || signer === \"\") {\n const accounts = await requestStringArray(provider, { method: \"eth_accounts\" });\n signer = accounts[0];\n }\n if (signer === undefined || signer === \"\") {\n throw new Error(\"No connected account\");\n }\n const signatureHex = await requestString(provider, {\n method: \"personal_sign\",\n params: [bytesToHex(msg), signer],\n });\n if (signatureHex === null) {\n throw new Error(\"Wallet returned a malformed personal_sign response\");\n }\n return { signature: hexToBytes(signatureHex), signedMessage: msg };\n },\n\n subscribe(listener) {\n const synchronizeAccount = async (options?: AccountStateOptions) => {\n try {\n const state = await readAccountState(provider, info.name, options);\n if (state !== null) {\n listener({ ...state, type: \"accountChanged\" });\n }\n } catch {\n // EIP-1193 event reads are best-effort; a later event retries synchronization.\n }\n };\n\n const onAccountsChanged: Eip1193Listener = (...args) => {\n const accs = toStringArray(args[0]);\n if (accs.length === 0) {\n listener({ type: \"disconnected\" });\n return;\n }\n void synchronizeAccount({ accounts: accs });\n };\n\n const onChainChanged: Eip1193Listener = (...args) => {\n const [chainId] = args;\n // Some wallets emit a decimal number here instead of the EIP-1193\n // hex string; leaving it absent re-engages the eth_chainId read.\n const chainIdHex = typeof chainId === \"string\" && chainId.length > 0 ? chainId : undefined;\n void synchronizeAccount({ chainIdHex });\n };\n\n const onDisconnect: Eip1193Listener = () => {\n listener({ type: \"disconnected\" });\n };\n\n const onConnect: Eip1193Listener = () => {\n void synchronizeAccount();\n };\n\n provider.on(\"accountsChanged\", onAccountsChanged);\n provider.on(\"chainChanged\", onChainChanged);\n provider.on(\"connect\", onConnect);\n provider.on(\"disconnect\", onDisconnect);\n\n return () => {\n provider.removeListener(\"accountsChanged\", onAccountsChanged);\n provider.removeListener(\"chainChanged\", onChainChanged);\n provider.removeListener(\"connect\", onConnect);\n provider.removeListener(\"disconnect\", onDisconnect);\n };\n },\n\n async switchChain(chain) {\n const targetHex = chainIdDecimalToHex(chain.reference);\n const current = await requestString(provider, { method: \"eth_chainId\" });\n if (current?.toLowerCase() === targetHex.toLowerCase()) {\n return;\n }\n await provider.request({\n method: \"wallet_switchEthereumChain\",\n params: [{ chainId: targetHex }],\n });\n },\n };\n};\n\nexport { bytesToHexPrefixed as bytesToHex, hexToBytes } from \"@usebutr/core\";\nexport { formatEther } from \"./evm-balance\";\nexport { buildEvmAdapter, chainIdDecimalToHex, chainIdHexToDecimal };\n","import type { WalletAdapter } from \"@usebutr/core\";\n\nimport type { Eip6963AnnounceEvent, Eip6963ProviderInfo } from \"./eip1193\";\nimport { buildEvmAdapter } from \"./eip6963-adapter\";\n\nconst ANNOUNCE_EVENT = \"eip6963:announceProvider\";\nconst REQUEST_EVENT = \"eip6963:requestProvider\";\n\ntype AdapterCallback = (adapter: WalletAdapter, info: Eip6963ProviderInfo) => void;\n\ntype DiscoverOptions = {\n /** Event target to listen on. Defaults to `window` in browser/RN/\n * SSR'd environments; tests can pass a fresh `new EventTarget()` to\n * exercise the discovery loop without a DOM. */\n target?: EventTarget;\n};\n\nconst isEip6963AnnounceEvent = (event: Event): event is Eip6963AnnounceEvent => {\n if (!(\"detail\" in event)) {\n return false;\n }\n const detail: unknown = event.detail;\n if (typeof detail !== \"object\" || detail === null) {\n return false;\n }\n if (!(\"info\" in detail) || !(\"provider\" in detail)) {\n return false;\n }\n const { info, provider } = detail;\n return (\n typeof info === \"object\" &&\n info !== null &&\n \"rdns\" in info &&\n typeof info.rdns === \"string\" &&\n typeof provider === \"object\" &&\n provider !== null\n );\n};\n\nconst isEventTarget = (value: unknown): value is EventTarget =>\n typeof value === \"object\" &&\n value !== null &&\n \"addEventListener\" in value &&\n typeof value.addEventListener === \"function\";\n\nconst resolveTarget = (target?: EventTarget): EventTarget | null => {\n if (target !== undefined) {\n return target;\n }\n const candidate: unknown = (globalThis as { window?: unknown }).window;\n return isEventTarget(candidate) ? candidate : null;\n};\n\n/**\n * Spec: https://eips.ethereum.org/EIPS/eip-6963. Dedupe is by `info.rdns`\n * because `info.uuid` is regenerated per page load. The listener stays\n * attached for the session so wallets that boot late still register.\n */\nconst discoverEvmAdapters = (\n onAdapter: AdapterCallback,\n options: DiscoverOptions = {},\n): (() => void) => {\n const target = resolveTarget(options.target);\n if (!target) {\n return () => {};\n }\n\n const seen = new Set<string>();\n const handler = (event: Event) => {\n if (!isEip6963AnnounceEvent(event)) {\n return;\n }\n const { info, provider } = event.detail;\n if (info.rdns.length === 0) {\n return;\n }\n if (seen.has(info.rdns)) {\n return;\n }\n seen.add(info.rdns);\n onAdapter(buildEvmAdapter(info, provider), info);\n };\n\n target.addEventListener(ANNOUNCE_EVENT, handler);\n target.dispatchEvent(new Event(REQUEST_EVENT));\n\n return () => {\n target.removeEventListener(ANNOUNCE_EVENT, handler);\n };\n};\n\nexport { ANNOUNCE_EVENT, REQUEST_EVENT, discoverEvmAdapters };\n","import type { WalletAdapter } from \"@usebutr/core\";\n\nimport type { Eip1193Provider, Eip6963ProviderInfo } from \"./eip1193\";\nimport { buildEvmAdapter } from \"./eip6963-adapter\";\n\n/**\n * Generic wallet icon (a stylised purse SVG, ~600 bytes). Used as\n * the fallback icon when an injected provider has no EIP-6963 info.\n * Inline rather than a network fetch so the picker doesn't flicker.\n */\nconst GENERIC_INJECTED_ICON =\n \"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSJjdXJyZW50Q29sb3IiIHN0cm9rZS13aWR0aD0iMiIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIj48cGF0aCBkPSJNMjEgMTJWN0g1YTIgMiAwIDAgMSAwLTQgaDE0djQiLz48cGF0aCBkPSJNMyA1djE0YTIgMiAwIDAgMCAyIDJoMTZ2LTVNMjEgMTIgaC0zYTIgMiAwIDAgMC0yIDJ2MGEyIDIgMCAwIDAgMiAyaDN6Ii8+PC9zdmc+\";\n\nconst DEFAULT_SETTLE_MS = 150;\n\ntype InjectedDiscoveryOptions = {\n /**\n * Consulted before emitting: an already-registered EIP-6963 adapter means\n * the wallet is covered by the standards path and emitting would duplicate\n * it. Omit to always emit.\n */\n hasAnyEip6963Adapter?: () => boolean;\n /**\n * Most wallets announce within the first frame; 150ms leaves room for slow\n * announcements without stalling the picker.\n */\n settleMs?: number;\n /** Override the global `window` reference (tests, iframes). */\n target?: { ethereum?: unknown } | null;\n};\n\nconst isEip1193Provider = (value: unknown): value is Eip1193Provider =>\n typeof value === \"object\" &&\n value !== null &&\n \"request\" in value &&\n typeof value.request === \"function\";\n\nconst readEthereum = (target: InjectedDiscoveryOptions[\"target\"]): Eip1193Provider | null => {\n const globalWindow: unknown = typeof window === \"undefined\" ? null : window;\n const host: unknown = target === undefined ? globalWindow : target;\n if (typeof host !== \"object\" || host === null || !(\"ethereum\" in host)) {\n return null;\n }\n const eth: unknown = host.ethereum;\n return isEip1193Provider(eth) ? eth : null;\n};\n\n/**\n * Last-resort path for the long tail of EVM wallets that expose only\n * `window.ethereum` and never announce via EIP-6963. The emitted adapter\n * carries `rdns: \"injected:legacy\"` so consumers can tell it apart.\n */\nconst discoverInjectedAdapter = (\n onAdapter: (adapter: WalletAdapter) => void,\n options: InjectedDiscoveryOptions = {},\n): (() => void) => {\n const settleMs = options.settleMs ?? DEFAULT_SETTLE_MS;\n let cancelled = false;\n const timer = setTimeout(() => {\n if (cancelled) {\n return;\n }\n if (options.hasAnyEip6963Adapter?.() === true) {\n return;\n }\n const provider = readEthereum(options.target);\n if (provider === null) {\n return;\n }\n const info: Eip6963ProviderInfo = {\n icon: GENERIC_INJECTED_ICON,\n name: \"Browser wallet\",\n rdns: \"injected:legacy\",\n uuid: \"injected:legacy\",\n };\n onAdapter(buildEvmAdapter(info, provider));\n }, settleMs);\n\n return () => {\n cancelled = true;\n clearTimeout(timer);\n };\n};\n\nexport type { InjectedDiscoveryOptions };\nexport { GENERIC_INJECTED_ICON, discoverInjectedAdapter };\n","import type { ChainBase } from \"@usebutr/core\";\n\n/**\n * Common EVM chain registry keyed by CAIP-2 id. Useful for chain-\n * switcher UIs. butr itself doesn't read this: `Connector.switchChain`\n * accepts any `ChainBase`.\n */\nconst EVM_CHAINS = {\n arbitrum: {\n id: \"eip155:42161\",\n name: \"Arbitrum One\",\n namespace: \"eip155\",\n reference: \"42161\",\n },\n base: { id: \"eip155:8453\", name: \"Base\", namespace: \"eip155\", reference: \"8453\" },\n bsc: { id: \"eip155:56\", name: \"BNB Smart Chain\", namespace: \"eip155\", reference: \"56\" },\n ethereum: { id: \"eip155:1\", name: \"Ethereum\", namespace: \"eip155\", reference: \"1\" },\n optimism: { id: \"eip155:10\", name: \"Optimism\", namespace: \"eip155\", reference: \"10\" },\n polygon: { id: \"eip155:137\", name: \"Polygon\", namespace: \"eip155\", reference: \"137\" },\n sepolia: { id: \"eip155:11155111\", name: \"Sepolia\", namespace: \"eip155\", reference: \"11155111\" },\n} as const satisfies Record<string, ChainBase>;\n\nconst EVM_CHAINS_LIST: ReadonlyArray<ChainBase> = Object.values(EVM_CHAINS);\n\nexport { EVM_CHAINS, EVM_CHAINS_LIST };\n","import type { PlatformDiscoverer } from \"@usebutr/core\";\n\nimport { discoverEvmAdapters } from \"./eip6963\";\nimport { discoverInjectedAdapter } from \"./injected\";\n\n/**\n * EIP-6963 is primary; the legacy `window.ethereum` fallback defers until\n * EIP-6963 has had a chance to fire.\n */\nconst evmDiscoverer: PlatformDiscoverer = {\n fallback: {\n subscribe: (onAdapter, opts) =>\n discoverInjectedAdapter(onAdapter, {\n hasAnyEip6963Adapter: opts.hasAnyPrimaryAdapter,\n }),\n },\n subscribe: discoverEvmAdapters,\n};\n\nexport { evmDiscoverer };\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","names":["HEX_PREFIX","hexToBytes","bytesToHex","hexToBytes"],"sources":["../src/capabilities.ts","../src/eip1193.ts","../src/evm-balance.ts","../src/eip6963-adapter.ts","../src/eip6963.ts","../src/injected.ts","../src/chains.ts","../src/discoverer.ts"],"sourcesContent":["import type { WalletCapabilities } from \"@usebutr/core\";\n\nconst EIP6963_RDNS_WITH_REQUEST_ACCOUNTS = new Set<string>([\n \"io.metamask\", // MetaMask: verified May 2026\n]);\n\ntype Eip6963CapabilityInput = { rdns: string };\n\nconst resolveEip6963Capabilities = (input: Eip6963CapabilityInput): WalletCapabilities => ({\n getBalance: true,\n getTransactionReceipt: true,\n requestAccounts: EIP6963_RDNS_WITH_REQUEST_ACCOUNTS.has(input.rdns),\n sendTransaction: true,\n signIn: false,\n signMessage: true,\n signTransaction: false,\n subscribe: true,\n switchAccount: false,\n switchChain: true,\n});\n\nexport type { Eip6963CapabilityInput };\nexport { EIP6963_RDNS_WITH_REQUEST_ACCOUNTS, resolveEip6963Capabilities };\n","/**\n * Declared inline rather than taken from `viem`, which would expand butr's\n * footprint. Loose on purpose: `request(...)` returns `unknown` and the\n * `request*` helpers narrow it at the boundary.\n */\n\ntype Eip1193Object = { [key: string]: Eip1193Value | undefined };\ntype Eip1193Value =\n | bigint\n | boolean\n | number\n | string\n | null\n | Uint8Array\n | ReadonlyArray<Eip1193Value>\n | Eip1193Object;\n\ntype Eip1193RequestArgs = {\n method: string;\n params?: ReadonlyArray<Eip1193Value> | Eip1193Object;\n};\n\ntype Eip1193Listener = (...args: ReadonlyArray<Eip1193Value | undefined>) => void;\n\ntype Eip1193Provider = {\n on: (event: string, listener: Eip1193Listener) => void;\n removeListener: (event: string, listener: Eip1193Listener) => void;\n request: (args: Eip1193RequestArgs) => Promise<Eip1193Value | undefined>;\n};\n\ntype Eip6963ProviderInfo = {\n /** Data URI or absolute URL pointing at the wallet's icon. */\n icon: string;\n /** Human-readable wallet name shown in pickers. */\n name: string;\n /** Reverse-DNS identifier: `io.metamask`, `io.rabby`, `app.phantom`.\n * Stable across versions, unique per wallet, used as the pool key. */\n rdns: string;\n /** Per-page UUID generated by the wallet. Not stable across reloads. */\n uuid: string;\n};\n\ntype Eip6963ProviderDetail = {\n info: Eip6963ProviderInfo;\n provider: Eip1193Provider;\n};\n\ntype Eip6963AnnounceEvent = CustomEvent<Eip6963ProviderDetail>;\n\n/** `provider.request` is typed `unknown` by design; these helpers narrow\n * the well-known EVM RPC shapes at the boundary with runtime guards so\n * call sites stay assertion-free. A malformed response is reported as\n * `null` / `[]` rather than a blank value, so call sites that cannot\n * proceed without a real one fail instead of inventing a default. */\nconst requestString = async (\n provider: Eip1193Provider,\n args: Eip1193RequestArgs,\n): Promise<string | null> => {\n const result = await provider.request(args);\n return typeof result === \"string\" ? result : null;\n};\n\nconst requestStringArray = async (\n provider: Eip1193Provider,\n args: Eip1193RequestArgs,\n): Promise<Array<string>> => {\n const result = await provider.request(args);\n return Array.isArray(result)\n ? result.filter((item): item is string => typeof item === \"string\")\n : [];\n};\n\nexport { requestString, requestStringArray };\n\nexport type {\n Eip1193Listener,\n Eip1193Object,\n Eip1193Provider,\n Eip1193RequestArgs,\n Eip1193Value,\n Eip6963AnnounceEvent,\n Eip6963ProviderDetail,\n Eip6963ProviderInfo,\n};\n","import { hexToBytes } from \"@usebutr/core\";\n\nimport type { Eip1193Provider } from \"./eip1193\";\nimport { requestString } from \"./eip1193\";\n\nconst HEX_PREFIX = \"0x\";\nconst ETH_DECIMALS = 18n;\nconst ERC20_BALANCE_OF_SELECTOR = \"0x70a08231\";\nconst ERC20_DECIMALS_SELECTOR = \"0x313ce567\";\nconst ERC20_SYMBOL_SELECTOR = \"0x95d89b41\";\n\n/** A failed read must not render as a confident zero balance. */\nconst requireHex = (hex: string | null, label: string): string => {\n if (hex === null) {\n throw new Error(`Wallet returned a malformed ${label} response`);\n }\n return hex;\n};\n\nconst formatUnits = (raw: bigint, decimals: number): string => {\n if (decimals === 0) {\n return raw.toString();\n }\n const unit = 10n ** BigInt(decimals);\n const integer = raw / unit;\n const remainder = raw % unit;\n if (remainder === 0n) {\n return integer.toString();\n }\n const fraction = remainder.toString().padStart(decimals, \"0\").replace(/0+$/v, \"\");\n return `${integer}.${fraction}`;\n};\n\nconst formatEther = (wei: bigint): string => formatUnits(wei, Number(ETH_DECIMALS));\n\nconst padAddressForCall = (address: string): string =>\n address.replace(/^0x/v, \"\").toLowerCase().padStart(64, \"0\");\n\nconst decodeAbiString = (hex: string): string => {\n const clean = hex.startsWith(HEX_PREFIX) ? hex.slice(2) : hex;\n if (clean.length === 0) {\n return \"\";\n }\n if (clean.length >= 128) {\n const lengthHex = clean.slice(64, 128);\n const length = Number(BigInt(`0x${lengthHex}`));\n if (length > 0 && clean.length >= 128 + length * 2) {\n return new TextDecoder().decode(hexToBytes(clean.slice(128, 128 + length * 2)));\n }\n }\n const bytes = hexToBytes(clean.slice(0, 64));\n let end = bytes.length;\n while (end > 0 && bytes[end - 1] === 0) {\n end -= 1;\n }\n return new TextDecoder().decode(bytes.subarray(0, end));\n};\n\nconst readEvmBalance = async (\n provider: Eip1193Provider,\n address: string,\n tokenAddress?: string,\n) => {\n if (tokenAddress === undefined || tokenAddress === \"\") {\n const balanceHex = await requestString(provider, {\n method: \"eth_getBalance\",\n params: [address, \"latest\"],\n });\n const value = BigInt(requireHex(balanceHex, \"eth_getBalance\"));\n return {\n decimals: Number(ETH_DECIMALS),\n formatted: formatEther(value),\n symbol: \"ETH\",\n value,\n };\n }\n\n const [balanceHex, decimalsHex, symbolHex] = await Promise.all([\n requestString(provider, {\n method: \"eth_call\",\n params: [\n { data: `${ERC20_BALANCE_OF_SELECTOR}${padAddressForCall(address)}`, to: tokenAddress },\n \"latest\",\n ],\n }),\n requestString(provider, {\n method: \"eth_call\",\n params: [{ data: ERC20_DECIMALS_SELECTOR, to: tokenAddress }, \"latest\"],\n }),\n requestString(provider, {\n method: \"eth_call\",\n params: [{ data: ERC20_SYMBOL_SELECTOR, to: tokenAddress }, \"latest\"],\n }),\n ]);\n const value = BigInt(requireHex(balanceHex, \"balanceOf()\"));\n const decimals = Number(BigInt(requireHex(decimalsHex, \"decimals()\")));\n return {\n decimals,\n formatted: formatUnits(value, decimals),\n symbol: decodeAbiString(symbolHex ?? \"\"),\n value,\n };\n};\n\nexport { formatEther, readEvmBalance };\n","import type {\n Account,\n ChainBase,\n TransactionInput,\n TransactionValue,\n WalletAdapter,\n} from \"@usebutr/core\";\nimport { bytesToHexPrefixed as bytesToHex, hexToBytes, sanitizeIcon } from \"@usebutr/core\";\n\nimport { resolveEip6963Capabilities } from \"./capabilities\";\nimport type {\n Eip1193Listener,\n Eip1193Object,\n Eip1193Provider,\n Eip1193Value,\n Eip6963ProviderInfo,\n} from \"./eip1193\";\nimport { requestString, requestStringArray } from \"./eip1193\";\nimport { readEvmBalance } from \"./evm-balance\";\n\nconst HEX_PREFIX = \"0x\";\n\nconst toStringArray = (value: Eip1193Value | undefined): Array<string> =>\n Array.isArray(value) ? value.filter((item): item is string => typeof item === \"string\") : [];\n\nconst toEip1193Value = (value: TransactionValue): Eip1193Value => {\n if (typeof value === \"function\") {\n throw new TypeError(\"EVM transactions cannot contain functions\");\n }\n if (Array.isArray(value)) {\n return value.map(toEip1193Value);\n }\n if (value instanceof Uint8Array) {\n return value;\n }\n if (typeof value === \"object\" && value !== null) {\n const result: Eip1193Object = {};\n for (const [key, nested] of Object.entries(value)) {\n result[key] = nested === undefined ? undefined : toEip1193Value(nested);\n }\n return result;\n }\n return value;\n};\n\nconst withFrom = (tx: TransactionInput, from?: string): Eip1193Value => {\n if (typeof tx === \"string\" || tx instanceof Uint8Array) {\n return tx;\n }\n const result: Eip1193Object = {};\n for (const [key, value] of Object.entries(tx)) {\n result[key] = value === undefined ? undefined : toEip1193Value(value);\n }\n if (from !== undefined) {\n result.from = from;\n }\n return result;\n};\n\nconst chainIdHexToDecimal = (hex: string): string => BigInt(hex).toString(10);\nconst chainIdDecimalToHex = (dec: string): string => `${HEX_PREFIX}${BigInt(dec).toString(16)}`;\n\nconst buildEvmChain = (chainIdHex: string, walletName: string): ChainBase => {\n const reference = chainIdHexToDecimal(chainIdHex);\n return {\n id: `eip155:${reference}`,\n name: walletName,\n namespace: \"eip155\",\n reference,\n };\n};\n\nconst buildEvmAccount = (address: string, chain: ChainBase): Account => ({\n chain,\n id: `${chain.id}:${address.toLowerCase()}`,\n walletAddress: address,\n});\n\ntype AccountStateOptions = {\n accounts?: Array<string>;\n chainIdHex?: string;\n};\n\n/** Rejections propagate: `getAccount`/`getAccounts` surface the wallet's\n * own provider error, while the `subscribe` bridge swallows it because a\n * later event retries synchronization. */\nconst readAccountState = async (\n provider: Eip1193Provider,\n walletName: string,\n options: AccountStateOptions = {},\n) => {\n const accounts =\n options.accounts ?? (await requestStringArray(provider, { method: \"eth_accounts\" }));\n if (accounts.length === 0) {\n return null;\n }\n const chainIdHex =\n options.chainIdHex ?? (await requestString(provider, { method: \"eth_chainId\" }));\n if (chainIdHex === null) {\n throw new Error(\"Wallet returned a malformed eth_chainId response\");\n }\n const chain = buildEvmChain(chainIdHex, walletName);\n const builtAccounts = accounts.map((address) => buildEvmAccount(address, chain));\n const account = builtAccounts[0];\n return account === undefined ? null : { account, accounts: builtAccounts };\n};\n\n/**\n * `disconnect` calls `wallet_revokePermissions`, which many wallets don't\n * implement and silently ignore, so their own auto-reconnect may outlive it.\n * `getBalance()` labels the native balance `\"ETH\"` on every EVM chain.\n */\nconst buildEvmAdapter = (info: Eip6963ProviderInfo, provider: Eip1193Provider): WalletAdapter => {\n return {\n capabilities: resolveEip6963Capabilities({ rdns: info.rdns }),\n chainPlatform: \"evm\",\n\n async connect(opts) {\n if (opts?.silent === true) {\n const accounts = await requestStringArray(provider, {\n method: \"eth_accounts\",\n });\n if (accounts.length === 0) {\n throw new Error(\"No authorized accounts for silent reconnect\");\n }\n return;\n }\n await provider.request({ method: \"eth_requestAccounts\" });\n },\n\n async disconnect() {\n try {\n await provider.request({\n method: \"wallet_revokePermissions\",\n params: [{ eth_accounts: {} }],\n });\n } catch {\n // Many wallets don't implement wallet_revokePermissions yet;\n // not a failure.\n }\n },\n\n async getAccount() {\n const state = await readAccountState(provider, info.name);\n return state?.account ?? null;\n },\n\n async getAccounts() {\n const state = await readAccountState(provider, info.name);\n return state?.accounts ?? [];\n },\n\n async getBalance(mint) {\n const accounts = await requestStringArray(provider, { method: \"eth_accounts\" });\n const first = accounts[0];\n if (first === undefined) {\n throw new Error(\"No connected account\");\n }\n return readEvmBalance(provider, first, mint);\n },\n\n getSigner: () => Promise.resolve(provider),\n\n async getTransactionReceipt(tx) {\n const receipt = await provider.request({\n method: \"eth_getTransactionReceipt\",\n params: [tx],\n });\n if (receipt === null || typeof receipt !== \"object\" || !(\"status\" in receipt)) {\n return { status: \"Pending\" };\n }\n return { status: receipt.status === \"0x1\" ? \"Success\" : \"Error\" };\n },\n\n icon: sanitizeIcon(info.icon),\n id: info.rdns,\n name: info.name,\n\n async requestAccounts() {\n try {\n await provider.request({\n method: \"wallet_requestPermissions\",\n params: [{ eth_accounts: {} }],\n });\n } catch (error) {\n const outerCode =\n typeof error === \"object\" && error !== null && \"code\" in error ? error.code : undefined;\n const errData =\n typeof error === \"object\" && error !== null && \"data\" in error ? error.data : undefined;\n const originalError =\n typeof errData === \"object\" && errData !== null && \"originalError\" in errData\n ? errData.originalError\n : undefined;\n const innerCode =\n typeof originalError === \"object\" && originalError !== null && \"code\" in originalError\n ? originalError.code\n : undefined;\n const isMethodNotSupported =\n outerCode === 4200 || // EIP-1474 \"method not supported\"\n outerCode === -32_601 || // JSON-RPC \"method not found\"\n outerCode === -32_603 || // JSON-RPC \"internal error\" (Coinbase wraps -32604 here)\n innerCode === 4200 ||\n innerCode === -32_601 ||\n innerCode === -32_604; // Coinbase's custom \"method not supported\"\n if (isMethodNotSupported) {\n await provider.request({ method: \"eth_requestAccounts\" });\n return;\n }\n throw error;\n }\n },\n\n async sendTx(tx, account) {\n const txWithFrom = withFrom(tx, account?.walletAddress);\n const hash = await requestString(provider, {\n method: \"eth_sendTransaction\",\n params: [txWithFrom],\n });\n if (hash === null) {\n throw new Error(\"Wallet returned no transaction hash\");\n }\n return hash;\n },\n\n async sendTxToChain(tx, targetChainIdDecimal, account, cb) {\n const current = await requestString(provider, { method: \"eth_chainId\" });\n const targetHex = chainIdDecimalToHex(targetChainIdDecimal);\n if (current?.toLowerCase() !== targetHex.toLowerCase()) {\n await provider.request({\n method: \"wallet_switchEthereumChain\",\n params: [{ chainId: targetHex }],\n });\n cb?.();\n }\n const txWithFrom = withFrom(tx, account?.walletAddress);\n const hash = await requestString(provider, {\n method: \"eth_sendTransaction\",\n params: [txWithFrom],\n });\n if (hash === null) {\n throw new Error(\"Wallet returned no transaction hash\");\n }\n return hash;\n },\n\n async signMessage(msg, account) {\n let signer = account?.walletAddress;\n if (signer === undefined || signer === \"\") {\n const accounts = await requestStringArray(provider, { method: \"eth_accounts\" });\n signer = accounts[0];\n }\n if (signer === undefined || signer === \"\") {\n throw new Error(\"No connected account\");\n }\n const signatureHex = await requestString(provider, {\n method: \"personal_sign\",\n params: [bytesToHex(msg), signer],\n });\n if (signatureHex === null) {\n throw new Error(\"Wallet returned a malformed personal_sign response\");\n }\n return { signature: hexToBytes(signatureHex), signedMessage: msg };\n },\n\n subscribe(listener) {\n const synchronizeAccount = async (options?: AccountStateOptions) => {\n try {\n const state = await readAccountState(provider, info.name, options);\n if (state !== null) {\n listener({ ...state, type: \"accountChanged\" });\n }\n } catch {\n // EIP-1193 event reads are best-effort; a later event retries synchronization.\n }\n };\n\n const onAccountsChanged: Eip1193Listener = (...args) => {\n const accs = toStringArray(args[0]);\n if (accs.length === 0) {\n listener({ type: \"disconnected\" });\n return;\n }\n void synchronizeAccount({ accounts: accs });\n };\n\n const onChainChanged: Eip1193Listener = (...args) => {\n const [chainId] = args;\n // Some wallets emit a decimal number here instead of the EIP-1193\n // hex string; leaving it absent re-engages the eth_chainId read.\n const chainIdHex = typeof chainId === \"string\" && chainId.length > 0 ? chainId : undefined;\n void synchronizeAccount({ chainIdHex });\n };\n\n const onDisconnect: Eip1193Listener = () => {\n listener({ type: \"disconnected\" });\n };\n\n const onConnect: Eip1193Listener = () => {\n void synchronizeAccount();\n };\n\n provider.on(\"accountsChanged\", onAccountsChanged);\n provider.on(\"chainChanged\", onChainChanged);\n provider.on(\"connect\", onConnect);\n provider.on(\"disconnect\", onDisconnect);\n\n return () => {\n provider.removeListener(\"accountsChanged\", onAccountsChanged);\n provider.removeListener(\"chainChanged\", onChainChanged);\n provider.removeListener(\"connect\", onConnect);\n provider.removeListener(\"disconnect\", onDisconnect);\n };\n },\n\n async switchChain(chain) {\n const targetHex = chainIdDecimalToHex(chain.reference);\n const current = await requestString(provider, { method: \"eth_chainId\" });\n if (current?.toLowerCase() === targetHex.toLowerCase()) {\n return;\n }\n await provider.request({\n method: \"wallet_switchEthereumChain\",\n params: [{ chainId: targetHex }],\n });\n },\n };\n};\n\nexport { bytesToHexPrefixed as bytesToHex, hexToBytes } from \"@usebutr/core\";\nexport { formatEther } from \"./evm-balance\";\nexport { buildEvmAdapter, chainIdDecimalToHex, chainIdHexToDecimal };\n","import type { WalletAdapter } from \"@usebutr/core\";\n\nimport type { Eip6963AnnounceEvent, Eip6963ProviderInfo } from \"./eip1193\";\nimport { buildEvmAdapter } from \"./eip6963-adapter\";\n\nconst ANNOUNCE_EVENT = \"eip6963:announceProvider\";\nconst REQUEST_EVENT = \"eip6963:requestProvider\";\n\ntype AdapterCallback = (adapter: WalletAdapter, info: Eip6963ProviderInfo) => void;\n\ntype DiscoverOptions = {\n /** Event target to listen on. Defaults to `window` in browser/RN/\n * SSR'd environments; tests can pass a fresh `new EventTarget()` to\n * exercise the discovery loop without a DOM. */\n target?: EventTarget;\n};\n\nconst isEip6963AnnounceEvent = (event: Event): event is Eip6963AnnounceEvent => {\n if (!(\"detail\" in event)) {\n return false;\n }\n const detail: unknown = event.detail;\n if (typeof detail !== \"object\" || detail === null) {\n return false;\n }\n if (!(\"info\" in detail) || !(\"provider\" in detail)) {\n return false;\n }\n const { info, provider } = detail;\n return (\n typeof info === \"object\" &&\n info !== null &&\n \"icon\" in info &&\n typeof info.icon === \"string\" &&\n \"name\" in info &&\n typeof info.name === \"string\" &&\n \"rdns\" in info &&\n typeof info.rdns === \"string\" &&\n \"uuid\" in info &&\n typeof info.uuid === \"string\" &&\n typeof provider === \"object\" &&\n provider !== null &&\n \"on\" in provider &&\n typeof provider.on === \"function\" &&\n \"removeListener\" in provider &&\n typeof provider.removeListener === \"function\" &&\n \"request\" in provider &&\n typeof provider.request === \"function\"\n );\n};\n\nconst resolveTarget = (target?: EventTarget): EventTarget | null => {\n if (target !== undefined) {\n return target;\n }\n return globalThis.window ?? null;\n};\n\n/**\n * Spec: https://eips.ethereum.org/EIPS/eip-6963. Dedupe is by `info.rdns`\n * because `info.uuid` is regenerated per page load. The listener stays\n * attached for the session so wallets that boot late still register.\n */\nconst discoverEvmAdapters = (\n onAdapter: AdapterCallback,\n options: DiscoverOptions = {},\n): (() => void) => {\n const target = resolveTarget(options.target);\n if (!target) {\n return () => {};\n }\n\n const seen = new Set<string>();\n const handler = (event: Event) => {\n if (!isEip6963AnnounceEvent(event)) {\n return;\n }\n const { info, provider } = event.detail;\n if (info.rdns.length === 0) {\n return;\n }\n if (seen.has(info.rdns)) {\n return;\n }\n seen.add(info.rdns);\n onAdapter(buildEvmAdapter(info, provider), info);\n };\n\n target.addEventListener(ANNOUNCE_EVENT, handler);\n target.dispatchEvent(new Event(REQUEST_EVENT));\n\n return () => {\n target.removeEventListener(ANNOUNCE_EVENT, handler);\n };\n};\n\nexport { ANNOUNCE_EVENT, REQUEST_EVENT, discoverEvmAdapters };\n","import type { WalletAdapter, WalletSigner } from \"@usebutr/core\";\n\nimport type { Eip1193Provider, Eip6963ProviderInfo } from \"./eip1193\";\nimport { buildEvmAdapter } from \"./eip6963-adapter\";\n\n/**\n * Generic wallet icon (a stylised purse SVG, ~600 bytes). Used as\n * the fallback icon when an injected provider has no EIP-6963 info.\n * Inline rather than a network fetch so the picker doesn't flicker.\n */\nconst GENERIC_INJECTED_ICON =\n \"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSJjdXJyZW50Q29sb3IiIHN0cm9rZS13aWR0aD0iMiIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIj48cGF0aCBkPSJNMjEgMTJWN0g1YTIgMiAwIDAgMSAwLTQgaDE0djQiLz48cGF0aCBkPSJNMyA1djE0YTIgMiAwIDAgMCAyIDJoMTZ2LTVNMjEgMTIgaC0zYTIgMiAwIDAgMC0yIDJ2MGEyIDIgMCAwIDAgMiAyaDN6Ii8+PC9zdmc+\";\n\nconst DEFAULT_SETTLE_MS = 150;\n\ntype InjectedDiscoveryOptions = {\n /**\n * Consulted before emitting: an already-registered EIP-6963 adapter means\n * the wallet is covered by the standards path and emitting would duplicate\n * it. Omit to always emit.\n */\n hasAnyEip6963Adapter?: () => boolean;\n /**\n * Most wallets announce within the first frame; 150ms leaves room for slow\n * announcements without stalling the picker.\n */\n settleMs?: number;\n /** Override the global `window` reference (tests, iframes). */\n target?: { ethereum?: Partial<Eip1193Provider> } | null;\n};\n\ndeclare global {\n // oxlint-disable-next-line typescript/consistent-type-definitions -- DOM globals require interface merging.\n interface Window {\n ethereum?: Partial<Eip1193Provider>;\n }\n}\n\nconst isEip1193Provider = (value: WalletSigner | undefined): value is Eip1193Provider =>\n value !== undefined &&\n \"on\" in value &&\n typeof value.on === \"function\" &&\n \"removeListener\" in value &&\n typeof value.removeListener === \"function\" &&\n \"request\" in value &&\n typeof value.request === \"function\";\n\nconst readEthereum = (target: InjectedDiscoveryOptions[\"target\"]): Eip1193Provider | null => {\n const host = target === undefined ? globalThis.window : target;\n return isEip1193Provider(host?.ethereum) ? host.ethereum : null;\n};\n\n/**\n * Last-resort path for the long tail of EVM wallets that expose only\n * `window.ethereum` and never announce via EIP-6963. The emitted adapter\n * carries `rdns: \"injected:legacy\"` so consumers can tell it apart.\n */\nconst discoverInjectedAdapter = (\n onAdapter: (adapter: WalletAdapter) => void,\n options: InjectedDiscoveryOptions = {},\n): (() => void) => {\n const settleMs = options.settleMs ?? DEFAULT_SETTLE_MS;\n let cancelled = false;\n const timer = setTimeout(() => {\n if (cancelled) {\n return;\n }\n if (options.hasAnyEip6963Adapter?.() === true) {\n return;\n }\n const provider = readEthereum(options.target);\n if (provider === null) {\n return;\n }\n const info: Eip6963ProviderInfo = {\n icon: GENERIC_INJECTED_ICON,\n name: \"Browser wallet\",\n rdns: \"injected:legacy\",\n uuid: \"injected:legacy\",\n };\n onAdapter(buildEvmAdapter(info, provider));\n }, settleMs);\n\n return () => {\n cancelled = true;\n clearTimeout(timer);\n };\n};\n\nexport type { InjectedDiscoveryOptions };\nexport { GENERIC_INJECTED_ICON, discoverInjectedAdapter, isEip1193Provider };\n","import type { ChainBase } from \"@usebutr/core\";\n\n/**\n * Common EVM chain registry keyed by CAIP-2 id. Useful for chain-\n * switcher UIs. butr itself doesn't read this: `Connector.switchChain`\n * accepts any `ChainBase`.\n */\nconst EVM_CHAINS = {\n arbitrum: {\n id: \"eip155:42161\",\n name: \"Arbitrum One\",\n namespace: \"eip155\",\n reference: \"42161\",\n },\n base: { id: \"eip155:8453\", name: \"Base\", namespace: \"eip155\", reference: \"8453\" },\n bsc: { id: \"eip155:56\", name: \"BNB Smart Chain\", namespace: \"eip155\", reference: \"56\" },\n ethereum: { id: \"eip155:1\", name: \"Ethereum\", namespace: \"eip155\", reference: \"1\" },\n optimism: { id: \"eip155:10\", name: \"Optimism\", namespace: \"eip155\", reference: \"10\" },\n polygon: { id: \"eip155:137\", name: \"Polygon\", namespace: \"eip155\", reference: \"137\" },\n sepolia: { id: \"eip155:11155111\", name: \"Sepolia\", namespace: \"eip155\", reference: \"11155111\" },\n} as const satisfies Record<string, ChainBase>;\n\nconst EVM_CHAINS_LIST: ReadonlyArray<ChainBase> = Object.values(EVM_CHAINS);\n\nexport { EVM_CHAINS, EVM_CHAINS_LIST };\n","import type { PlatformDiscoverer } from \"@usebutr/core\";\n\nimport { discoverEvmAdapters } from \"./eip6963\";\nimport { discoverInjectedAdapter } from \"./injected\";\n\n/**\n * EIP-6963 is primary; the legacy `window.ethereum` fallback defers until\n * EIP-6963 has had a chance to fire.\n */\nconst evmDiscoverer: PlatformDiscoverer = {\n fallback: {\n subscribe: (onAdapter, opts) =>\n discoverInjectedAdapter(onAdapter, {\n hasAnyEip6963Adapter: opts.hasAnyPrimaryAdapter,\n }),\n },\n subscribe: discoverEvmAdapters,\n};\n\nexport { evmDiscoverer };\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,22 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@usebutr/evm",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.1",
|
|
4
4
|
"description": "EIP-1193 / EIP-6963 / injected wallet discovery + adapters for butr.",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"butr",
|
|
7
|
+
"dapp",
|
|
8
|
+
"eip-6963",
|
|
9
|
+
"ethereum",
|
|
10
|
+
"metamask",
|
|
11
|
+
"react",
|
|
12
|
+
"typescript",
|
|
13
|
+
"wallet",
|
|
14
|
+
"web3"
|
|
15
|
+
],
|
|
16
|
+
"homepage": "https://docs.usebutr.com/api/evm",
|
|
17
|
+
"bugs": {
|
|
18
|
+
"url": "https://github.com/pedroapfilho/usebutr/issues"
|
|
19
|
+
},
|
|
5
20
|
"license": "MIT",
|
|
6
21
|
"author": "Pedro Filho <pedro@filho.me>",
|
|
7
22
|
"repository": {
|
|
@@ -10,7 +25,8 @@
|
|
|
10
25
|
"directory": "packages/evm"
|
|
11
26
|
},
|
|
12
27
|
"files": [
|
|
13
|
-
"dist"
|
|
28
|
+
"dist",
|
|
29
|
+
"CHANGELOG.md"
|
|
14
30
|
],
|
|
15
31
|
"type": "module",
|
|
16
32
|
"sideEffects": false,
|
|
@@ -25,10 +41,10 @@
|
|
|
25
41
|
"access": "public"
|
|
26
42
|
},
|
|
27
43
|
"dependencies": {
|
|
28
|
-
"@usebutr/core": "2.0.
|
|
44
|
+
"@usebutr/core": "2.0.1"
|
|
29
45
|
},
|
|
30
46
|
"devDependencies": {
|
|
31
|
-
"typescript": "^
|
|
47
|
+
"typescript": "^7.0.2",
|
|
32
48
|
"vitest": "^4.1.10",
|
|
33
49
|
"@repo/config-vitest": "0.0.0",
|
|
34
50
|
"@repo/typescript-config": "0.0.0"
|