Skip to content

Commit

Permalink
Generic login + ExtensionProvider login (#12)
Browse files Browse the repository at this point in the history
* implement generic login and finalize the login with extension provider

* refactoring

* refactoring

* refactoring around provider type and login methods

* support for normal login and login with native token

* refactoring, add initDapp function, set nativeAuthCofig at init

* revert minify value

* fix import

* refactoring

* refactoring

* refactoring

* add nativeAuthConfig selector

* refactoring empty provider

* changelog update

* revert minify value
  • Loading branch information
CiprianDraghici committed Aug 29, 2024
1 parent 0cb8598 commit bcc37e0
Show file tree
Hide file tree
Showing 30 changed files with 357 additions and 232 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

- [Generic login + ExtensionProvider login](https://github.com/multiversx/mx-sdk-dapp-core/pull/12)
- [Make middlewares registration more scalable](https://github.com/multiversx/mx-sdk-dapp-core/pull/11)
- [Fix Node Polyfills](https://github.com/multiversx/mx-sdk-dapp-core/pull/10)
- [Removed chain id from network slice & added esbuild and absolute imports](https://github.com/multiversx/mx-sdk-dapp-core/pull/3)
Expand Down
5 changes: 1 addition & 4 deletions esbuild.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,7 @@ const executeBuild = () =>
process: 'process',
Buffer: 'Buffer'
},
plugins: [
plugin(stdLibBrowser),
nodeExternalsPlugin(),
]
plugins: [plugin(stdLibBrowser), nodeExternalsPlugin()]
})
.then(() => {
console.log(
Expand Down
88 changes: 0 additions & 88 deletions src/core/ProviderFactory.ts

This file was deleted.

2 changes: 1 addition & 1 deletion src/core/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
export * from './ProviderFactory';
export * from './providers/ProviderFactory';
export * from './Logger';
30 changes: 30 additions & 0 deletions src/core/methods/init/init.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { initStore } from 'store/store';
import { defaultStorageCallback, StorageCallback } from 'store/storage';
import { setTokenLoginNativeAuthTokenConfig } from 'store/actions/loginInfo/loginInfoActions';
import { NativeAuthConfigType } from 'services/nativeAuth/nativeAuth.types';
import { getDefaultNativeAuthConfig } from 'services/nativeAuth/methods/getDefaultNativeAuthConfig';

type InitAppType = {
storage?: {
getStorageCallback: StorageCallback;
};
nativeAuth?: boolean | NativeAuthConfigType;
};
const defaultInitAppProps = {
storage: {
getStorageCallback: defaultStorageCallback
}
};
export const initializeDApp = (props?: InitAppType) => {
const { storage, nativeAuth } = { ...defaultInitAppProps, ...props };
initStore(storage.getStorageCallback);

if (nativeAuth) {
const nativeAuthConfig: NativeAuthConfigType =
typeof nativeAuth === 'boolean'
? getDefaultNativeAuthConfig()
: nativeAuth;

setTokenLoginNativeAuthTokenConfig(nativeAuthConfig);
}
};
6 changes: 3 additions & 3 deletions src/core/methods/login/helpers/getLoginService.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import { Address, SignableMessage } from '@multiversx/sdk-core';
import { nativeAuth } from 'services/nativeAuth';
import { getNativeAuthConfig } from 'services/nativeAuth/methods';
import { buildNativeAuthConfig } from 'services/nativeAuth/methods';
import { networkSelector, tokenLoginSelector } from 'store/selectors';
import { getState } from 'store/store';
import { OnProviderLoginType } from 'types/login.types';
import { getAccount } from '../../account/getAccount';
import { setTokenLogin } from 'store/actions/loginInfo/loginInfoActions';
import { NativeAuthConfigType } from 'types/nativeAuth.types';
import { NativeAuthConfigType } from 'services/nativeAuth/nativeAuth.types';

const getApiAddress = (
apiAddress: string,
Expand All @@ -29,7 +29,7 @@ export const getLoginService = (config?: OnProviderLoginType['nativeAuth']) => {

const apiAddress = getApiAddress(network.apiAddress, config);

const configuration = getNativeAuthConfig({
const configuration = buildNativeAuthConfig({
...(config === true ? {} : config),
...(apiAddress ? { apiAddress } : {})
});
Expand Down
111 changes: 111 additions & 0 deletions src/core/methods/login/login.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
import { nativeAuth } from 'services/nativeAuth';
import { setAddress } from 'store/actions/account';
import {
setProviderType,
setTokenLogin
} from 'store/actions/loginInfo/loginInfoActions';
import { setAccountProvider } from 'core/providers/accountProvider';
import {
IProvider,
IProviderFactory
} from 'core/providers/types/providerFactory.types';
import { ProviderFactory } from 'core/providers/ProviderFactory';
import { nativeAuthConfigSelector } from 'store/selectors';
import { getState } from 'store/store';
import { NativeAuthConfigType } from 'services/nativeAuth/nativeAuth.types';
import { getIsLoggedIn } from 'utils/account/getIsLoggedIn';
import { getAddress } from 'utils/account/getAddress';

async function loginWithoutNativeToken(provider: IProvider) {
await provider.login();

const address = provider.getAddress?.();

if (!address) {
throw new Error('Address not found');
}

setAddress(address);

return {
address
};
}

async function loginWithNativeToken(
provider: IProvider,
nativeAuthConfig: NativeAuthConfigType
) {
const nativeAuthClient = nativeAuth(nativeAuthConfig);

const loginToken = await nativeAuthClient.initialize({
noCache: true
});

await provider.login({ token: loginToken });

const address = provider.getAddress?.();
const signature = provider.getTokenLoginSignature?.();

if (!address) {
throw new Error('Address not found');
}

if (!signature) {
throw new Error('Signature not found');
}

const nativeAuthToken = nativeAuthClient.getToken({
address,
token: loginToken,
signature
});

setAddress(address);
setTokenLogin({
loginToken,
signature,
nativeAuthToken,
nativeAuthConfig
});

return {
address,
signature,
nativeAuthToken,
loginToken,
nativeAuthConfig
};
}

export const login = async ({
providerConfig
}: {
providerConfig: IProviderFactory;
}) => {
const loggedIn = getIsLoggedIn();

if (loggedIn) {
console.warn('Already logged in with:', getAddress());
return;
}

const factory = new ProviderFactory();
const provider = await factory.create(providerConfig);

if (!provider) {
throw new Error('Provider not found');
}

await provider.init?.();
setAccountProvider(provider);
setProviderType(providerConfig.type);

const nativeAuthConfig = nativeAuthConfigSelector(getState());

if (nativeAuthConfig) {
return await loginWithNativeToken(provider, nativeAuthConfig);
}

return await loginWithoutNativeToken(provider);
};
6 changes: 3 additions & 3 deletions src/core/methods/login/webWalletLogin.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { LoginMethodsEnum } from 'types/enums.types';
import { OnProviderLoginType } from 'types/login.types';
import { getWindowLocation } from 'utils/window/getWindowLocation';
import { getLoginService } from './helpers/getLoginService';
Expand All @@ -14,6 +13,7 @@ import { setAccount } from 'store/actions/account/accountActions';
import { getLatestNonce } from 'utils/account/getLatestNonce';
import { AccountType } from 'types/account.types';
import { CrossWindowProvider } from 'lib/sdkWebWalletCrossWindowProvider';
import { ProviderTypeEnum } from '../../providers/types/providerFactory.types';

export const webWalletLogin = async ({
token: tokenToSign,
Expand Down Expand Up @@ -100,7 +100,7 @@ export const webWalletLogin = async ({

loginAction({
address: account.address,
loginMethod: LoginMethodsEnum.crossWindow
providerType: ProviderTypeEnum.crossWindow
});

const newAccount: AccountType = {
Expand All @@ -112,7 +112,7 @@ export const webWalletLogin = async ({

return newAccount;
} catch (error) {
console.error('error loging in', error);
console.error('error logging in', error);
throw error;
}
};
10 changes: 2 additions & 8 deletions src/core/methods/logout/logout.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
import { storage } from 'storage';
import { localStorageKeys } from 'storage/local';
import { LoginMethodsEnum } from 'types';
import { getAddress } from '../account/getAddress';
import { CrossWindowProvider } from 'lib/sdkWebWalletCrossWindowProvider';
import { logoutAction } from 'store/actions/sharedActions/sharedActions';
import { getWebviewToken } from '../account/getWebviewToken';
import { getAccountProvider } from 'core/providers/accountProvider';
import { getProviderType } from 'core/providers/helpers/utils';
import { ProviderTypeEnum } from 'core/providers/types/providerFactory.types';

const broadcastLogoutAcrossTabs = (address: string) => {
const storedData = storage.local?.getItem(localStorageKeys.logoutEvent);
Expand Down Expand Up @@ -35,7 +34,6 @@ export type LogoutPropsType = {
};

export async function logout(
shouldAttemptReLogin = Boolean(getWebviewToken()),
options = {
shouldBroadcastLogoutAcrossTabs: true,
hasConsentPopup: false
Expand All @@ -45,10 +43,6 @@ export async function logout(
const provider = getAccountProvider();
const providerType = getProviderType(provider);

if (shouldAttemptReLogin && provider?.relogin != null) {
return provider.relogin();
}

if (options.shouldBroadcastLogoutAcrossTabs) {
broadcastLogoutAcrossTabs(address);
}
Expand All @@ -58,7 +52,7 @@ export async function logout(

if (
options.hasConsentPopup &&
providerType === LoginMethodsEnum.crossWindow
providerType === ProviderTypeEnum.crossWindow
) {
(provider as unknown as CrossWindowProvider).setShouldShowConsentPopup(
true
Expand Down
Loading

0 comments on commit bcc37e0

Please sign in to comment.