Skip to content

Commit

Permalink
Merge pull request #17 from multiversx/development
Browse files Browse the repository at this point in the history
v0.0.0-alpha.9
  • Loading branch information
CiprianDraghici authored Aug 29, 2024
2 parents 80accd4 + 9a9f281 commit 798c0be
Show file tree
Hide file tree
Showing 126 changed files with 4,628 additions and 1,032 deletions.
9 changes: 7 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

## [[v0.0.0-alpha.8]](https://github.com/multiversx/mx-sdk-dapp-core/pull/16)] - 2024-08-27
- [Added `@multiversx/sdk-web-wallet-cross-window-provider` as peer dep](https://github.com/multiversx/mx-sdk-dapp-core/pull/15)
## [[0.0.0-alpha.9]](https://github.com/multiversx/mx-sdk-dapp-core)] - 2024-08-29
- [CrossWindow login](https://github.com/multiversx/mx-sdk-dapp-core/pull/13)
## [[v0.0.0-alpha.8]](https://github.com/multiversx/mx-sdk-dapp-core/pull/16) - 2024-08-27
- [Added sdk-web-wallet-cross-window-provider as peer dependency](https://github.com/multiversx/mx-sdk-dapp-core/pull/14)
- [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)
- [Reverted absolute imports](https://github.com/multiversx/mx-sdk-dapp-core/pull/2)
- [Added network store](https://github.com/multiversx/mx-sdk-dapp-core/pull/1)
Expand Down
6 changes: 5 additions & 1 deletion esbuild.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
const esbuild = require('esbuild');
const glob = require('glob');
const plugin = require('node-stdlib-browser/helpers/esbuild/plugin');
const stdLibBrowser = require('node-stdlib-browser');
const { nodeExternalsPlugin } = require('esbuild-node-externals');

/*
The reason why we use esbuild instead of tsc is because esbuild can output .mjs files
Expand Down Expand Up @@ -34,7 +37,8 @@ const executeBuild = () =>
global: 'global',
process: 'process',
Buffer: 'Buffer'
}
},
plugins: [plugin(stdLibBrowser), nodeExternalsPlugin()]
})
.then(() => {
console.log(
Expand Down
19 changes: 14 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@multiversx/sdk-dapp-core",
"version": "0.0.0-alpha.8",
"version": "0.0.0-alpha.9",
"main": "out/index.js",
"module": "out/index.js",
"types": "out/index.d.ts",
Expand Down Expand Up @@ -30,16 +30,23 @@
"access": "public"
},
"dependencies": {
"@lifeomic/axios-fetch": "3.0.1",
"@multiversx/sdk-extension-provider": "3.0.0",
"@multiversx/sdk-hw-provider": "6.4.0",
"@multiversx/sdk-metamask-provider": "0.0.5",
"@multiversx/sdk-native-auth-client": "^1.0.8",
"@multiversx/sdk-opera-provider": "1.0.0-alpha.1",
"@multiversx/sdk-wallet-connect-provider": "4.1.2",
"@multiversx/sdk-web-wallet-provider": "3.2.1",
"@types/lodash": "^4.17.4",
"isomorphic-fetch": "^3.0.0",
"lodash": "^4.17.21",
"zustand": "^4.4.7"
},
"peerDependencies": {
"@multiversx/sdk-core": ">= 13.0.0",
"@multiversx/sdk-dapp-utils": "^0.0.1",
"@multiversx/sdk-web-wallet-cross-window-provider": ">= 0.4.2",
"@multiversx/sdk-dapp-utils": ">= 0.1.0",
"@multiversx/sdk-web-wallet-cross-window-provider": ">= 1.0.0",
"axios": ">=1.6.5",
"bignumber.js": "9.x"
},
Expand All @@ -48,8 +55,8 @@
},
"devDependencies": {
"@multiversx/sdk-core": ">= 13.0.0",
"@multiversx/sdk-dapp-utils": "^0.0.1",
"@multiversx/sdk-web-wallet-cross-window-provider": ">= 0.4.2",
"@multiversx/sdk-dapp-utils": ">= 0.1.0",
"@multiversx/sdk-web-wallet-cross-window-provider": ">= 1.0.0",
"@swc/core": "^1.4.17",
"@swc/jest": "^0.2.36",
"@types/node": "20.12.8",
Expand All @@ -59,6 +66,7 @@
"axios-mock-adapter": "^1.22.0",
"bignumber.js": "9.x",
"esbuild": "^0.21.1",
"esbuild-node-externals": "1.14.0",
"eslint": "9.1.1",
"eslint-config-prettier": "9.1.0",
"eslint-config-standard": "17.1.0",
Expand All @@ -72,6 +80,7 @@
"jest": "29.7.0",
"jest-environment-jsdom": "29.7.0",
"msw": "1.3.1",
"node-stdlib-browser": "1.2.0",
"prettier": "3.2.5",
"protobufjs": "^7.3.0",
"react": "^18.3.1",
Expand Down
2 changes: 1 addition & 1 deletion src/__mocks__/accountConfig.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { fallbackNetworkConfigurations } from 'constants/network';
import { fallbackNetworkConfigurations } from 'constants/network.constants';
import { EnvironmentsEnum } from 'types';

export const testAddress =
Expand Down
28 changes: 28 additions & 0 deletions src/apiCalls/accounts/getAccountFromApi.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { ACCOUNTS_ENDPOINT } from 'apiCalls/endpoints';
import { axiosInstance } from 'apiCalls/utils/axiosInstance';
import { getCleanApiAddress } from 'apiCalls/utils/getCleanApiAddress';
import { AccountType } from 'types/account.types';

export const accountFetcher = (address: string | null) => {
const apiAddress = getCleanApiAddress();
const url = `${apiAddress}/${ACCOUNTS_ENDPOINT}/${address}?withGuardianInfo=true`;
// we need to get it with an axios instance because of cross-window user interaction issues
return axiosInstance.get(url, {
baseURL: apiAddress
});
};

export const getAccountFromApi = async (address?: string) => {
if (!address) {
return null;
}

try {
const { data } = await accountFetcher(address);
return data as AccountType;
} catch (err) {
console.error('error fetching configuration for ', address);
}

return null;
};
1 change: 1 addition & 0 deletions src/apiCalls/accounts/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './getAccountFromApi';
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { networkStore } from '../network';
import { networkSelector } from 'store/selectors/networkSelectors';
import { getState } from 'store/store';

export const getCleanApiAddress = (customApiAddress?: string) => {
const { network } = networkStore.getState();
const network = networkSelector(getState());
const apiAddress = customApiAddress ?? network.apiAddress;
return apiAddress.endsWith('/') ? apiAddress.slice(0, -1) : apiAddress;
};
2 changes: 1 addition & 1 deletion src/apiCalls/configuration/getNetworkConfigFromApi.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import axios from 'axios';
import { getCleanApiAddress } from 'store/slices/network/actions/getCleanApiAddress';
import { ApiNetworkConfigType } from 'types/network.types';
import { NETWORK_CONFIG_ENDPOINT } from '../endpoints';
import { getCleanApiAddress } from '../utils/getCleanApiAddress';

const urlIsValid = (url: string) => {
try {
Expand Down
4 changes: 4 additions & 0 deletions src/apiCalls/utils/axiosFetcher.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import { axiosInstance } from 'apiCalls/utils/axiosInstance';

export const axiosFetcher = (url: string) =>
axiosInstance.get(url).then((response) => response.data);
99 changes: 99 additions & 0 deletions src/apiCalls/utils/axiosInstance.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
import { buildAxiosFetch } from '@lifeomic/axios-fetch';
import axios, { AxiosRequestConfig, AxiosResponse } from 'axios';

// Needs to be used beacause an async call made after cross-window user interaction makes the dapp unresponsive

const fetch = buildAxiosFetch(axios);

const getFormattedAxiosResponse = async <T>(response: Response, config?: T) => {
if (!response.ok) {
throw new Error(`HTTP error! Status: ${response.status}`);
}

// Clone the response to be able to read it twice (for status and data)
const clonedResponse = response.clone();

// Parse the JSON body asynchronously
const jsonPromise = clonedResponse.json();

// Return the standardized response object
const [responseData] = await Promise.all([jsonPromise]);
return {
data: responseData,
status: response.status,
statusText: response.statusText,
headers: response.headers,
config
};
};

async function customPost<T = any, R = AxiosResponse<T, any>, D = any>(
url: string,
data?: D,
config?: AxiosRequestConfig<D> | undefined
): Promise<R> {
try {
const response = await fetch(url, {
method: 'POST',
body: data ? JSON.stringify(data) : undefined,
headers: {
'Content-Type': 'application/json',
...(config?.headers || {})
},
...config
} as RequestInit);

return getFormattedAxiosResponse(response, config) as unknown as Promise<R>;
} catch (error) {
console.error('Fetch Error:', error);
throw error;
}
}

async function customGet<T = any, R = AxiosResponse<T, any>, D = any>(
url: string,
config?: AxiosRequestConfig<D> | undefined
): Promise<R> {
try {
const response = await fetch(url, config as RequestInit);
if (!response.ok) {
throw new Error(`HTTP error! Status: ${response.status}`);
}

return getFormattedAxiosResponse(response, config) as unknown as Promise<R>;
} catch (error) {
console.error('Fetch Error:', error);
throw error;
}
}

async function customPatch<T = any, R = AxiosResponse<T, any>, D = any>(
url: string,
data?: D,
config?: AxiosRequestConfig<D> | undefined
): Promise<R> {
try {
const response = await fetch(url, {
method: 'PATCH',
body: data ? JSON.stringify(data) : undefined,
headers: config?.headers || {},
...config
} as RequestInit);

if (!response.ok) {
throw new Error(`HTTP error! Status: ${response.status}`);
}

return getFormattedAxiosResponse(response, config) as unknown as Promise<R>;
} catch (error) {
console.error('Fetch Error:', error);
throw error;
}
}

const axiosInstance = axios.create();
axiosInstance.get = customGet;
axiosInstance.post = customPost;
axiosInstance.patch = customPatch;

export { axiosInstance };
8 changes: 8 additions & 0 deletions src/apiCalls/utils/getCleanApiAddress.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { networkSelector } from 'store/selectors/networkSelectors';
import { getState } from 'store/store';

export const getCleanApiAddress = (customApiAddress?: string) => {
const network = networkSelector(getState());
const apiAddress = customApiAddress ?? network.apiAddress;
return apiAddress.endsWith('/') ? apiAddress.slice(0, -1) : apiAddress;
};
18 changes: 18 additions & 0 deletions src/apiCalls/utils/getScamAddressData.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import axios from 'axios';
import { ScamInfoType } from 'types/account.types';
import { ACCOUNTS_ENDPOINT } from '../endpoints';
import { networkSelector } from 'store/selectors';
import { getState } from 'store/store';

export async function getScamAddressData(addressToVerify: string) {
const { apiAddress, apiTimeout } = networkSelector(getState());

const { data } = await axios.get<{
scamInfo?: ScamInfoType;
code?: string;
}>(`${apiAddress}/${ACCOUNTS_ENDPOINT}/${addressToVerify}`, {
timeout: Number(apiTimeout)
});

return data;
}
4 changes: 4 additions & 0 deletions src/apiCalls/utils/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export * from './axiosFetcher';
export * from './axiosInstance';
export * from './getCleanApiAddress';
export * from './getScamAddressData';
10 changes: 10 additions & 0 deletions src/constants/browser.constants.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { safeWindow } from './window.constants';

const userAgent = String(safeWindow?.navigator?.userAgent);

export const isSafari = /^((?!chrome|android).)*safari/i.test(userAgent);

const isFirefoxOnWindows =
/firefox/i.test(userAgent) && /windows/i.test(userAgent);

export const isBrowserWithPopupConfirmation = isSafari || isFirefoxOnWindows;
13 changes: 13 additions & 0 deletions src/constants/errorMessages.constants.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
export const ERROR_SIGNING = 'error when signing';
export const CANCELLED = 'cancelled';
export const TRANSACTION_CANCELLED = 'Transaction canceled';
export const ERROR_SIGNING_TX = 'error signing transaction';
export const PROVIDER_NOT_INITIALIZED = 'provider not initialized';
export const MISSING_PROVIDER_MESSAGE =
'You need a signer/valid signer to send a transaction,use either WalletProvider, LedgerProvider or WalletConnect';
export const DEFAULT_TRANSACTION_STATUS_MESSAGE =
'Undefined transaction status';
export const SECOND_LOGIN_ATTEMPT_ERROR =
'Action not allowed. User is logged in. Call logout() first';
export const SENDER_DIFFERENT_THAN_LOGGED_IN_ADDRESS =
'You cannot sign transactions from a different account';
11 changes: 7 additions & 4 deletions src/constants/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
export * from './network';
export * from './placeholders';
export * from './storage';
export * from './window';
export * from './network.constants';
export * from './placeholders.constants';
export * from './storage.constants';
export * from './window.constants';
export * from './browser.constants';
export * from './errorMessages.constants';
export * from './ledger.constants';
1 change: 1 addition & 0 deletions src/constants/ledger.constants.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export const LEDGER_CONTRACT_DATA_ENABLED_VALUE = 1;
File renamed without changes.
8 changes: 8 additions & 0 deletions src/constants/placeholders.constants.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
/**
* Not Applicable
* @value N/A
*/
export const N_A = 'N/A';

export const ZERO = '0';
export const ELLIPSIS = '...';
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { createJSONStorage } from 'zustand/middleware';
import { safeWindow } from './window';
import { safeWindow } from './window.constants';

export const persistConfig: {
persistReducersStorageType: 'localStorage' | 'sessionStorage';
Expand Down
File renamed without changes.
Loading

0 comments on commit 798c0be

Please sign in to comment.