@effectstream/wallets 0.100.0

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/README.md ADDED
@@ -0,0 +1 @@
1
+ # Effectstream Wallets
package/package.json ADDED
@@ -0,0 +1,30 @@
1
+ {
2
+ "name": "@effectstream/wallets",
3
+ "version": "0.100.0",
4
+ "license": "MIT",
5
+ "exports": "./src/mod.ts",
6
+ "dependencies": {
7
+ "@effectstream/concise": "0.100.0",
8
+ "@effectstream/crypto": "0.100.0",
9
+ "@effectstream/event-client": "0.100.0",
10
+ "@effectstream/utils": "0.100.0",
11
+ "@aurowallet/mina-provider": "^1.0.12",
12
+ "@metamask/providers": "^22.1.0",
13
+ "@midnight-ntwrk/dapp-connector-api": "4.0.1",
14
+ "@perawallet/connect": "^1.4.2",
15
+ "@polkadot/api": "15.10.2",
16
+ "@polkadot/extension-dapp": "^0.58.10",
17
+ "@polkadot/extension-inject": "^0.58.10",
18
+ "@polkadot/util": "^13.4.3",
19
+ "@polkadot/util-crypto": "^13.4.3",
20
+ "@types/semver": "7.7.1",
21
+ "assert-never": "^1.4.0",
22
+ "avail-js-sdk": "^0.4.2",
23
+ "bech32": "^2.0.0",
24
+ "ethers": "^6.15.0",
25
+ "semver": "^7.7.3",
26
+ "viem": "2.37.3",
27
+ "web3": "^4.16.0",
28
+ "web3-utils": "^4.3.3"
29
+ }
30
+ }
@@ -0,0 +1,62 @@
1
+ import { AddressType } from "@effectstream/utils";
2
+
3
+
4
+ export type WalletOption = {
5
+ name: string; // name of the wallet used in APIs (as opposed to a human-friendly string)
6
+ displayName: string;
7
+ /**
8
+ * URI-encoded image
9
+ * DANGER: SVGs can contain Javascript, so these should only be rendered with <img> tags
10
+ *
11
+ * Note: not every wallet type has an image (ex: locally generated keypairs)
12
+ * Example values:
13
+ * data:image/svg+xml,...
14
+ * data:image/png;base64,...
15
+ */
16
+ icon?: undefined | string;
17
+ };
18
+
19
+ export type ActiveConnection<T> = {
20
+ metadata: WalletOption;
21
+ api: T;
22
+ };
23
+ export type ConnectionOption<T> = {
24
+ metadata: WalletOption;
25
+ api: () => Promise<T>;
26
+ };
27
+ export async function optionToActive<T>(option: ConnectionOption<T>): Promise<ActiveConnection<T>> {
28
+ const connection = {
29
+ metadata: option.metadata,
30
+ api: await option.api(),
31
+ };
32
+ return connection;
33
+ }
34
+
35
+ export interface IConnector<T> {
36
+ getProvider(): undefined | IProvider<T>;
37
+ getOrThrowProvider(): IProvider<T>;
38
+ isConnected(): boolean;
39
+ }
40
+
41
+ export interface IInjectedConnector<T> {
42
+ /** connect while letting Paima pick all the connection logic for you */
43
+ connectSimple(): Promise<IProvider<T>>;
44
+ /** connect to an explicit API that Paima supports */
45
+ connectNamed(name: string): Promise<IProvider<T>>;
46
+ /** connect to an API that you've initialized yourself externally */
47
+ connectExternal(conn: ActiveConnection<T>): Promise<IProvider<T>>;
48
+ }
49
+
50
+ // Exported to package
51
+ export type AddressAndType = {
52
+ type: AddressType;
53
+ address: string;
54
+ };
55
+
56
+ export type UserSignature = string;
57
+
58
+ export interface IProvider<T> {
59
+ getConnection(): ActiveConnection<T>;
60
+ signMessage(message: string): Promise<UserSignature>;
61
+ getAddress(): AddressAndType;
62
+ }
@@ -0,0 +1,168 @@
1
+ import { PeraWalletConnect } from "@perawallet/connect";
2
+ import { AddressType, uint8ArrayToHexString } from "@effectstream/utils";
3
+ import {
4
+ type IConnector,
5
+ type IInjectedConnector,
6
+ type ConnectionOption,
7
+ optionToActive,
8
+ type ActiveConnection,
9
+ type IProvider,
10
+ type AddressAndType,
11
+ type UserSignature,
12
+ } from "../IProvider.ts";
13
+ import { getWindow } from "../windows.ts";
14
+ import { CryptoManager } from "@effectstream/crypto";
15
+
16
+ export type AlgorandApi = PeraWalletConnect;
17
+ export type AlgorandAddress = string;
18
+
19
+ export class AlgorandConnector
20
+ implements IConnector<AlgorandApi>, IInjectedConnector<AlgorandApi>
21
+ {
22
+ private provider: AlgorandProvider | undefined;
23
+ private static INSTANCE: undefined | AlgorandConnector = undefined;
24
+
25
+ static getWalletOptions(): ConnectionOption<AlgorandApi>[] {
26
+ // Algorand has no standard for wallet discovery
27
+ // The closest that exists is ARC11 (https://arc.algorand.foundation/ARCs/arc-0011)
28
+ // but it doesn't give any information about which wallet is injected
29
+ // and, similar to window.ethereum, has wallets overriding each other
30
+ // and Pera wallet doesn't even use this standard
31
+ // instead, the best we can do is check if Pera injected its UI component in the window
32
+ if (
33
+ (getWindow() as any)?.customElements.get("pera-wallet-connect-modal") ==
34
+ null
35
+ ) {
36
+ return [];
37
+ }
38
+ return [
39
+ {
40
+ metadata: {
41
+ name: "pera",
42
+ displayName: "Pera Wallet",
43
+ },
44
+ api: async (): Promise<AlgorandApi> => {
45
+ // const { PeraWalletConnect } = await import("@perawallet/connect");
46
+ const peraWallet = new PeraWalletConnect();
47
+ return peraWallet;
48
+ },
49
+ },
50
+ ];
51
+ }
52
+
53
+ static instance(): AlgorandConnector {
54
+ if (AlgorandConnector.INSTANCE == null) {
55
+ const newInstance = new AlgorandConnector();
56
+ AlgorandConnector.INSTANCE = newInstance;
57
+ }
58
+ return AlgorandConnector.INSTANCE;
59
+ }
60
+ connectSimple = async (): Promise<AlgorandProvider> => {
61
+ if (this.provider != null) {
62
+ return this.provider;
63
+ }
64
+ const options = AlgorandConnector.getWalletOptions();
65
+ if (options.length === 0) {
66
+ throw new Error(`No Algorand wallet found`);
67
+ }
68
+ return await this.connectExternal(await optionToActive(options[0]));
69
+ };
70
+ connectExternal = async (
71
+ conn: ActiveConnection<AlgorandApi>
72
+ ): Promise<AlgorandProvider> => {
73
+ if (this.provider?.getConnection().metadata?.name === conn.metadata.name) {
74
+ return this.provider;
75
+ }
76
+ this.provider = await AlgorandProvider.init(conn);
77
+ return this.provider;
78
+ };
79
+ connectNamed = async (name: string): Promise<AlgorandProvider> => {
80
+ if (this.provider?.getConnection().metadata?.name === name) {
81
+ return this.provider;
82
+ }
83
+ const provider = AlgorandConnector.getWalletOptions().find(
84
+ (entry) => entry.metadata.name === name
85
+ );
86
+ if (provider == null) {
87
+ throw new Error(`AlgorandProvider: unsupported connection type ${name}`);
88
+ }
89
+ return await this.connectExternal(await optionToActive(provider));
90
+ };
91
+ getProvider = (): undefined | AlgorandProvider => {
92
+ return this.provider;
93
+ };
94
+ getOrThrowProvider = (): AlgorandProvider => {
95
+ if (this.provider == null) {
96
+ throw new Error(`AlgorandConnector provider isn't initialized yet`);
97
+ }
98
+ return this.provider;
99
+ };
100
+ isConnected = (): boolean => {
101
+ return this.provider != null;
102
+ };
103
+ }
104
+
105
+ export class AlgorandProvider implements IProvider<AlgorandApi> {
106
+ constructor(
107
+ private readonly conn: ActiveConnection<AlgorandApi>,
108
+ readonly address: AlgorandAddress
109
+ ) {}
110
+ static init = async (
111
+ conn: ActiveConnection<AlgorandApi>
112
+ ): Promise<AlgorandProvider> => {
113
+ let newAccounts: string[] = [];
114
+ // conn.api.isConnected starts as false, even if connected
115
+ // if connected and connected() is called, then an error is thrown
116
+ try {
117
+ newAccounts = await conn.api.reconnectSession();
118
+ if ( newAccounts.length < 1) {
119
+ throw new Error("[peraLogin] no addresses returned!");
120
+ }
121
+ } catch (error) {
122
+ newAccounts = await conn.api.connect();
123
+ }
124
+
125
+ if (newAccounts.length < 1) {
126
+ throw new Error("[peraLogin] no addresses returned!");
127
+ }
128
+ return new AlgorandProvider(conn, newAccounts[0]);
129
+ };
130
+ getConnection = (): ActiveConnection<AlgorandApi> => {
131
+ return this.conn;
132
+ };
133
+ getAddress = (): AddressAndType => {
134
+ return {
135
+ type: AddressType.ALGORAND,
136
+ address: this.address,
137
+ };
138
+ };
139
+ signMessage = async (message: string): Promise<UserSignature> => {
140
+ const txn = await CryptoManager.Algorand().buildAlgorandTransaction(
141
+ this.getAddress().address,
142
+ message
143
+ );
144
+ const signerTx = {
145
+ txn,
146
+ signers: [this.getAddress().address],
147
+ };
148
+
149
+ const signedTxs = await this.conn.api.signTransaction(
150
+ [[signerTx]],
151
+ this.getAddress().address
152
+ );
153
+ if (signedTxs.length !== 1) {
154
+ throw new Error(
155
+ `[signMessageAlgorand] invalid number of signatures returned: ${signedTxs.length}`
156
+ );
157
+ }
158
+ const signedTx = await CryptoManager.Algorand().decodeSignedTransaction(
159
+ signedTxs[0]
160
+ );
161
+ const signature = signedTx.sig;
162
+ if (!signature) {
163
+ throw new Error(`[signMessageAlgorand] signature missing in signed Tx`);
164
+ }
165
+ const hexSignature = uint8ArrayToHexString(signature);
166
+ return hexSignature;
167
+ };
168
+ }
@@ -0,0 +1,22 @@
1
+ import type { Result } from "@effectstream/utils";
2
+ import type { IProvider } from "../IProvider.ts";
3
+ import type { WalletMode, ApiForMode } from "../utils.ts";
4
+ import { type LoginInfoMap, connectInjected } from "../wallet-modes.ts";
5
+ import { AlgorandConnector } from "./algorand.ts";
6
+
7
+ export async function algorandLoginWrapper(
8
+ loginInfo: LoginInfoMap[WalletMode.Algorand]
9
+ ): Promise<Result<IProvider<ApiForMode<WalletMode.Algorand>>>> {
10
+ const loginResult = await connectInjected(
11
+ "algorandLoginWrapper",
12
+ loginInfo,
13
+ AlgorandConnector.instance()
14
+ );
15
+ if (loginResult.success === false) {
16
+ return loginResult;
17
+ }
18
+ return {
19
+ success: true,
20
+ result: loginResult.result,
21
+ };
22
+ }
@@ -0,0 +1,81 @@
1
+ import { Buffer } from "node:buffer";
2
+ import { utf8ToHex } from 'web3-utils';
3
+ import type { ApiPromise } from "avail-js-sdk";
4
+ import { AddressType } from "@effectstream/utils";
5
+ import type { IProvider, ActiveConnection, AddressAndType, UserSignature } from "../IProvider.ts";
6
+ type PolkadotAddress = string;
7
+ import { u8aToHex } from "@polkadot/util";
8
+
9
+ // Problematic dependency for deno-fresh
10
+ import type { Keyring } from "avail-js-sdk";
11
+
12
+ // Problematic dependency for deno-vite
13
+ // import type { Keyring } from "@polkadot/api";
14
+ export type AvailJsApi = { rpc: ApiPromise; keyring: Keyring };
15
+
16
+ export class AvailConnector {
17
+ private provider: AvailJsProvider | undefined;
18
+ private static INSTANCE: undefined | AvailConnector = undefined;
19
+
20
+ static instance(): AvailConnector {
21
+ if (AvailConnector.INSTANCE == null) {
22
+ const newInstance = new AvailConnector();
23
+ AvailConnector.INSTANCE = newInstance;
24
+ }
25
+ return AvailConnector.INSTANCE;
26
+ }
27
+
28
+ connectExternal = async (conn: AvailJsApi): Promise<AvailJsProvider> => {
29
+ this.provider = await AvailJsProvider.init(conn);
30
+ return this.provider;
31
+ };
32
+
33
+ getProvider = (): undefined | AvailJsProvider => {
34
+ return this.provider;
35
+ };
36
+ getOrThrowProvider = (): AvailJsProvider => {
37
+ if (this.provider == null) {
38
+ throw new Error(`AvailJsConnector not initialized yet`);
39
+ }
40
+ return this.provider;
41
+ };
42
+ isConnected = (): boolean => {
43
+ return this.provider != null;
44
+ };
45
+ }
46
+
47
+ export class AvailJsProvider implements IProvider<AvailJsApi> {
48
+ constructor(
49
+ private readonly conn: ActiveConnection<AvailJsApi>,
50
+ readonly address: PolkadotAddress
51
+ ) {}
52
+
53
+ static init = async (api: AvailJsApi): Promise<AvailJsProvider> => {
54
+ const pair = api.keyring.getPairs()[0];
55
+
56
+ const conn = {
57
+ api: api,
58
+ metadata: {
59
+ name: 'AvailJs',
60
+ displayName: 'AvailJs',
61
+ },
62
+ };
63
+ return new AvailJsProvider(conn, pair.address);
64
+ };
65
+
66
+ getConnection = (): ActiveConnection<AvailJsApi> => {
67
+ return this.conn;
68
+ };
69
+ getAddress = (): AddressAndType => {
70
+ return {
71
+ type: AddressType.AVAIL,
72
+ address: this.address,
73
+ };
74
+ };
75
+ signMessage = async (message: string): Promise<UserSignature> => {
76
+ const hexMessage = utf8ToHex(message);
77
+ const buffer = Buffer.from(hexMessage.slice(2), 'hex');
78
+ const signature = this.conn.api.keyring.getPairs()[0].sign(buffer);
79
+ return u8aToHex(signature);
80
+ };
81
+ }
@@ -0,0 +1,44 @@
1
+ import type { Result } from "@effectstream/utils";
2
+ import type { IProvider } from "../IProvider.ts";
3
+ import type { WalletMode, ApiForMode } from "../utils.ts";
4
+ import type { LoginInfoMap } from "../wallet-modes.ts";
5
+ import { type AvailJsApi, AvailConnector } from "./avail.ts";
6
+
7
+ // Problematic dependency for deno-fresh
8
+ import { Keyring } from "avail-js-sdk";
9
+
10
+ // Problematic dependency for deno-vite
11
+ // import { Keyring } from "@polkadot/api";
12
+
13
+ async function connectWallet(
14
+ loginInfo: LoginInfoMap[WalletMode.AvailJs]
15
+ ): Promise<Result<IProvider<AvailJsApi>>> {
16
+ try {
17
+ console.log(`availJsLoginWrapper: Attempting to log into ${loginInfo.connection.metadata.name}`);
18
+ const keyring = new Keyring({ type: 'sr25519' });
19
+ keyring.addFromUri(loginInfo.seed);
20
+
21
+ const provider = await AvailConnector.instance().connectExternal({
22
+ rpc: loginInfo.connection.api,
23
+ keyring: keyring,
24
+ });
25
+
26
+ return {
27
+ success: true,
28
+ result: provider,
29
+ };
30
+ } catch (err: any) {
31
+ console.log(`availJsLoginWrapper: Error while logging into wallet name}`);
32
+ return {
33
+ success: false,
34
+ errorMessage: err.message ?? String(err),
35
+ }
36
+ }
37
+ }
38
+
39
+ export async function availJsLoginWrapper(
40
+ loginInfo: LoginInfoMap[WalletMode.AvailJs]
41
+ ): Promise<Result<IProvider<ApiForMode<WalletMode.AvailJs>>>> {
42
+ const loginResult = await connectWallet(loginInfo);
43
+ return loginResult;
44
+ }
@@ -0,0 +1,194 @@
1
+ import { bech32 } from "bech32";
2
+ import { hexStringToUint8Array, AddressType } from "@effectstream/utils";
3
+ import {
4
+ type IConnector,
5
+ type IInjectedConnector,
6
+ type ConnectionOption,
7
+ optionToActive,
8
+ type ActiveConnection,
9
+ type IProvider,
10
+ type AddressAndType,
11
+ type UserSignature,
12
+ } from "../IProvider.ts";
13
+ import { getWindow } from "../windows.ts";
14
+ import { utf8ToHex } from "web3-utils";
15
+
16
+ // TODO: proper type definitions for CIP30
17
+ export type CardanoApi = any;
18
+ /** bech32 */
19
+ export type CardanoAddress = {
20
+ bech32: string;
21
+ hex: string;
22
+ };
23
+
24
+ // JSR Error: modifying global types is not allowed
25
+ // declare global {
26
+ // interface Window {
27
+ // cardano?: Record<string, { name?: string; enable?: () => Promise<CardanoApi> }>;
28
+ // }
29
+ // }
30
+
31
+ // 4 helpers to convert hex addresses to bech32
32
+ const NETWORK_TAG_MAINNET = '1';
33
+ const NETWORK_TAG_TESTNET = '0';
34
+ const PREFIX_MAINNET = 'addr';
35
+ const PREFIX_TESTNET = 'addr_test';
36
+
37
+ export class CardanoConnector implements IConnector<CardanoApi>, IInjectedConnector<CardanoApi> {
38
+ private provider: CardanoProvider | undefined;
39
+ private static INSTANCE: undefined | CardanoConnector = undefined;
40
+
41
+ static getWalletOptions(): ConnectionOption<CardanoApi>[] {
42
+ const cardanoApi: Record<string, { name?: string; enable?: () => Promise<CardanoApi> }> = (getWindow() as any)?.cardano;
43
+ if (cardanoApi == null) return [];
44
+
45
+ const options = Object.entries(cardanoApi).reduce((options, [key, info]) => {
46
+ if (info.name != null && info.enable != null) {
47
+ options.push({
48
+ metadata: {
49
+ name: key,
50
+ displayName: info.name,
51
+ icon: 'icon' in info ? (info.icon as string) : undefined,
52
+ },
53
+ api: info.enable,
54
+ });
55
+ }
56
+ return options;
57
+ }, [] as ConnectionOption<CardanoApi>[]);
58
+ return options;
59
+ }
60
+
61
+ static instance(): CardanoConnector {
62
+ if (CardanoConnector.INSTANCE == null) {
63
+ const newInstance = new CardanoConnector();
64
+ CardanoConnector.INSTANCE = newInstance;
65
+ }
66
+ return CardanoConnector.INSTANCE;
67
+ }
68
+ connectSimple = async (): Promise<CardanoProvider> => {
69
+ if (this.provider != null) {
70
+ return this.provider;
71
+ }
72
+ const options = CardanoConnector.getWalletOptions();
73
+ if (options.length === 0) {
74
+ throw new Error(`No Cardano wallet found`);
75
+ }
76
+
77
+ // flint has some custom support for Paima, so best to return this one first if it exists
78
+ const flintWallet = options.find(option => option.metadata.name === 'flint');
79
+ if (flintWallet != null) {
80
+ return await this.connectExternal(await optionToActive(flintWallet));
81
+ }
82
+ return await this.connectExternal(await optionToActive(options[0]));
83
+ };
84
+ connectNamed = async (name: string): Promise<CardanoProvider> => {
85
+ if (this.provider?.getConnection().metadata?.name === name) {
86
+ return this.provider;
87
+ }
88
+ const provider = CardanoConnector.getWalletOptions().find(
89
+ entry => entry.metadata.name === name
90
+ );
91
+ if (provider == null) {
92
+ throw new Error(`Cardano wallet ${name} not found`);
93
+ }
94
+ return await this.connectExternal(await optionToActive(provider));
95
+ };
96
+ connectExternal = async (
97
+ conn: ActiveConnection<CardanoApi>
98
+ ): Promise<CardanoProvider> => {
99
+ if (this.provider?.getConnection().metadata?.name === conn.metadata.name) {
100
+ return this.provider;
101
+ }
102
+ this.provider = await CardanoProvider.init(conn);
103
+ return this.provider;
104
+ };
105
+ getProvider = (): undefined | CardanoProvider => {
106
+ return this.provider;
107
+ };
108
+ getOrThrowProvider = (): CardanoProvider => {
109
+ if (this.provider == null) {
110
+ throw new Error(`CardanoConnector provider isn't initialized yet`);
111
+ }
112
+ return this.provider;
113
+ };
114
+ isConnected = (): boolean => {
115
+ return this.provider != null;
116
+ };
117
+ }
118
+
119
+ function pickBech32Prefix(hexAddress: string): string {
120
+ if (hexAddress.length < 2) {
121
+ throw new Error(
122
+ `[cardanoLoginSpecific] Invalid address returned from wallet: ${hexAddress}`
123
+ );
124
+ }
125
+ const networkTag = hexAddress.at(1);
126
+ switch (networkTag) {
127
+ case NETWORK_TAG_MAINNET:
128
+ return PREFIX_MAINNET;
129
+ case NETWORK_TAG_TESTNET:
130
+ return PREFIX_TESTNET;
131
+ default:
132
+ throw new Error(
133
+ `[cardanoLoginSpecific] Invalid network tag in address ${hexAddress}`
134
+ );
135
+ }
136
+ }
137
+
138
+ export class CardanoProvider implements IProvider<CardanoApi> {
139
+ constructor(
140
+ private readonly conn: ActiveConnection<CardanoApi>,
141
+ readonly address: CardanoAddress
142
+ ) {}
143
+
144
+ static init = async (
145
+ conn: ActiveConnection<CardanoApi>
146
+ ): Promise<CardanoProvider> => {
147
+ const hexAddress = await CardanoProvider.fetchAddress(conn);
148
+ const prefix = pickBech32Prefix(hexAddress);
149
+ const words = bech32.toWords(hexStringToUint8Array(hexAddress));
150
+ const userAddress = bech32.encode(prefix, words, 200);
151
+
152
+ return new CardanoProvider(conn, {
153
+ bech32: userAddress,
154
+ hex: hexAddress,
155
+ });
156
+ };
157
+ getConnection = (): ActiveConnection<CardanoApi> => {
158
+ return this.conn;
159
+ };
160
+ getAddress = (): AddressAndType => {
161
+ return {
162
+ type: AddressType.CARDANO,
163
+ address: this.address.bech32,
164
+ };
165
+ };
166
+ signMessage = async (message: string): Promise<UserSignature> => {
167
+ const hexMessage = utf8ToHex(message).slice(2);
168
+ const address = (this.conn.metadata.name === 'nami' || this.conn.metadata.name === 'subwallet') ? this.address.hex : this.address.bech32;
169
+ const { signature, key } = await this.conn.api.signData(address, hexMessage);
170
+ return `${signature}+${key}`;
171
+ };
172
+
173
+ static fetchAddress = async (conn: ActiveConnection<CardanoApi>): Promise<string> => {
174
+ try {
175
+ const addresses = await conn.api.getUsedAddresses();
176
+ if (addresses.length > 0) {
177
+ return addresses[0];
178
+ }
179
+ } catch (err) {
180
+ console.log('[pickCardanoAddress] error calling getUsedAddresses:', err);
181
+ }
182
+
183
+ try {
184
+ const unusedAddresses = await conn.api.getUnusedAddresses();
185
+ if (unusedAddresses.length > 0) {
186
+ return unusedAddresses[0];
187
+ }
188
+ } catch (err) {
189
+ console.log('[pickCardanoAddress] error calling getUnusedAddresses:', err);
190
+ }
191
+
192
+ throw new Error('[pickCardanoAddress] no used or unused addresses');
193
+ };
194
+ }
@@ -0,0 +1,34 @@
1
+ import type { Result } from "@effectstream/utils";
2
+ import type { IProvider } from "../IProvider.ts";
3
+ import type { WalletMode, ApiForMode } from "../utils.ts";
4
+ import { type LoginInfoMap, connectInjected } from "../wallet-modes.ts";
5
+ import { CardanoConnector } from "./cardano.ts";
6
+
7
+ export async function checkCardanoWalletStatus(): Promise<Result<string>> {
8
+ const provider = CardanoConnector.instance().getProvider();
9
+ if (provider == null) {
10
+ return {
11
+ success: false,
12
+ errorMessage: "No Cardano wallet found",
13
+ };
14
+ }
15
+
16
+ return { success: true, result: "OK" };
17
+ }
18
+
19
+ export async function cardanoLoginWrapper(
20
+ loginInfo: LoginInfoMap[WalletMode.Cardano]
21
+ ): Promise<Result<IProvider<ApiForMode<WalletMode.Cardano>>>> {
22
+ const loginResult = await connectInjected(
23
+ "cardanoLoginWrapper",
24
+ loginInfo,
25
+ CardanoConnector.instance()
26
+ );
27
+ if (loginResult.success === false) {
28
+ return loginResult;
29
+ }
30
+ return {
31
+ success: true,
32
+ result: loginResult.result,
33
+ };
34
+ }