diff --git a/README.md b/README.md index d27116ece..3ed95086c 100644 --- a/README.md +++ b/README.md @@ -32,6 +32,24 @@ npm install --global browserify npm install esmify --no-save ``` +## Optional Dependencies + +### axios + +This package can make HTTP requests using `axios`, which is not bundled by default. If you plan to use the API network provider or Proxy network provider, make sure to install `axios`: + +```bash +npm install axios +``` + +### @multiversx/sdk-bls-wasm + +This package requires `@multiversx/sdk-bls-wasm` for BLS (Boneh-Lynn-Shacham) cryptographic functions, which is not bundled by default. If you plan to use BLS functionality, make sure to install this optional dependency: + +```bash +npm install @multiversx/sdk-bls-wasm +``` + ### Building the library In order to compile the library, run the following: diff --git a/package-lock.json b/package-lock.json index 26f31f194..1d439e3cc 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,7 +9,6 @@ "version": "13.7.0", "license": "MIT", "dependencies": { - "@multiversx/sdk-bls-wasm": "0.3.5", "@multiversx/sdk-transaction-decoder": "1.0.2", "@noble/ed25519": "1.7.3", "@noble/hashes": "1.3.0", @@ -46,8 +45,11 @@ "ts-node": "9.1.1", "typescript": "4.1.2" }, + "optionalDependencies": { + "@multiversx/sdk-bls-wasm": "0.3.5", + "axios": "^1.7.4" + }, "peerDependencies": { - "axios": "^1.7.4", "bignumber.js": "^9.0.1", "protobufjs": "^7.2.6" } @@ -160,6 +162,7 @@ "version": "0.3.5", "resolved": "https://registry.npmjs.org/@multiversx/sdk-bls-wasm/-/sdk-bls-wasm-0.3.5.tgz", "integrity": "sha512-c0tIdQUnbBLSt6NYU+OpeGPYdL0+GV547HeHT8Xc0BKQ7Cj0v82QUoA2QRtWrR1G4MNZmLsIacZSsf6DrIS2Bw==", + "optional": true, "engines": { "node": ">=8.9.0" } @@ -868,7 +871,7 @@ "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", - "peer": true + "optional": true }, "node_modules/available-typed-arrays": { "version": "1.0.5", @@ -886,7 +889,7 @@ "version": "1.7.4", "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.4.tgz", "integrity": "sha512-DukmaFRnY6AzAALSH4J2M3k6PkaC+MfaAGdEERRWcC9q3/TWQwLpHR8ZRLKTdQ3aBDL64EdluRDjJqKw+BPZEw==", - "peer": true, + "optional": true, "dependencies": { "follow-redirects": "^1.15.6", "form-data": "^4.0.0", @@ -1406,7 +1409,7 @@ "version": "1.0.8", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "peer": true, + "optional": true, "dependencies": { "delayed-stream": "~1.0.0" }, @@ -1624,7 +1627,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", - "peer": true, + "optional": true, "engines": { "node": ">=0.4.0" } @@ -2402,7 +2405,7 @@ "url": "https://github.com/sponsors/RubenVerborgh" } ], - "peer": true, + "optional": true, "engines": { "node": ">=4.0" }, @@ -2425,7 +2428,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", - "peer": true, + "optional": true, "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", @@ -3432,7 +3435,7 @@ "version": "1.52.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", - "peer": true, + "optional": true, "engines": { "node": ">= 0.6" } @@ -3441,7 +3444,7 @@ "version": "2.1.35", "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", - "peer": true, + "optional": true, "dependencies": { "mime-db": "1.52.0" }, @@ -4195,7 +4198,7 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", - "peer": true + "optional": true }, "node_modules/public-encrypt": { "version": "4.0.3", @@ -5281,7 +5284,8 @@ "@multiversx/sdk-bls-wasm": { "version": "0.3.5", "resolved": "https://registry.npmjs.org/@multiversx/sdk-bls-wasm/-/sdk-bls-wasm-0.3.5.tgz", - "integrity": "sha512-c0tIdQUnbBLSt6NYU+OpeGPYdL0+GV547HeHT8Xc0BKQ7Cj0v82QUoA2QRtWrR1G4MNZmLsIacZSsf6DrIS2Bw==" + "integrity": "sha512-c0tIdQUnbBLSt6NYU+OpeGPYdL0+GV547HeHT8Xc0BKQ7Cj0v82QUoA2QRtWrR1G4MNZmLsIacZSsf6DrIS2Bw==", + "optional": true }, "@multiversx/sdk-transaction-decoder": { "version": "1.0.2", @@ -5814,7 +5818,7 @@ "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", - "peer": true + "optional": true }, "available-typed-arrays": { "version": "1.0.5", @@ -5826,7 +5830,7 @@ "version": "1.7.4", "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.4.tgz", "integrity": "sha512-DukmaFRnY6AzAALSH4J2M3k6PkaC+MfaAGdEERRWcC9q3/TWQwLpHR8ZRLKTdQ3aBDL64EdluRDjJqKw+BPZEw==", - "peer": true, + "optional": true, "requires": { "follow-redirects": "^1.15.6", "form-data": "^4.0.0", @@ -6268,7 +6272,7 @@ "version": "1.0.8", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "peer": true, + "optional": true, "requires": { "delayed-stream": "~1.0.0" } @@ -6450,7 +6454,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", - "peer": true + "optional": true }, "deps-sort": { "version": "2.0.1", @@ -7045,7 +7049,7 @@ "version": "1.15.6", "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz", "integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==", - "peer": true + "optional": true }, "for-each": { "version": "0.3.3", @@ -7060,7 +7064,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", - "peer": true, + "optional": true, "requires": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", @@ -7823,13 +7827,13 @@ "version": "1.52.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", - "peer": true + "optional": true }, "mime-types": { "version": "2.1.35", "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", - "peer": true, + "optional": true, "requires": { "mime-db": "1.52.0" } @@ -8391,7 +8395,7 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", - "peer": true + "optional": true }, "public-encrypt": { "version": "4.0.3", diff --git a/package.json b/package.json index 4a5358470..0ea7fe47a 100644 --- a/package.json +++ b/package.json @@ -37,7 +37,6 @@ }, "dependencies": { "@multiversx/sdk-transaction-decoder": "1.0.2", - "@multiversx/sdk-bls-wasm": "0.3.5", "json-bigint": "1.0.0", "bech32": "1.1.4", "bip39": "3.1.0", @@ -75,7 +74,10 @@ }, "peerDependencies": { "bignumber.js": "^9.0.1", - "protobufjs": "^7.2.6", - "axios": "^1.7.4" + "protobufjs": "^7.2.6" + }, + "optionalDependencies": { + "axios": "^1.7.4", + "@multiversx/sdk-bls-wasm": "0.3.5" } } diff --git a/src/networkProviders/apiNetworkProvider.ts b/src/networkProviders/apiNetworkProvider.ts index 985a4b50e..177f3ab3d 100644 --- a/src/networkProviders/apiNetworkProvider.ts +++ b/src/networkProviders/apiNetworkProvider.ts @@ -1,5 +1,5 @@ -import axios from "axios"; import { ErrContractQuery, ErrNetworkProvider } from "../errors"; +import { getAxios } from "../utils"; import { numberToPaddedHex } from "../utils.codec"; import { AccountOnNetwork, GuardianData } from "./accounts"; import { defaultAxiosConfig, defaultPagination } from "./config"; @@ -26,12 +26,14 @@ export class ApiNetworkProvider implements INetworkProvider { private config: NetworkProviderConfig; private backingProxyNetworkProvider; private userAgentPrefix = `${BaseUserAgent}/api`; + private axios: any; constructor(url: string, config?: NetworkProviderConfig) { this.url = url; const proxyConfig = this.getProxyConfig(config); this.config = { ...defaultAxiosConfig, ...config }; this.backingProxyNetworkProvider = new ProxyNetworkProvider(url, proxyConfig); + this.axios = getAxios(); extendUserAgent(this.userAgentPrefix, this.config); } @@ -205,7 +207,7 @@ export class ApiNetworkProvider implements INetworkProvider { const url = `${this.url}/${resourceUrl}`; try { - const response = await axios.get(url, this.config); + const response = await this.axios.default.get(url, this.config); return response.data; } catch (error) { this.handleApiError(error, resourceUrl); @@ -216,7 +218,7 @@ export class ApiNetworkProvider implements INetworkProvider { const url = `${this.url}/${resourceUrl}`; try { - const response = await axios.post(url, payload, { + const response = await this.axios.default.post(url, payload, { ...this.config, headers: { "Content-Type": "application/json", diff --git a/src/networkProviders/proxyNetworkProvider.ts b/src/networkProviders/proxyNetworkProvider.ts index 4a70cf14b..e62327ea4 100644 --- a/src/networkProviders/proxyNetworkProvider.ts +++ b/src/networkProviders/proxyNetworkProvider.ts @@ -1,5 +1,5 @@ -import axios from "axios"; import { ErrContractQuery, ErrNetworkProvider } from "../errors"; +import { getAxios } from "../utils"; import { AccountOnNetwork, GuardianData } from "./accounts"; import { defaultAxiosConfig } from "./config"; import { BaseUserAgent, EsdtContractAddress } from "./constants"; @@ -22,10 +22,12 @@ export class ProxyNetworkProvider implements INetworkProvider { private url: string; private config: NetworkProviderConfig; private userAgentPrefix = `${BaseUserAgent}/proxy`; + private axios: any; constructor(url: string, config?: NetworkProviderConfig) { this.url = url; this.config = { ...defaultAxiosConfig, ...config }; + this.axios = getAxios(); extendUserAgent(this.userAgentPrefix, this.config); } @@ -227,7 +229,7 @@ export class ProxyNetworkProvider implements INetworkProvider { const url = `${this.url}/${resourceUrl}`; try { - const response = await axios.get(url, this.config); + const response = await this.axios.default.get(url, this.config); const payload = response.data.data; return payload; } catch (error) { @@ -239,7 +241,7 @@ export class ProxyNetworkProvider implements INetworkProvider { const url = `${this.url}/${resourceUrl}`; try { - const response = await axios.post(url, payload, { + const response = await this.axios.default.post(url, payload, { ...this.config, headers: { "Content-Type": "application/json", diff --git a/src/testutils/utils.ts b/src/testutils/utils.ts index 76ef1b9f8..349e82f3b 100644 --- a/src/testutils/utils.ts +++ b/src/testutils/utils.ts @@ -1,14 +1,14 @@ -import { PathLike } from "fs"; +import BigNumber from "bignumber.js"; import * as fs from "fs"; -import { SmartContract } from "../smartcontracts/smartContract"; +import { PathLike } from "fs"; +import { IChainID, IGasLimit } from "../interface"; import { Code } from "../smartcontracts/code"; +import { SmartContract } from "../smartcontracts/smartContract"; import { AbiRegistry, TypedValue } from "../smartcontracts/typesystem"; import { Transaction } from "../transaction"; import { TransactionWatcher } from "../transactionWatcher"; -import { IChainID, IGasLimit } from "../interface"; +import { getAxios } from "../utils"; import { TestWallet } from "./wallets"; -import axios, { AxiosResponse } from "axios"; -import BigNumber from "bignumber.js"; export async function prepareDeployment(obj: { deployer: TestWallet; @@ -41,7 +41,8 @@ export async function prepareDeployment(obj: { export async function loadContractCode(path: PathLike): Promise { if (isOnBrowserTests()) { - let response: AxiosResponse = await axios.get(path.toString(), { + const axios = await getAxios(); + let response: any = await axios.default.get(path.toString(), { responseType: "arraybuffer", transformResponse: [], headers: { @@ -60,7 +61,8 @@ export async function loadContractCode(path: PathLike): Promise { export async function loadAbiRegistry(path: PathLike): Promise { if (isOnBrowserTests()) { - let response: AxiosResponse = await axios.get(path.toString()); + const axios = await getAxios(); + let response: any = await axios.default.get(path.toString()); return AbiRegistry.create(response.data); } diff --git a/src/testutils/wallets.ts b/src/testutils/wallets.ts index 9c5add288..e332cec0c 100644 --- a/src/testutils/wallets.ts +++ b/src/testutils/wallets.ts @@ -1,10 +1,10 @@ -import axios from "axios"; import * as fs from "fs"; import * as path from "path"; import { Account } from "../account"; import { Address } from "../address"; import { IAddress } from "../interface"; import { IAccountOnNetwork } from "../interfaceOfNetwork"; +import { getAxios } from "../utils"; import { UserSecretKey, UserSigner } from "./../wallet"; import { readTestFile } from "./files"; import { isOnBrowserTests } from "./utils"; @@ -82,7 +82,8 @@ async function readTestWalletFileContents(name: string): Promise { } async function downloadTextFile(url: string) { - let response = await axios.get(url, { responseType: "text", transformResponse: [] }); + const axios = await getAxios(); + let response = await axios.default.get(url, { responseType: "text", transformResponse: [] }); let text = response.data.toString(); return text; } diff --git a/src/utils.ts b/src/utils.ts index dd72af659..c80c7c6df 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -56,3 +56,11 @@ export function isEmpty(value: { isEmpty?: () => boolean; length?: number }): bo return value.length === 0; } + +export function getAxios() { + try { + return require("axios"); + } catch (error) { + throw new Error("axios is required but not installed. Please install axios to make network requests."); + } +} diff --git a/src/wallet/validatorKeys.ts b/src/wallet/validatorKeys.ts index d91bc315a..4b2b856f7 100644 --- a/src/wallet/validatorKeys.ts +++ b/src/wallet/validatorKeys.ts @@ -2,20 +2,29 @@ import { ErrInvariantFailed } from "../errors"; import { guardLength } from "./assertions"; import { parseValidatorKey } from "./pem"; -const bls = require("@multiversx/sdk-bls-wasm"); - export const VALIDATOR_SECRETKEY_LENGTH = 32; export const VALIDATOR_PUBKEY_LENGTH = 96; export class BLS { private static isInitialized: boolean = false; + public static bls: any; + + private static loadBLSModule() { + if (!BLS.bls) { + try { + BLS.bls = require("@multiversx/sdk-bls-wasm"); + } catch (error) { + throw new Error("BLS module is required but not installed. Please install '@multiversx/sdk-bls-wasm'."); + } + } + } static async initIfNecessary() { if (BLS.isInitialized) { return; } - - await bls.init(bls.BLS12_381); + BLS.loadBLSModule(); + await BLS.bls.init(BLS.bls.BLS12_381); BLS.isInitialized = true; } @@ -37,7 +46,7 @@ export class ValidatorSecretKey { BLS.guardInitialized(); guardLength(buffer, VALIDATOR_SECRETKEY_LENGTH); - this.secretKey = new bls.SecretKey(); + this.secretKey = new BLS.bls.SecretKey(); this.secretKey.setLittleEndian(Uint8Array.from(buffer)); this.publicKey = this.secretKey.getPublicKey(); }