@cartridge/controller 0.13.10-alpha.1 → 0.13.11-alpha.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/.turbo/turbo-build$colon$deps.log +18 -22
- package/dist/controller.d.ts +2 -1
- package/dist/iframe/keychain.d.ts +1 -1
- package/dist/{index-B46sSAxE.js → index-hg9K2M84.js} +475 -199
- package/dist/index-hg9K2M84.js.map +1 -0
- package/dist/index.js +817 -788
- package/dist/index.js.map +1 -1
- package/dist/node/index.cjs +1 -1
- package/dist/node/index.cjs.map +1 -1
- package/dist/node/index.js +1 -1
- package/dist/node/index.js.map +1 -1
- package/dist/session.js +4 -4
- package/dist/stats.html +1 -1
- package/dist/types.d.ts +15 -3
- package/dist/utils.d.ts +0 -1
- package/dist/wallets/ethereum-base.d.ts +5 -1
- package/dist/wallets/metamask/index.d.ts +1 -0
- package/dist/wallets/phantom-evm/index.d.ts +1 -0
- package/package.json +4 -5
- package/src/controller.ts +35 -5
- package/src/iframe/keychain.ts +5 -0
- package/src/lookup.ts +4 -1
- package/src/types.ts +19 -0
- package/src/utils.ts +0 -8
- package/src/wallets/ethereum-base.ts +35 -48
- package/src/wallets/metamask/index.ts +6 -0
- package/src/wallets/phantom-evm/index.ts +4 -0
- package/dist/index-B46sSAxE.js.map +0 -1
- package/dist/telegram/backend.d.ts +0 -30
- package/dist/telegram/provider.d.ts +0 -24
- package/src/telegram/backend.ts +0 -43
- package/src/telegram/provider.ts +0 -148
package/dist/types.d.ts
CHANGED
|
@@ -13,11 +13,11 @@ export type KeychainSession = {
|
|
|
13
13
|
privateKey: string;
|
|
14
14
|
};
|
|
15
15
|
};
|
|
16
|
-
export declare const EMBEDDED_WALLETS: readonly ["google", "webauthn", "discord", "walletconnect", "password"];
|
|
16
|
+
export declare const EMBEDDED_WALLETS: readonly ["google", "webauthn", "discord", "walletconnect", "password", "sms"];
|
|
17
17
|
export type EmbeddedWallet = (typeof EMBEDDED_WALLETS)[number];
|
|
18
|
-
export declare const ALL_AUTH_OPTIONS: readonly ["google", "webauthn", "discord", "walletconnect", "password", "metamask", "rabby", "phantom-evm", "argent", "braavos", "phantom", "base"];
|
|
18
|
+
export declare const ALL_AUTH_OPTIONS: readonly ["google", "webauthn", "discord", "walletconnect", "password", "sms", "metamask", "rabby", "phantom-evm", "argent", "braavos", "phantom", "base"];
|
|
19
19
|
export type AuthOption = (typeof ALL_AUTH_OPTIONS)[number];
|
|
20
|
-
export declare const IMPLEMENTED_AUTH_OPTIONS: ("metamask" | "rabby" | "phantom-evm" | "google" | "webauthn" | "discord" | "walletconnect" | "password")[];
|
|
20
|
+
export declare const IMPLEMENTED_AUTH_OPTIONS: ("metamask" | "rabby" | "phantom-evm" | "google" | "webauthn" | "discord" | "walletconnect" | "password" | "sms")[];
|
|
21
21
|
export type AuthOptions = (typeof IMPLEMENTED_AUTH_OPTIONS)[number][];
|
|
22
22
|
export declare enum ResponseCodes {
|
|
23
23
|
SUCCESS = "SUCCESS",
|
|
@@ -102,6 +102,7 @@ export interface Keychain {
|
|
|
102
102
|
openPurchaseCredits(): void;
|
|
103
103
|
openExecute(calls: Call[]): Promise<void>;
|
|
104
104
|
switchChain(rpcUrl: string): Promise<void>;
|
|
105
|
+
openBundle(id: number, registryAddress: string, options?: BundleOptions): Promise<void>;
|
|
105
106
|
openStarterPack(id: string | number, options?: StarterpackOptions): Promise<void>;
|
|
106
107
|
navigate(path: string): Promise<void>;
|
|
107
108
|
externalDetectWallets(): Promise<ExternalWallet[]>;
|
|
@@ -162,6 +163,8 @@ export type KeychainOptions = IFrameOptions & {
|
|
|
162
163
|
tokens?: Tokens;
|
|
163
164
|
/** When true, defer iframe mounting until connect() is called. Reduces initial load and resource fetching. */
|
|
164
165
|
lazyload?: boolean;
|
|
166
|
+
/** When true, force WebAuthn operations to run in a popup window instead of the iframe. Useful for development and testing. */
|
|
167
|
+
webauthnPopup?: boolean;
|
|
165
168
|
};
|
|
166
169
|
export type ProfileContextTypeVariant = "inventory" | "trophies" | "achievements" | "quests" | "leaderboard" | "activity";
|
|
167
170
|
export type Token = "eth" | "strk" | "lords" | "usdc" | "usdt";
|
|
@@ -172,6 +175,15 @@ export type OpenOptions = {
|
|
|
172
175
|
/** The URL to redirect to after authentication (defaults to current page) */
|
|
173
176
|
redirectUrl?: string;
|
|
174
177
|
};
|
|
178
|
+
export type SocialClaimOptions = {
|
|
179
|
+
shareMessage: string;
|
|
180
|
+
};
|
|
181
|
+
export type BundleOptions = {
|
|
182
|
+
/** Callback fired after the Play button closes the starterpack modal */
|
|
183
|
+
onPurchaseComplete?: () => void;
|
|
184
|
+
/** Options for social claim conditional starterpack */
|
|
185
|
+
socialClaimOptions?: SocialClaimOptions;
|
|
186
|
+
};
|
|
175
187
|
export type StarterpackOptions = {
|
|
176
188
|
/** The preimage to use */
|
|
177
189
|
preimage?: string;
|
package/dist/utils.d.ts
CHANGED
|
@@ -23,5 +23,4 @@ export declare function toWasmPolicies(policies: ParsedSessionPolicies): Policy[
|
|
|
23
23
|
export declare function toArray<T>(val: T | T[]): T[];
|
|
24
24
|
export declare function humanizeString(str: string): string;
|
|
25
25
|
export declare function parseChainId(url: URL): ChainId;
|
|
26
|
-
export declare function isMobile(): boolean;
|
|
27
26
|
export declare function sanitizeImageSrc(src: string): string;
|
|
@@ -6,12 +6,16 @@ export declare abstract class EthereumWalletBase implements WalletAdapter {
|
|
|
6
6
|
abstract readonly displayName: string;
|
|
7
7
|
platform: ExternalPlatform | undefined;
|
|
8
8
|
protected account: string | undefined;
|
|
9
|
-
protected store: import('mipd').Store;
|
|
10
9
|
protected provider: EIP6963ProviderDetail | undefined;
|
|
11
10
|
protected connectedAccounts: string[];
|
|
12
11
|
constructor();
|
|
13
12
|
private getProvider;
|
|
14
13
|
private getEthereumProvider;
|
|
14
|
+
/**
|
|
15
|
+
* Fallback provider detection when EIP-6963 announcement is missed.
|
|
16
|
+
* Subclasses can override to provide wallet-specific fallback logic.
|
|
17
|
+
*/
|
|
18
|
+
protected getFallbackProvider(): any;
|
|
15
19
|
private initializeIfAvailable;
|
|
16
20
|
private initialized;
|
|
17
21
|
private initializeProvider;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cartridge/controller",
|
|
3
|
-
"version": "0.13.
|
|
3
|
+
"version": "0.13.11-alpha.1",
|
|
4
4
|
"description": "Cartridge Controller",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -26,15 +26,14 @@
|
|
|
26
26
|
}
|
|
27
27
|
},
|
|
28
28
|
"dependencies": {
|
|
29
|
-
"@cartridge/controller-wasm": "0.
|
|
29
|
+
"@cartridge/controller-wasm": "0.10.0",
|
|
30
30
|
"@cartridge/penpal": "^6.2.4",
|
|
31
31
|
"micro-sol-signer": "^0.5.0",
|
|
32
32
|
"bs58": "^6.0.0",
|
|
33
33
|
"ethers": "^6.13.5",
|
|
34
34
|
"@starknet-io/get-starknet-wallet-standard": "5.0.0-beta.0",
|
|
35
35
|
"@starknet-io/types-js": "0.9.1",
|
|
36
|
-
"@
|
|
37
|
-
"@turnkey/sdk-browser": "^4.0.0",
|
|
36
|
+
"@turnkey/sdk-browser": "^5.15.2",
|
|
38
37
|
"cbor-x": "^1.5.0",
|
|
39
38
|
"starknet": "^8.5.2",
|
|
40
39
|
"mipd": "^0.0.7",
|
|
@@ -56,7 +55,7 @@
|
|
|
56
55
|
"vite-plugin-node-polyfills": "^0.23.0",
|
|
57
56
|
"vite-plugin-top-level-await": "^1.4.4",
|
|
58
57
|
"vite-plugin-wasm": "^3.4.1",
|
|
59
|
-
"@cartridge/tsconfig": "0.13.
|
|
58
|
+
"@cartridge/tsconfig": "0.13.11-alpha.1"
|
|
60
59
|
},
|
|
61
60
|
"scripts": {
|
|
62
61
|
"build:deps": "pnpm build:browser && pnpm build:node",
|
package/src/controller.ts
CHANGED
|
@@ -32,6 +32,7 @@ import {
|
|
|
32
32
|
HeadlessUsernameLookupResult,
|
|
33
33
|
StarterpackOptions,
|
|
34
34
|
UpdateSessionOptions,
|
|
35
|
+
BundleOptions,
|
|
35
36
|
} from "./types";
|
|
36
37
|
import { validateRedirectUrl } from "./url-validator";
|
|
37
38
|
import { parseChainId } from "./utils";
|
|
@@ -309,8 +310,9 @@ export default class ControllerProvider extends BaseProvider {
|
|
|
309
310
|
return this.account;
|
|
310
311
|
}
|
|
311
312
|
|
|
312
|
-
|
|
313
|
-
|
|
313
|
+
if (!headless) {
|
|
314
|
+
this.iframes.keychain.open();
|
|
315
|
+
}
|
|
314
316
|
|
|
315
317
|
// Use connect() parameter if provided, otherwise fall back to constructor options
|
|
316
318
|
const effectiveOptions = Array.isArray(options)
|
|
@@ -353,7 +355,6 @@ export default class ControllerProvider extends BaseProvider {
|
|
|
353
355
|
}
|
|
354
356
|
console.log(e);
|
|
355
357
|
} finally {
|
|
356
|
-
// Only close modal if it was opened (not headless)
|
|
357
358
|
if (!headless) {
|
|
358
359
|
this.iframes.keychain.close();
|
|
359
360
|
}
|
|
@@ -391,7 +392,6 @@ export default class ControllerProvider extends BaseProvider {
|
|
|
391
392
|
|
|
392
393
|
async disconnect() {
|
|
393
394
|
this.account = undefined;
|
|
394
|
-
this.emitAccountsChanged([]);
|
|
395
395
|
|
|
396
396
|
try {
|
|
397
397
|
if (typeof localStorage !== "undefined") {
|
|
@@ -413,8 +413,13 @@ export default class ControllerProvider extends BaseProvider {
|
|
|
413
413
|
return;
|
|
414
414
|
}
|
|
415
415
|
|
|
416
|
+
// Disconnect the keychain (clears iframe localStorage) before emitting
|
|
417
|
+
// state changes, because emitAccountsChanged can trigger framework
|
|
418
|
+
// re-renders that navigate or reload the page.
|
|
416
419
|
await this.keychain.disconnect();
|
|
417
|
-
|
|
420
|
+
this.close();
|
|
421
|
+
|
|
422
|
+
this.emitAccountsChanged([]);
|
|
418
423
|
}
|
|
419
424
|
|
|
420
425
|
async openProfile(tab: ProfileContextTypeVariant = "inventory") {
|
|
@@ -607,6 +612,31 @@ export default class ControllerProvider extends BaseProvider {
|
|
|
607
612
|
});
|
|
608
613
|
}
|
|
609
614
|
|
|
615
|
+
async openBundle(
|
|
616
|
+
id: number,
|
|
617
|
+
registryAddress: string,
|
|
618
|
+
options?: BundleOptions,
|
|
619
|
+
): Promise<void> {
|
|
620
|
+
if (!this.iframes) {
|
|
621
|
+
return;
|
|
622
|
+
}
|
|
623
|
+
|
|
624
|
+
if (!this.keychain || !this.iframes.keychain) {
|
|
625
|
+
console.error(new NotReadyToConnect().message);
|
|
626
|
+
return;
|
|
627
|
+
}
|
|
628
|
+
|
|
629
|
+
const { onPurchaseComplete, ...bundleOptions } = options ?? {};
|
|
630
|
+
this.iframes.keychain.setOnStarterpackPlay(onPurchaseComplete);
|
|
631
|
+
const sanitizedOptions =
|
|
632
|
+
Object.keys(bundleOptions).length > 0
|
|
633
|
+
? (bundleOptions as Omit<BundleOptions, "onPurchaseComplete">)
|
|
634
|
+
: undefined;
|
|
635
|
+
|
|
636
|
+
await this.keychain.openBundle(id, registryAddress, sanitizedOptions);
|
|
637
|
+
this.iframes.keychain?.open();
|
|
638
|
+
}
|
|
639
|
+
|
|
610
640
|
async openStarterPack(
|
|
611
641
|
id: string | number,
|
|
612
642
|
options?: StarterpackOptions,
|
package/src/iframe/keychain.ts
CHANGED
|
@@ -40,6 +40,7 @@ export class KeychainIFrame extends IFrame<Keychain> {
|
|
|
40
40
|
encryptedBlob,
|
|
41
41
|
propagateSessionErrors,
|
|
42
42
|
errorDisplayMode,
|
|
43
|
+
webauthnPopup,
|
|
43
44
|
...iframeOptions
|
|
44
45
|
}: KeychainIframeOptions) {
|
|
45
46
|
let onStarterpackPlayHandler: (() => Promise<void>) | undefined;
|
|
@@ -101,6 +102,10 @@ export class KeychainIFrame extends IFrame<Keychain> {
|
|
|
101
102
|
_url.searchParams.set("should_override_preset_policies", "true");
|
|
102
103
|
}
|
|
103
104
|
|
|
105
|
+
if (webauthnPopup) {
|
|
106
|
+
_url.searchParams.set("webauthn_popup", "true");
|
|
107
|
+
}
|
|
108
|
+
|
|
104
109
|
// Policy precedence logic:
|
|
105
110
|
// 1. If shouldOverridePresetPolicies is true and policies are provided, use policies
|
|
106
111
|
// 2. Otherwise, if preset is defined, ignore provided policies
|
package/src/lookup.ts
CHANGED
|
@@ -119,10 +119,13 @@ const HEADLESS_AUTH_OPTIONS: AuthOption[] = [
|
|
|
119
119
|
"discord",
|
|
120
120
|
"walletconnect",
|
|
121
121
|
"password",
|
|
122
|
+
"sms",
|
|
122
123
|
"metamask",
|
|
123
124
|
"rabby",
|
|
124
125
|
"phantom-evm",
|
|
125
|
-
].filter((option) =>
|
|
126
|
+
].filter((option) =>
|
|
127
|
+
IMPLEMENTED_AUTH_OPTIONS.includes(option as AuthOption),
|
|
128
|
+
) as AuthOption[];
|
|
126
129
|
|
|
127
130
|
function normalizeSignerOptions(
|
|
128
131
|
signers: LookupSigner[] | undefined,
|
package/src/types.ts
CHANGED
|
@@ -38,6 +38,7 @@ export const EMBEDDED_WALLETS = [
|
|
|
38
38
|
"discord",
|
|
39
39
|
"walletconnect",
|
|
40
40
|
"password",
|
|
41
|
+
"sms",
|
|
41
42
|
] as const;
|
|
42
43
|
|
|
43
44
|
export type EmbeddedWallet = (typeof EMBEDDED_WALLETS)[number];
|
|
@@ -171,6 +172,11 @@ export interface Keychain {
|
|
|
171
172
|
openPurchaseCredits(): void;
|
|
172
173
|
openExecute(calls: Call[]): Promise<void>;
|
|
173
174
|
switchChain(rpcUrl: string): Promise<void>;
|
|
175
|
+
openBundle(
|
|
176
|
+
id: number,
|
|
177
|
+
registryAddress: string,
|
|
178
|
+
options?: BundleOptions,
|
|
179
|
+
): Promise<void>;
|
|
174
180
|
openStarterPack(
|
|
175
181
|
id: string | number,
|
|
176
182
|
options?: StarterpackOptions,
|
|
@@ -259,6 +265,8 @@ export type KeychainOptions = IFrameOptions & {
|
|
|
259
265
|
tokens?: Tokens;
|
|
260
266
|
/** When true, defer iframe mounting until connect() is called. Reduces initial load and resource fetching. */
|
|
261
267
|
lazyload?: boolean;
|
|
268
|
+
/** When true, force WebAuthn operations to run in a popup window instead of the iframe. Useful for development and testing. */
|
|
269
|
+
webauthnPopup?: boolean;
|
|
262
270
|
};
|
|
263
271
|
|
|
264
272
|
export type ProfileContextTypeVariant =
|
|
@@ -280,6 +288,17 @@ export type OpenOptions = {
|
|
|
280
288
|
redirectUrl?: string;
|
|
281
289
|
};
|
|
282
290
|
|
|
291
|
+
export type SocialClaimOptions = {
|
|
292
|
+
shareMessage: string;
|
|
293
|
+
};
|
|
294
|
+
|
|
295
|
+
export type BundleOptions = {
|
|
296
|
+
/** Callback fired after the Play button closes the starterpack modal */
|
|
297
|
+
onPurchaseComplete?: () => void;
|
|
298
|
+
/** Options for social claim conditional starterpack */
|
|
299
|
+
socialClaimOptions?: SocialClaimOptions;
|
|
300
|
+
};
|
|
301
|
+
|
|
283
302
|
export type StarterpackOptions = {
|
|
284
303
|
/** The preimage to use */
|
|
285
304
|
preimage?: string;
|
package/src/utils.ts
CHANGED
|
@@ -256,14 +256,6 @@ export function parseChainId(url: URL): ChainId {
|
|
|
256
256
|
throw new Error(`Chain ${url.toString()} not supported`);
|
|
257
257
|
}
|
|
258
258
|
|
|
259
|
-
export function isMobile() {
|
|
260
|
-
return (
|
|
261
|
-
window.matchMedia("(max-width: 768px)").matches ||
|
|
262
|
-
"ontouchstart" in window ||
|
|
263
|
-
navigator.maxTouchPoints > 0
|
|
264
|
-
);
|
|
265
|
-
}
|
|
266
|
-
|
|
267
259
|
// Sanitize image src to prevent XSS
|
|
268
260
|
export function sanitizeImageSrc(src: string): string {
|
|
269
261
|
// Allow only http/https URLs (absolute)
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { getAddress } from "ethers/address";
|
|
2
|
-
import { createStore, EIP6963ProviderDetail } from "mipd";
|
|
3
|
-
import { isMobile } from "../utils";
|
|
2
|
+
import { createStore, EIP6963ProviderDetail, Store } from "mipd";
|
|
4
3
|
import { chainIdToPlatform } from "./platform";
|
|
5
4
|
import {
|
|
6
5
|
ExternalPlatform,
|
|
@@ -10,6 +9,17 @@ import {
|
|
|
10
9
|
WalletAdapter,
|
|
11
10
|
} from "./types";
|
|
12
11
|
|
|
12
|
+
// Shared store across all EthereumWalletBase instances so late EIP-6963
|
|
13
|
+
// announcements are captured once and visible to every wallet adapter.
|
|
14
|
+
let sharedStore: Store | undefined;
|
|
15
|
+
|
|
16
|
+
function getSharedStore(): Store {
|
|
17
|
+
if (!sharedStore) {
|
|
18
|
+
sharedStore = createStore();
|
|
19
|
+
}
|
|
20
|
+
return sharedStore;
|
|
21
|
+
}
|
|
22
|
+
|
|
13
23
|
export abstract class EthereumWalletBase implements WalletAdapter {
|
|
14
24
|
abstract readonly type: ExternalWalletType;
|
|
15
25
|
abstract readonly rdns: string;
|
|
@@ -17,7 +27,6 @@ export abstract class EthereumWalletBase implements WalletAdapter {
|
|
|
17
27
|
|
|
18
28
|
platform: ExternalPlatform | undefined;
|
|
19
29
|
protected account: string | undefined = undefined;
|
|
20
|
-
protected store = createStore();
|
|
21
30
|
protected provider: EIP6963ProviderDetail | undefined;
|
|
22
31
|
protected connectedAccounts: string[] = [];
|
|
23
32
|
|
|
@@ -26,10 +35,10 @@ export abstract class EthereumWalletBase implements WalletAdapter {
|
|
|
26
35
|
}
|
|
27
36
|
|
|
28
37
|
private getProvider(): EIP6963ProviderDetail | undefined {
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
38
|
+
// Use shared store's findProvider which reflects late announcements
|
|
39
|
+
const found = getSharedStore().findProvider({ rdns: this.rdns as any });
|
|
40
|
+
if (found) {
|
|
41
|
+
this.provider = found;
|
|
33
42
|
}
|
|
34
43
|
return this.provider;
|
|
35
44
|
}
|
|
@@ -40,15 +49,14 @@ export abstract class EthereumWalletBase implements WalletAdapter {
|
|
|
40
49
|
return provider.provider;
|
|
41
50
|
}
|
|
42
51
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
this.rdns === "io.metamask" &&
|
|
46
|
-
typeof window !== "undefined" &&
|
|
47
|
-
(window as any).ethereum?.isMetaMask
|
|
48
|
-
) {
|
|
49
|
-
return (window as any).ethereum;
|
|
50
|
-
}
|
|
52
|
+
return this.getFallbackProvider();
|
|
53
|
+
}
|
|
51
54
|
|
|
55
|
+
/**
|
|
56
|
+
* Fallback provider detection when EIP-6963 announcement is missed.
|
|
57
|
+
* Subclasses can override to provide wallet-specific fallback logic.
|
|
58
|
+
*/
|
|
59
|
+
protected getFallbackProvider(): any {
|
|
52
60
|
return null;
|
|
53
61
|
}
|
|
54
62
|
|
|
@@ -101,29 +109,20 @@ export abstract class EthereumWalletBase implements WalletAdapter {
|
|
|
101
109
|
}
|
|
102
110
|
|
|
103
111
|
isAvailable(): boolean {
|
|
104
|
-
if (isMobile()) {
|
|
105
|
-
return false;
|
|
106
|
-
}
|
|
107
|
-
|
|
108
112
|
// Check dynamically each time, as the provider might be announced after instantiation
|
|
109
113
|
const provider = this.getProvider();
|
|
110
114
|
|
|
111
|
-
// Also check for MetaMask via window.ethereum as a fallback for MetaMask specifically
|
|
112
|
-
if (
|
|
113
|
-
!provider &&
|
|
114
|
-
this.rdns === "io.metamask" &&
|
|
115
|
-
typeof window !== "undefined"
|
|
116
|
-
) {
|
|
117
|
-
// MetaMask might be available via window.ethereum even if not announced via EIP-6963 yet
|
|
118
|
-
return !!(window as any).ethereum?.isMetaMask;
|
|
119
|
-
}
|
|
120
|
-
|
|
121
115
|
// Initialize if we just found the provider
|
|
122
116
|
if (provider && !this.initialized) {
|
|
123
117
|
this.initializeIfAvailable();
|
|
124
118
|
}
|
|
125
119
|
|
|
126
|
-
|
|
120
|
+
if (provider) {
|
|
121
|
+
return true;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
// Fall back to wallet-specific detection when EIP-6963 announcement is missed
|
|
125
|
+
return typeof window !== "undefined" && !!this.getFallbackProvider();
|
|
127
126
|
}
|
|
128
127
|
|
|
129
128
|
getInfo(): ExternalWallet {
|
|
@@ -158,18 +157,7 @@ export abstract class EthereumWalletBase implements WalletAdapter {
|
|
|
158
157
|
throw new Error(`${this.displayName} is not available`);
|
|
159
158
|
}
|
|
160
159
|
|
|
161
|
-
|
|
162
|
-
const provider = this.getProvider();
|
|
163
|
-
|
|
164
|
-
if (provider) {
|
|
165
|
-
ethereum = provider.provider;
|
|
166
|
-
} else if (
|
|
167
|
-
this.rdns === "io.metamask" &&
|
|
168
|
-
(window as any).ethereum?.isMetaMask
|
|
169
|
-
) {
|
|
170
|
-
// Fallback for MetaMask when not announced via EIP-6963
|
|
171
|
-
ethereum = (window as any).ethereum;
|
|
172
|
-
}
|
|
160
|
+
const ethereum = this.getEthereumProvider();
|
|
173
161
|
|
|
174
162
|
if (!ethereum) {
|
|
175
163
|
throw new Error(`${this.displayName} provider not found`);
|
|
@@ -183,15 +171,14 @@ export abstract class EthereumWalletBase implements WalletAdapter {
|
|
|
183
171
|
this.account = getAddress(accounts[0]);
|
|
184
172
|
this.connectedAccounts = accounts.map(getAddress);
|
|
185
173
|
|
|
186
|
-
// If we used
|
|
187
|
-
if (!
|
|
188
|
-
// Create a mock EIP6963ProviderDetail for consistency
|
|
174
|
+
// If we used a fallback provider, store it for future use
|
|
175
|
+
if (!this.getProvider()) {
|
|
189
176
|
this.provider = {
|
|
190
177
|
info: {
|
|
191
|
-
uuid:
|
|
192
|
-
name:
|
|
178
|
+
uuid: `${this.rdns}-fallback`,
|
|
179
|
+
name: this.displayName,
|
|
193
180
|
icon: "data:image/svg+xml;base64,",
|
|
194
|
-
rdns:
|
|
181
|
+
rdns: this.rdns,
|
|
195
182
|
},
|
|
196
183
|
provider: ethereum,
|
|
197
184
|
} as EIP6963ProviderDetail;
|
|
@@ -5,4 +5,10 @@ export class MetaMaskWallet extends EthereumWalletBase {
|
|
|
5
5
|
readonly type: ExternalWalletType = "metamask";
|
|
6
6
|
readonly rdns = "io.metamask";
|
|
7
7
|
readonly displayName = "MetaMask";
|
|
8
|
+
|
|
9
|
+
protected getFallbackProvider(): any {
|
|
10
|
+
return (window as any).ethereum?.isMetaMask
|
|
11
|
+
? (window as any).ethereum
|
|
12
|
+
: null;
|
|
13
|
+
}
|
|
8
14
|
}
|
|
@@ -5,4 +5,8 @@ export class PhantomEVMWallet extends EthereumWalletBase {
|
|
|
5
5
|
readonly type: ExternalWalletType = "phantom-evm";
|
|
6
6
|
readonly rdns = "app.phantom";
|
|
7
7
|
readonly displayName = "Phantom";
|
|
8
|
+
|
|
9
|
+
protected getFallbackProvider(): any {
|
|
10
|
+
return (window as any).phantom?.ethereum ?? null;
|
|
11
|
+
}
|
|
8
12
|
}
|