@reown/appkit-controllers 1.8.23-multichain-btc-fix.0 → 1.8.23
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/dist/esm/exports/index.js +1 -0
- package/dist/esm/exports/index.js.map +1 -1
- package/dist/esm/src/utils/ProviderReauthUtil.js +149 -0
- package/dist/esm/src/utils/ProviderReauthUtil.js.map +1 -0
- package/dist/esm/tests/utils/ProviderReauthUtil.test.js +213 -0
- package/dist/esm/tests/utils/ProviderReauthUtil.test.js.map +1 -0
- package/dist/esm/tsconfig.tsbuildinfo +1 -1
- package/dist/types/exports/index.d.ts +1 -0
- package/dist/types/src/utils/ProviderReauthUtil.d.ts +45 -0
- package/dist/types/tests/utils/ProviderReauthUtil.test.d.ts +1 -0
- package/package.json +3 -3
|
@@ -3,6 +3,7 @@ export { ModalController } from '../src/controllers/ModalController.js';
|
|
|
3
3
|
export { RouterController } from '../src/controllers/RouterController.js';
|
|
4
4
|
export { ChainController } from '../src/controllers/ChainController.js';
|
|
5
5
|
export { ProviderController } from '../src/controllers/ProviderController.js';
|
|
6
|
+
export { isCoinbaseConnectorId, isUnauthorizedProviderError, maybeWrapCoinbaseProvider, withCoinbaseReauth } from '../src/utils/ProviderReauthUtil.js';
|
|
6
7
|
export { OnRampController } from '../src/controllers/OnRampController.js';
|
|
7
8
|
export { AdapterController } from '../src/controllers/AdapterController/index.js';
|
|
8
9
|
export { AdapterBlueprint } from '../src/controllers/AdapterController/ChainAdapterBlueprint.js';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../exports/index.ts"],"names":[],"mappings":"AAAA,+EAA+E;AAC/E,OAAO,EAAE,eAAe,EAAE,MAAM,uCAAuC,CAAA;AAMvE,OAAO,EAAE,gBAAgB,EAAE,MAAM,wCAAwC,CAAA;AAGzE,OAAO,EAAE,eAAe,EAAE,MAAM,uCAAuC,CAAA;AAGvE,OAAO,EAAE,kBAAkB,EAAE,MAAM,0CAA0C,CAAA;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../exports/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
import { ChainController } from '../controllers/ChainController.js';
|
|
2
|
+
/**
|
|
3
|
+
* Recovers a provider whose wallet session was restored WITHOUT re-authorizing
|
|
4
|
+
* the underlying SDK — the Coinbase Wallet SDK case.
|
|
5
|
+
*
|
|
6
|
+
* On an AppKit auto-restore, the Coinbase provider is read back via
|
|
7
|
+
* `eth_accounts` only; `eth_requestAccounts` is never re-issued (unlike wagmi's
|
|
8
|
+
* own `reconnect`, which calls the connector's `connect()` →
|
|
9
|
+
* `eth_requestAccounts`). The Coinbase SDK keeps the accounts but drops its
|
|
10
|
+
* internal authorization, so the first signing RPC on the raw provider throws
|
|
11
|
+
* EIP-1193 `4100` ("Must call 'eth_requestAccounts' before other methods").
|
|
12
|
+
* Consumers that call `.request()` directly on the provider (e.g. WalletConnect
|
|
13
|
+
* Pay) hit this; consumers going through wagmi's hooks do not, because wagmi
|
|
14
|
+
* re-authorized first.
|
|
15
|
+
*
|
|
16
|
+
* The recovery is adapter-agnostic: it wraps the one shared Coinbase provider
|
|
17
|
+
* instance that every consumer reads, so both the wagmi and ethers adapters are
|
|
18
|
+
* covered, and downstream code keeps no workaround of its own.
|
|
19
|
+
*/
|
|
20
|
+
/** Marks a provider already wrapped by {@link withCoinbaseReauth}. */
|
|
21
|
+
const REAUTH_WRAPPED = Symbol('appkit.coinbaseReauthWrapped');
|
|
22
|
+
/** Maximum `cause`-chain depth walked by {@link isUnauthorizedProviderError}. */
|
|
23
|
+
const MAX_CAUSE_DEPTH = 5;
|
|
24
|
+
/** Stable-identity cache: one wrapper per raw provider instance. */
|
|
25
|
+
const wrapperCache = new WeakMap();
|
|
26
|
+
/**
|
|
27
|
+
* True when `connectorId` is a Coinbase connector.
|
|
28
|
+
*
|
|
29
|
+
* The connector id (not the provider "type") is the reliable signal: it is a
|
|
30
|
+
* stable `'coinbaseWallet'` / `'coinbaseWalletSDK'` across every adapter and
|
|
31
|
+
* registration path, whereas the provider type is remapped to `'EXTERNAL'` by
|
|
32
|
+
* `PresetsUtil.ConnectorTypesMap` on most paths. Matched case-insensitively by
|
|
33
|
+
* substring to also tolerate the wagmi restore path's uppercased
|
|
34
|
+
* `connector.type` (`'COINBASEWALLET'`).
|
|
35
|
+
*/
|
|
36
|
+
export function isCoinbaseConnectorId(connectorId) {
|
|
37
|
+
return typeof connectorId === 'string' && connectorId.toLowerCase().includes('coinbase');
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* EIP-1193 `4100` unauthorized error, matched by code or by the SDK's
|
|
41
|
+
* `eth_requestAccounts` wording, walking the `cause` chain (viem/provider
|
|
42
|
+
* wrappers nest the original error) with bounded depth.
|
|
43
|
+
*/
|
|
44
|
+
export function isUnauthorizedProviderError(err, depth = 0) {
|
|
45
|
+
if (!err || typeof err !== 'object' || depth > MAX_CAUSE_DEPTH) {
|
|
46
|
+
return false;
|
|
47
|
+
}
|
|
48
|
+
const candidate = err;
|
|
49
|
+
if (candidate.code === 4100) {
|
|
50
|
+
return true;
|
|
51
|
+
}
|
|
52
|
+
if (typeof candidate.message === 'string' && candidate.message.includes('eth_requestAccounts')) {
|
|
53
|
+
return true;
|
|
54
|
+
}
|
|
55
|
+
if (candidate.cause && candidate.cause !== err) {
|
|
56
|
+
return isUnauthorizedProviderError(candidate.cause, depth + 1);
|
|
57
|
+
}
|
|
58
|
+
return false;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Re-assert the app's active eip155 chain on the provider. `eth_requestAccounts`
|
|
62
|
+
* can reset the Coinbase SDK's active chain (it tends to land back on mainnet),
|
|
63
|
+
* so an `eth_sendTransaction` retry must re-pin the chain first — otherwise the
|
|
64
|
+
* transaction could broadcast on the wrong network. Failure to switch is
|
|
65
|
+
* propagated: better to fail the signing than to send funds on the wrong chain.
|
|
66
|
+
*/
|
|
67
|
+
async function reassertActiveChain(provider) {
|
|
68
|
+
const chainId = ChainController.getActiveCaipNetwork('eip155')?.id;
|
|
69
|
+
if (typeof chainId !== 'number') {
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
await provider.request({
|
|
73
|
+
method: 'wallet_switchEthereumChain',
|
|
74
|
+
params: [{ chainId: `0x${chainId.toString(16)}` }]
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Wrap a Coinbase provider so any signing RPC that fails with `4100` triggers a
|
|
79
|
+
* one-shot recovery: a single `eth_requestAccounts` re-authorization, an active-
|
|
80
|
+
* chain re-assert for state-changing calls, then exactly one retry.
|
|
81
|
+
*
|
|
82
|
+
* - Non-`4100` failures pass through untouched (no re-auth attempt).
|
|
83
|
+
* - A rejected re-auth prompt propagates and classifies as a user rejection.
|
|
84
|
+
* - A still-unauthorized retry fails once (no loop) — the recovery calls the raw
|
|
85
|
+
* provider, never the wrapper, so it cannot recurse.
|
|
86
|
+
*
|
|
87
|
+
* Non-`request` members are delegated to the raw provider bound to the raw
|
|
88
|
+
* instance, so private class fields and EIP-1193 event emitters keep working.
|
|
89
|
+
* The wrapper is cached per raw instance so repeated `setProvider` calls with
|
|
90
|
+
* the same provider return a stable reference (no consumer identity churn).
|
|
91
|
+
*/
|
|
92
|
+
export function withCoinbaseReauth(provider) {
|
|
93
|
+
const raw = provider;
|
|
94
|
+
if (!provider || typeof raw.request !== 'function') {
|
|
95
|
+
return provider;
|
|
96
|
+
}
|
|
97
|
+
if (provider[REAUTH_WRAPPED]) {
|
|
98
|
+
return provider;
|
|
99
|
+
}
|
|
100
|
+
const cached = wrapperCache.get(provider);
|
|
101
|
+
if (cached) {
|
|
102
|
+
return cached;
|
|
103
|
+
}
|
|
104
|
+
async function request(args) {
|
|
105
|
+
try {
|
|
106
|
+
return await raw.request(args);
|
|
107
|
+
}
|
|
108
|
+
catch (err) {
|
|
109
|
+
if (!isUnauthorizedProviderError(err)) {
|
|
110
|
+
throw err;
|
|
111
|
+
}
|
|
112
|
+
// One handshake re-authorizes the same SDK provider instance.
|
|
113
|
+
await raw.request({ method: 'eth_requestAccounts' });
|
|
114
|
+
if (args.method === 'eth_sendTransaction') {
|
|
115
|
+
await reassertActiveChain(raw);
|
|
116
|
+
}
|
|
117
|
+
return raw.request(args);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
const proxy = new Proxy(provider, {
|
|
121
|
+
get(target, prop) {
|
|
122
|
+
if (prop === REAUTH_WRAPPED) {
|
|
123
|
+
return true;
|
|
124
|
+
}
|
|
125
|
+
if (prop === 'request') {
|
|
126
|
+
return request;
|
|
127
|
+
}
|
|
128
|
+
const value = Reflect.get(target, prop, target);
|
|
129
|
+
return typeof value === 'function' ? value.bind(target) : value;
|
|
130
|
+
}
|
|
131
|
+
});
|
|
132
|
+
wrapperCache.set(provider, proxy);
|
|
133
|
+
return proxy;
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Apply {@link withCoinbaseReauth} to an eip155 Coinbase provider, returning
|
|
137
|
+
* every other provider untouched. This is the single decision the provider
|
|
138
|
+
* registration seam (`syncProvider`) needs — keeping the guard here (keyed on
|
|
139
|
+
* the reliable connector id) rather than in the state setter.
|
|
140
|
+
*/
|
|
141
|
+
export function maybeWrapCoinbaseProvider(params) {
|
|
142
|
+
const { connectorId, chainNamespace, provider } = params;
|
|
143
|
+
const shouldWrap = chainNamespace === 'eip155' &&
|
|
144
|
+
isCoinbaseConnectorId(connectorId) &&
|
|
145
|
+
typeof provider === 'object' &&
|
|
146
|
+
provider !== null;
|
|
147
|
+
return shouldWrap ? withCoinbaseReauth(provider) : provider;
|
|
148
|
+
}
|
|
149
|
+
//# sourceMappingURL=ProviderReauthUtil.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ProviderReauthUtil.js","sourceRoot":"","sources":["../../../../src/utils/ProviderReauthUtil.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
import { afterEach, describe, expect, it, vi } from 'vitest';
|
|
2
|
+
import { ChainController, isCoinbaseConnectorId, isUnauthorizedProviderError, maybeWrapCoinbaseProvider, withCoinbaseReauth } from '../../exports/index.js';
|
|
3
|
+
// -- Helpers ------------------------------------------------------------------
|
|
4
|
+
const unauthorized = () => ({
|
|
5
|
+
code: 4100,
|
|
6
|
+
message: "Must call 'eth_requestAccounts' before other methods"
|
|
7
|
+
});
|
|
8
|
+
/**
|
|
9
|
+
* Minimal EIP-1193-ish provider whose `request` is a spy. `impl` decides the
|
|
10
|
+
* behaviour per call so we can script "fail 4100 → succeed on retry".
|
|
11
|
+
*/
|
|
12
|
+
function createProvider(impl) {
|
|
13
|
+
return {
|
|
14
|
+
request: vi.fn(impl),
|
|
15
|
+
on: vi.fn(),
|
|
16
|
+
removeListener: vi.fn()
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
// -- Tests --------------------------------------------------------------------
|
|
20
|
+
describe('isCoinbaseConnectorId', () => {
|
|
21
|
+
it('matches Coinbase connector ids, tolerating casing variants', () => {
|
|
22
|
+
expect(isCoinbaseConnectorId('coinbaseWallet')).toBe(true);
|
|
23
|
+
expect(isCoinbaseConnectorId('coinbaseWalletSDK')).toBe(true);
|
|
24
|
+
// wagmi restore path can surface connector.type.toUpperCase()
|
|
25
|
+
expect(isCoinbaseConnectorId('COINBASEWALLET')).toBe(true);
|
|
26
|
+
expect(isCoinbaseConnectorId('walletConnect')).toBe(false);
|
|
27
|
+
expect(isCoinbaseConnectorId('injected')).toBe(false);
|
|
28
|
+
expect(isCoinbaseConnectorId('EXTERNAL')).toBe(false);
|
|
29
|
+
expect(isCoinbaseConnectorId(undefined)).toBe(false);
|
|
30
|
+
});
|
|
31
|
+
});
|
|
32
|
+
describe('maybeWrapCoinbaseProvider', () => {
|
|
33
|
+
it('wraps an eip155 Coinbase provider (by connector id, not remapped type)', () => {
|
|
34
|
+
const provider = createProvider(async () => null);
|
|
35
|
+
const wrapped = maybeWrapCoinbaseProvider({
|
|
36
|
+
connectorId: 'coinbaseWalletSDK',
|
|
37
|
+
chainNamespace: 'eip155',
|
|
38
|
+
provider
|
|
39
|
+
});
|
|
40
|
+
expect(wrapped).not.toBe(provider);
|
|
41
|
+
});
|
|
42
|
+
it('leaves a non-Coinbase provider untouched (identity preserved)', () => {
|
|
43
|
+
const provider = createProvider(async () => null);
|
|
44
|
+
// The ethers/live paths remap Coinbase to type 'EXTERNAL'; guarding on the
|
|
45
|
+
// connector id (not the type) is what makes the fix adapter-agnostic.
|
|
46
|
+
const same = maybeWrapCoinbaseProvider({
|
|
47
|
+
connectorId: 'walletConnect',
|
|
48
|
+
chainNamespace: 'eip155',
|
|
49
|
+
provider
|
|
50
|
+
});
|
|
51
|
+
expect(same).toBe(provider);
|
|
52
|
+
});
|
|
53
|
+
it('does not wrap a Coinbase connector on a non-eip155 namespace', () => {
|
|
54
|
+
const provider = createProvider(async () => null);
|
|
55
|
+
const same = maybeWrapCoinbaseProvider({
|
|
56
|
+
connectorId: 'coinbaseWalletSDK',
|
|
57
|
+
chainNamespace: 'solana',
|
|
58
|
+
provider
|
|
59
|
+
});
|
|
60
|
+
expect(same).toBe(provider);
|
|
61
|
+
});
|
|
62
|
+
});
|
|
63
|
+
describe('isUnauthorizedProviderError', () => {
|
|
64
|
+
it('matches EIP-1193 code 4100', () => {
|
|
65
|
+
expect(isUnauthorizedProviderError({ code: 4100 })).toBe(true);
|
|
66
|
+
});
|
|
67
|
+
it('matches the eth_requestAccounts wording without a code', () => {
|
|
68
|
+
expect(isUnauthorizedProviderError({
|
|
69
|
+
message: "Must call 'eth_requestAccounts' before other methods"
|
|
70
|
+
})).toBe(true);
|
|
71
|
+
});
|
|
72
|
+
it('walks the cause chain', () => {
|
|
73
|
+
const nested = { message: 'wrapped', cause: { code: 4100 } };
|
|
74
|
+
expect(isUnauthorizedProviderError(nested)).toBe(true);
|
|
75
|
+
});
|
|
76
|
+
it('does not treat user rejection (4001) or plain errors as unauthorized', () => {
|
|
77
|
+
expect(isUnauthorizedProviderError({ code: 4001, message: 'User rejected' })).toBe(false);
|
|
78
|
+
expect(isUnauthorizedProviderError(new Error('boom'))).toBe(false);
|
|
79
|
+
expect(isUnauthorizedProviderError(undefined)).toBe(false);
|
|
80
|
+
});
|
|
81
|
+
it('is cycle-safe via bounded depth', () => {
|
|
82
|
+
const cyclic = { message: 'x' };
|
|
83
|
+
cyclic.cause = cyclic;
|
|
84
|
+
expect(isUnauthorizedProviderError(cyclic)).toBe(false);
|
|
85
|
+
});
|
|
86
|
+
});
|
|
87
|
+
describe('withCoinbaseReauth', () => {
|
|
88
|
+
afterEach(() => {
|
|
89
|
+
vi.restoreAllMocks();
|
|
90
|
+
});
|
|
91
|
+
it('passes through a successful request without re-auth', async () => {
|
|
92
|
+
const provider = createProvider(async () => '0xresult');
|
|
93
|
+
const wrapped = withCoinbaseReauth(provider);
|
|
94
|
+
await expect(wrapped.request({ method: 'eth_sign' })).resolves.toBe('0xresult');
|
|
95
|
+
expect(provider.request).toHaveBeenCalledTimes(1);
|
|
96
|
+
expect(provider.request).not.toHaveBeenCalledWith({ method: 'eth_requestAccounts' });
|
|
97
|
+
});
|
|
98
|
+
it('recovers a 4100 by re-authorizing then retrying once', async () => {
|
|
99
|
+
let signAttempts = 0;
|
|
100
|
+
const provider = createProvider(async ({ method }) => {
|
|
101
|
+
if (method === 'eth_signTypedData_v4') {
|
|
102
|
+
signAttempts += 1;
|
|
103
|
+
if (signAttempts === 1) {
|
|
104
|
+
throw unauthorized();
|
|
105
|
+
}
|
|
106
|
+
return '0xsig';
|
|
107
|
+
}
|
|
108
|
+
return null;
|
|
109
|
+
});
|
|
110
|
+
const wrapped = withCoinbaseReauth(provider);
|
|
111
|
+
await expect(wrapped.request({ method: 'eth_signTypedData_v4' })).resolves.toBe('0xsig');
|
|
112
|
+
expect(provider.request).toHaveBeenCalledWith({ method: 'eth_requestAccounts' });
|
|
113
|
+
// original (fail) + requestAccounts + retry (success) = 3
|
|
114
|
+
expect(provider.request).toHaveBeenCalledTimes(3);
|
|
115
|
+
});
|
|
116
|
+
it('re-asserts the active chain before retrying eth_sendTransaction', async () => {
|
|
117
|
+
vi.spyOn(ChainController, 'getActiveCaipNetwork').mockReturnValue({ id: 8453 });
|
|
118
|
+
let sendAttempts = 0;
|
|
119
|
+
const provider = createProvider(async ({ method }) => {
|
|
120
|
+
if (method === 'eth_sendTransaction') {
|
|
121
|
+
sendAttempts += 1;
|
|
122
|
+
if (sendAttempts === 1) {
|
|
123
|
+
throw unauthorized();
|
|
124
|
+
}
|
|
125
|
+
return '0xhash';
|
|
126
|
+
}
|
|
127
|
+
return null;
|
|
128
|
+
});
|
|
129
|
+
const wrapped = withCoinbaseReauth(provider);
|
|
130
|
+
await expect(wrapped.request({ method: 'eth_sendTransaction' })).resolves.toBe('0xhash');
|
|
131
|
+
// Base 8453 → 0x2105; asserted before the retry
|
|
132
|
+
expect(provider.request).toHaveBeenCalledWith({
|
|
133
|
+
method: 'wallet_switchEthereumChain',
|
|
134
|
+
params: [{ chainId: '0x2105' }]
|
|
135
|
+
});
|
|
136
|
+
});
|
|
137
|
+
it('does NOT switch chain when recovering a non-transaction method', async () => {
|
|
138
|
+
const switchSpy = vi.spyOn(ChainController, 'getActiveCaipNetwork');
|
|
139
|
+
let attempts = 0;
|
|
140
|
+
const provider = createProvider(async ({ method }) => {
|
|
141
|
+
if (method === 'eth_signTypedData_v4') {
|
|
142
|
+
attempts += 1;
|
|
143
|
+
if (attempts === 1) {
|
|
144
|
+
throw unauthorized();
|
|
145
|
+
}
|
|
146
|
+
return '0xsig';
|
|
147
|
+
}
|
|
148
|
+
return null;
|
|
149
|
+
});
|
|
150
|
+
const wrapped = withCoinbaseReauth(provider);
|
|
151
|
+
await wrapped.request({ method: 'eth_signTypedData_v4' });
|
|
152
|
+
expect(switchSpy).not.toHaveBeenCalled();
|
|
153
|
+
expect(provider.request).not.toHaveBeenCalledWith(expect.objectContaining({ method: 'wallet_switchEthereumChain' }));
|
|
154
|
+
});
|
|
155
|
+
it('propagates a non-4100 error without attempting re-auth', async () => {
|
|
156
|
+
const rejection = { code: 4001, message: 'User rejected' };
|
|
157
|
+
const provider = createProvider(async () => {
|
|
158
|
+
throw rejection;
|
|
159
|
+
});
|
|
160
|
+
const wrapped = withCoinbaseReauth(provider);
|
|
161
|
+
await expect(wrapped.request({ method: 'eth_sendTransaction' })).rejects.toBe(rejection);
|
|
162
|
+
expect(provider.request).toHaveBeenCalledTimes(1);
|
|
163
|
+
expect(provider.request).not.toHaveBeenCalledWith({ method: 'eth_requestAccounts' });
|
|
164
|
+
});
|
|
165
|
+
it('propagates a rejected re-auth prompt and does not retry the signing call', async () => {
|
|
166
|
+
const promptRejection = { code: 4001, message: 'User rejected the request' };
|
|
167
|
+
let sendAttempts = 0;
|
|
168
|
+
const provider = createProvider(async ({ method }) => {
|
|
169
|
+
if (method === 'eth_requestAccounts') {
|
|
170
|
+
throw promptRejection;
|
|
171
|
+
}
|
|
172
|
+
if (method === 'eth_sendTransaction') {
|
|
173
|
+
sendAttempts += 1;
|
|
174
|
+
throw unauthorized();
|
|
175
|
+
}
|
|
176
|
+
return null;
|
|
177
|
+
});
|
|
178
|
+
const wrapped = withCoinbaseReauth(provider);
|
|
179
|
+
await expect(wrapped.request({ method: 'eth_sendTransaction' })).rejects.toBe(promptRejection);
|
|
180
|
+
expect(sendAttempts).toBe(1); // no retry after the failed handshake
|
|
181
|
+
});
|
|
182
|
+
it('fails once (no loop) when the retry is still unauthorized', async () => {
|
|
183
|
+
const provider = createProvider(async ({ method }) => {
|
|
184
|
+
if (method === 'eth_requestAccounts') {
|
|
185
|
+
return ['0xabc'];
|
|
186
|
+
}
|
|
187
|
+
// eth_signTypedData_v4 always unauthorized
|
|
188
|
+
throw unauthorized();
|
|
189
|
+
});
|
|
190
|
+
const wrapped = withCoinbaseReauth(provider);
|
|
191
|
+
await expect(wrapped.request({ method: 'eth_signTypedData_v4' })).rejects.toMatchObject({
|
|
192
|
+
code: 4100
|
|
193
|
+
});
|
|
194
|
+
// original + requestAccounts + one retry = 3, then it gives up
|
|
195
|
+
expect(provider.request).toHaveBeenCalledTimes(3);
|
|
196
|
+
});
|
|
197
|
+
it('returns a stable wrapper for the same instance and is not double-wrapped', () => {
|
|
198
|
+
const provider = createProvider(async () => null);
|
|
199
|
+
const first = withCoinbaseReauth(provider);
|
|
200
|
+
const second = withCoinbaseReauth(provider);
|
|
201
|
+
expect(first).toBe(second);
|
|
202
|
+
// wrapping the wrapper is a no-op
|
|
203
|
+
expect(withCoinbaseReauth(first)).toBe(first);
|
|
204
|
+
});
|
|
205
|
+
it('delegates non-request members to the raw provider', () => {
|
|
206
|
+
const provider = createProvider(async () => null);
|
|
207
|
+
const wrapped = withCoinbaseReauth(provider);
|
|
208
|
+
const listener = () => undefined;
|
|
209
|
+
wrapped.on('accountsChanged', listener);
|
|
210
|
+
expect(provider.on).toHaveBeenCalledWith('accountsChanged', listener);
|
|
211
|
+
});
|
|
212
|
+
});
|
|
213
|
+
//# sourceMappingURL=ProviderReauthUtil.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ProviderReauthUtil.test.js","sourceRoot":"","sources":["../../../../tests/utils/ProviderReauthUtil.test.ts"],"names":[],"mappings":"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"}
|