diff --git a/docs/developers/sc-calls-format.md b/docs/developers/sc-calls-format.md index 5d99fbf50..e19405019 100644 --- a/docs/developers/sc-calls-format.md +++ b/docs/developers/sc-calls-format.md @@ -116,11 +116,13 @@ c70cf50b238372fffaf7b7c5723b06b57859d424a2da621bcc1b2f317543aa36 ### Converting addresses using online tools -There are multiple (_unofficial or community supported_) tools that one can use in order to convert an address into hexadecimal encoding: +There are multiple tools that one can use in order to convert an address into hexadecimal encoding: -- https://slowli.github.io/bech32-buffer/ (go to `Data`, select `erd` as Tag and `Bech32` as Encoding) +- [https://utils.multiversx.com/converters#addresses-bech32-to-hexadecimal](https://utils.multiversx.com/converters#addresses-bech32-to-hexadecimal) -- http://207.244.241.38/elrond-converters/#bech32-to-hex +- [https://slowli.github.io/bech32-buffer](https://slowli.github.io/bech32-buffer) (go to `Data`, select `erd` as Tag and `Bech32` as Encoding) + +- [http://207.244.241.38/elrond-converters/#bech32-to-hex](http://207.244.241.38/elrond-converters/#bech32-to-hex) [comment]: # (mx-context-auto) diff --git a/docs/developers/smart-contracts.md b/docs/developers/smart-contracts.md index 36d779724..5bca8e4cb 100644 --- a/docs/developers/smart-contracts.md +++ b/docs/developers/smart-contracts.md @@ -11,10 +11,10 @@ The MultiversX Blockchain's virtual machine (VM) executes [WebAssembly](https:// written in _any programming language_ that can be compiled to WASM bytecode. **Though, we only provide support for Rust.** Developers are encouraged to use Rust for their smart contracts, however. MultiversX provides a [Rust framework](https://github.com/multiversx/mx-sdk-rs) -which allows for unusually clean and efficient code in smart contracts, a rarity in the blockchain field. -A declarative testing framework is bundled as well. For the best coding experience, +which allows for unusually clean and efficient code in smart contracts, a rarity in the blockchain field. +A declarative testing framework is bundled as well. For the best coding experience, developers have the [MultiversX IDE](https://marketplace.visualstudio.com/items?itemName=Elrond.vscode-elrond-ide) at their disposal. -Read more about the MultiversX VM [here](/learn/space-vm). +Read more about the MultiversX VM [here](/learn/space-vm). Navigate through the sidebar to see some tutorials to get you started, as well as the Rust framework documentation. diff --git a/docs/integrators/walletconnect-json-rpc-methods.md b/docs/integrators/walletconnect-json-rpc-methods.md index ae83c4bf3..e41f402ab 100644 --- a/docs/integrators/walletconnect-json-rpc-methods.md +++ b/docs/integrators/walletconnect-json-rpc-methods.md @@ -25,35 +25,39 @@ This method returns a signature and any additional properties ( e.g. Guardian in ### Parameters - 1. `Object` - Signing parameters: - 1.1. `transactions` : `Array` - Array of Transactions - 1.1.1 `Object` - Transaction Object - 1.1.1.1 `nonce` : `String` - The Nonce of the Sender. - 1.1.1.2 `value` : `String` - The Value to transfer, as a string representation of a Big Integer (can be "0"). - 1.1.1.3 `receiver` : `String` - The Address (bech32) of the Receiver. - 1.1.1.4 `sender` : `String` - The Address (bech32) of the Sender. - 1.1.1.5 `gasPrice` : `Number` - The desired Gas Price (per Gas Unit). - 1.1.1.6 `gasLimit` : `Number` - The maximum amount of Gas Units to consume. - 1.1.1.7 `data` : `String | undefined` - The base64 string representation of the Transaction's message (data). - 1.1.1.8 `chainID` : `String` - The Chain identifier. ( `1` for Mainnet, `T` for Testnet, `D` for Devnet ) - 1.1.1.9 `version` : `String | undefined` - The Version of the Transaction (e.g. 1). - 1.1.1.10 `options` : `String | undefined` - The Options of the Transaction (e.g. 1). - 1.1.1.11 `guardian` : `String | undefined` - The Address (bech32) of the Guardian. - 1.1.1.12 `receiverUsername` : `String | undefined` - The base64 string representation of the Sender's username. - 1.1.1.10 `senderUsername` : `String | undefined` - The base64 string representation of the Receiver's username. +```text +1. `Object` - Signing parameters: + 1.1. `transactions` : `Array` - Array of Transactions + 1.1.1 `Object` - Transaction Object + 1.1.1.1 `nonce` : `String` - The Nonce of the Sender. + 1.1.1.2 `value` : `String` - The Value to transfer, as a string representation of a Big Integer (can be "0"). + 1.1.1.3 `receiver` : `String` - The Address (bech32) of the Receiver. + 1.1.1.4 `sender` : `String` - The Address (bech32) of the Sender. + 1.1.1.5 `gasPrice` : `Number` - The desired Gas Price (per Gas Unit). + 1.1.1.6 `gasLimit` : `Number` - The maximum amount of Gas Units to consume. + 1.1.1.7 `data` : `String | undefined` - The base64 string representation of the Transaction's message (data). + 1.1.1.8 `chainID` : `String` - The Chain identifier. ( `1` for Mainnet, `T` for Testnet, `D` for Devnet ) + 1.1.1.9 `version` : `String | undefined` - The Version of the Transaction (e.g. 1). + 1.1.1.10 `options` : `String | undefined` - The Options of the Transaction (e.g. 1). + 1.1.1.11 `guardian` : `String | undefined` - The Address (bech32) of the Guardian. + 1.1.1.12 `receiverUsername` : `String | undefined` - The base64 string representation of the Sender's username. + 1.1.1.10 `senderUsername` : `String | undefined` - The base64 string representation of the Receiver's username. +``` [comment]: # (mx-context-auto) ### Returns - 1. `Object` - 1.1. `signatures` : `Array` - 1.1.1 `Object` - corresponding signature and optional properties response for the provided transaction - 1.1.1.1 `signature` : The Signature (hex-encoded) of the Transaction. - 1.1.1.2 `guardian` : `String | undefined` - The Address (bech32) of the Guardian. - 1.1.1.3 `guardianSignature` : `String | undefined` - The Guardian's Signature (hex-encoded) of the Transaction. - 1.1.1.4 `options` : `Number | undefined` - The Version of the Transaction (e.g. 1). - 1.1.1.5 `version` : `Number | undefined` - The Options of the Transaction (e.g. 1). +```text +1. `Object` + 1.1. `signatures` : `Array` + 1.1.1 `Object` - corresponding signature and optional properties response for the provided transaction + 1.1.1.1 `signature` : The Signature (hex-encoded) of the Transaction. + 1.1.1.2 `guardian` : `String | undefined` - The Address (bech32) of the Guardian. + 1.1.1.3 `guardianSignature` : `String | undefined` - The Guardian's Signature (hex-encoded) of the Transaction. + 1.1.1.4 `options` : `Number | undefined` - The Version of the Transaction (e.g. 1). + 1.1.1.5 `version` : `Number | undefined` - The Options of the Transaction (e.g. 1). +``` [comment]: # (mx-context-auto) @@ -120,38 +124,42 @@ The same logic applies to the Transaction Object here too. [comment]: # (mx-context-auto) -### Parameters - - 1. `Object` - Signing parameters: - 1.1. `transaction` : `Object` - Transaction Object - 1.1.1 `nonce` : `String` - The Nonce of the Sender. - 1.1.2 `value` : `String` - The Value to transfer, as a string representation of a Big Integer (can be "0"). - 1.1.3 `receiver` : `String` - The Address (bech32) of the Receiver. - 1.1.4 `sender` : `String` - The Address (bech32) of the Sender. - 1.1.5 `gasPrice` : `Number` - The desired Gas Price (per Gas Unit). - 1.1.6 `gasLimit` : `Number` - The maximum amount of Gas Units to consume. - 1.1.7 `data` : `String | undefined` - The base64 string representation of the Transaction's message (data). - 1.1.8 `chainID` : `String` - The Chain identifier. ( `1` for Mainnet, `T` for Testnet, `D` for Devnet ) - 1.1.9 `version` : `String | undefined` - The Version of the Transaction (e.g. 1). - 1.1.10 `options` : `String | undefined` - The Options of the Transaction (e.g. 1). - 1.1.11 `guardian` : `String | undefined` - The Address (bech32) of the Guardian. - 1.1.12 `receiverUsername` : `String | undefined` - The base64 string representation of the Sender's username. - 1.1.10 `senderUsername` : `String | undefined` - The base64 string representation of the Receiver's username. +### Parameters {#mvx_signTransaction-parameters} + +```text +1. `Object` - Signing parameters: + 1.1. `transaction` : `Object` - Transaction Object + 1.1.1 `nonce` : `String` - The Nonce of the Sender. + 1.1.2 `value` : `String` - The Value to transfer, as a string representation of a Big Integer (can be "0"). + 1.1.3 `receiver` : `String` - The Address (bech32) of the Receiver. + 1.1.4 `sender` : `String` - The Address (bech32) of the Sender. + 1.1.5 `gasPrice` : `Number` - The desired Gas Price (per Gas Unit). + 1.1.6 `gasLimit` : `Number` - The maximum amount of Gas Units to consume. + 1.1.7 `data` : `String | undefined` - The base64 string representation of the Transaction's message (data). + 1.1.8 `chainID` : `String` - The Chain identifier. ( `1` for Mainnet, `T` for Testnet, `D` for Devnet ) + 1.1.9 `version` : `String | undefined` - The Version of the Transaction (e.g. 1). + 1.1.10 `options` : `String | undefined` - The Options of the Transaction (e.g. 1). + 1.1.11 `guardian` : `String | undefined` - The Address (bech32) of the Guardian. + 1.1.12 `receiverUsername` : `String | undefined` - The base64 string representation of the Sender's username. + 1.1.10 `senderUsername` : `String | undefined` - The base64 string representation of the Receiver's username. +``` [comment]: # (mx-context-auto) -### Returns +### Returns {#mvx_signTransaction-returns} - 1. `Object` - corresponding signature and optional properties response for the provided transaction - 1.1 `signature` : The Signature (hex-encoded) of the Transaction. - 1.2 `guardian` : `String | undefined` - The Address (bech32) of the Guardian. - 1.3 `guardianSignature` : `String | undefined` - The Guardian's Signature (hex-encoded) of the Transaction. - 1.4 `options` : `Number | undefined` - The Version of the Transaction (e.g. 1). - 1.5 `version` : `Number | undefined` - The Options of the Transaction (e.g. 1). +```text +1. `Object` - corresponding signature and optional properties response for the provided transaction + 1.1 `signature` : The Signature (hex-encoded) of the Transaction. + 1.2 `guardian` : `String | undefined` - The Address (bech32) of the Guardian. + 1.3 `guardianSignature` : `String | undefined` - The Guardian's Signature (hex-encoded) of the Transaction. + 1.4 `options` : `Number | undefined` - The Version of the Transaction (e.g. 1). + 1.5 `version` : `Number | undefined` - The Options of the Transaction (e.g. 1). +``` [comment]: # (mx-context-auto) -### Example +### Example {#mvx_signTransaction-example} ```javascript // Request @@ -192,22 +200,26 @@ This method returns a signature for the provided message from the requested sign [comment]: # (mx-context-auto) -### Parameters +### Parameters {#mvx_signMessage-parameters} - 1. `Object` - Signing parameters: - 1.1. `message` : `String` - the message to be signed - 1.2. `address` : `String` - bech32 formatted MultiversX address ( erd1... ) +```text +1. `Object` - Signing parameters: + 1.1. `message` : `String` - the message to be signed + 1.2. `address` : `String` - bech32 formatted MultiversX address ( erd1... ) +``` [comment]: # (mx-context-auto) -### Returns +### Returns {#mvx_signMessage-returns} - 1. `Object` - 1.1. `signature` : `String` - corresponding signature for the signed message +```text +1. `Object` + 1.1. `signature` : `String` - corresponding signature for the signed message +``` [comment]: # (mx-context-auto) -### Example +### Example {#mvx_signMessage-example} ```javascript // Request @@ -241,22 +253,26 @@ The functionality is mostly the same as `mvx_signMessage`, only in this case ins [comment]: # (mx-context-auto) -### Parameters +### Parameters {#mvx_signNativeAuthToken-parameters} - 1. `Object` - Signing parameters: - 1.1. `token` : `String` - the loginToken to be signed - 1.2. `address` : `String` - bech32 formatted MultiversX address ( erd1... ) +```text +1. `Object` - Signing parameters: + 1.1. `token` : `String` - the loginToken to be signed + 1.2. `address` : `String` - bech32 formatted MultiversX address ( erd1... ) +``` [comment]: # (mx-context-auto) -### Returns +### Returns {#mvx_signNativeAuthToken-returns} - 1. `Object` - 1.1. `signature` : `String` - corresponding signature for the signed token +```text +1. `Object` + 1.1. `signature` : `String` - corresponding signature for the signed token +``` [comment]: # (mx-context-auto) -### Example +### Example {#mvx_signNativeAuthToken-example} ```javascript // Request @@ -294,20 +310,22 @@ Wallets can implement this method to improve the UX. It is used to transmit that [comment]: # (mx-context-auto) -### Parameters +### Parameters {#mvx_cancelAction-parameters} - 1. `Object` - Action parameters - 1.1. `action` : `String | undefined` - Current action to be cancelled ( for ex. `cancelSignTx` ) +```text +1. `Object` - Action parameters + 1.1. `action` : `String | undefined` - Current action to be cancelled ( for ex. `cancelSignTx` ) +``` [comment]: # (mx-context-auto) -### Returns +### Returns {#mvx_cancelAction-parameters} - void +`void` [comment]: # (mx-context-auto) -### Example +### Example {#mvx_cancelAction-parameters} ```javascript // Request diff --git a/docs/learn/getting-started.md b/docs/learn/getting-started.md index 1835f8fa2..27e94de11 100644 --- a/docs/learn/getting-started.md +++ b/docs/learn/getting-started.md @@ -10,13 +10,17 @@ If you're not on MultiversX, get started by creating your wallet with [xPortal]( ::: ## **Learn** + If you want to learn more, get started by diving into these concepts: + - [**MultiversX Blockchain Basics**](https://www.youtube.com/watch?v=tv6OBimIX98&list=PLQVcheGWwBRWFjgEGLx1Fv2qF_6UVpSXX) - Learn about the basics of the blockchain, cryptocurrencies, consensus models, MultiversX explorer, wallet and a live demo of how to interact with the network. - [**Architecture**](/docs/learn/architecture-overview.md) - A breakdown of Multiversx's onchain system. - [**Sovereign Chains**](/docs/sovereign/overview.md) - Learn what Sovereign Chains represent for MultiversX. ## **Build** + If you are a developer, you've come to the right place. The development act is one of the easiest and most straight-forward that you will find in the entire space, with lots of tools and support offered by the foundation and community fellow developers. + - [**Get EGLD**](/docs/learn/EGLD.md#getting-egld) - You need EGLD or xEGLD in order to be able to interact with the MultiversX Network. - [**Tutorials**](https://multiversx.com/builders/build-your-first-multiversx-dapp-in-30-minutes) - A great start for anyone looking to learn what it means to develop on the MultiversX blockchain. - [**Cryptozombies**](https://cryptozombies.io/en/multiversx) - Interactive tutorials for learning how to write MultiversX Smart Contracts. @@ -27,6 +31,7 @@ If you are a developer, you've come to the right place. The development act is o - [**Support**](https://t.me/MultiversXDevelopers) - We encourage everyone to ask for support or seek answers for their questions if there are any. You can find us on [Telegram](https://t.me/MultiversXDevelopers), [Discord](https://discord.gg/multiversxbuilders) or [StackOverflow](https://stackoverflow.com/questions/tagged/multiversx). ## **Contribute** + MultiversX highly values and encourages contributions from the community, especially those who make their code public. To stay engaged with the latest developments and connect with other developers, consider joining a developer session. :::note @@ -34,6 +39,7 @@ Contributing to the [MultiversX electric-capital repository](https://github.com/ ::: ### **Repositories** + | Repository | Description | |------------|------------| | [Protocol](https://github.com/multiversx/mx-chain-go)| Implementation of the protocol| @@ -44,6 +50,7 @@ Contributing to the [MultiversX electric-capital repository](https://github.com/ | [MultiversX Organization](https://github.com/multiversx/) | Official MultiversX Github Organization| ### **Developer Sessions** + We host a bi-monthly developer session to discuss upcoming changes to the protocol, SDKs and Tools. The call is open to anyone and we expect any builder to join and get involved. - [Sessions Calendar](https://multiversx.com/events/sessions) - Calendar of all planned Developer and Validators Sessions. diff --git a/docs/sdk-and-tools/rest-api/multiversx-api.md b/docs/sdk-and-tools/rest-api/multiversx-api.md index c17267525..ef61e14a8 100644 --- a/docs/sdk-and-tools/rest-api/multiversx-api.md +++ b/docs/sdk-and-tools/rest-api/multiversx-api.md @@ -105,9 +105,9 @@ Rest API documentation of `api.multiversx.com` can be found on the [Swagger docs [comment]: # (mx-context-auto) -## References: +## References - Github repository: [https://github.com/multiversx/mx-api-service](https://github.com/multiversx/mx-api-service) - Swagger docs: [https://api.multiversx.com](https://api.multiversx.com) - Raw JSON Swagger OpenAPI definitions: [https://api.multiversx.com/-json](https://api.multiversx.com/-json) -- MultiversX blog: [https://elrond.com/blog/elrond-api-internet-scale-defi](https://elrond.com/blog/elrond-api-internet-scale-defi) +- MultiversX blog: [https://multiversx.com/blog/elrond-api-internet-scale-defi](https://multiversx.com/blog/elrond-api-internet-scale-defi) diff --git a/docs/sdk-and-tools/sdk-js/extending-sdk-js.md b/docs/sdk-and-tools/sdk-js/extending-sdk-js.md index 28c707bea..d75f129d3 100644 --- a/docs/sdk-and-tools/sdk-js/extending-sdk-js.md +++ b/docs/sdk-and-tools/sdk-js/extending-sdk-js.md @@ -24,7 +24,7 @@ The default classes from `@multiversx/sdk-network-providers` should **only be us You can derive from the default network providers (`ApiNetworkProvider` and `ProxyNetworkProvider`) and overwrite / add additional methods, making use of `doGetGeneric()` and `doPostGeneric()`. For example: -``` +```js export class MyTailoredNetworkProvider extends ApiNetworkProvider { async getEconomics(): Promise<{totalSupply: number, marketCap: number}> { let response = await this.doGetGeneric("economics"); @@ -41,7 +41,7 @@ export class MyTailoredNetworkProvider extends ApiNetworkProvider { If, for some reason, the default transaction completion detection algorithm provided by **sdk-js** does not satisfy your requirements, you may want to use a different strategy for transaction awaiting, such as: -``` +```js await transactionWatcher.awaitAllEvents(txHash, ["mySpecialEventFoo", "mySpecialEventBar"]); await transactionWatcher.awaitAnyEvents(txHash, ["mySpecialEventFoo", "mySpecialEventBar"]); ``` diff --git a/docs/sdk-and-tools/sdk-js/migration-guides.md b/docs/sdk-and-tools/sdk-js/migration-guides.md index 2ec60e645..e3b931410 100644 --- a/docs/sdk-and-tools/sdk-js/migration-guides.md +++ b/docs/sdk-and-tools/sdk-js/migration-guides.md @@ -18,5 +18,3 @@ See [migration support](https://github.com/multiversx/mx-sdk-js-core/issues?q=la ## Migrate to a newer sdk-wallet See [migration support](https://github.com/multiversx/mx-sdk-js-wallet/issues?q=label:migration). - - diff --git a/docs/sdk-and-tools/sdk-js/sdk-js-cookbook-v12.md b/docs/sdk-and-tools/sdk-js/sdk-js-cookbook-v12.md index 96e8f50c1..6771f5e1f 100644 --- a/docs/sdk-and-tools/sdk-js/sdk-js-cookbook-v12.md +++ b/docs/sdk-and-tools/sdk-js/sdk-js-cookbook-v12.md @@ -23,7 +23,7 @@ In order to migrate to the newer `sdk-js v13`, please follow [the migration guid Creating an API provider: -``` +```js import { ApiNetworkProvider } from "@multiversx/sdk-network-providers"; const apiNetworkProvider = new ApiNetworkProvider("https://devnet-api.multiversx.com"); @@ -31,7 +31,7 @@ const apiNetworkProvider = new ApiNetworkProvider("https://devnet-api.multiversx Creating a Proxy provider: -``` +```js import { ProxyNetworkProvider } from "@multiversx/sdk-network-providers"; const proxyNetworkProvider = new ProxyNetworkProvider("https://devnet-gateway.multiversx.com"); @@ -47,7 +47,7 @@ On this topic, please see [extending sdk-js](https://docs.multiversx.com/sdk-and ## Fetching network parameters -``` +```js const networkConfig = await apiNetworkProvider.getNetworkConfig(); console.log(networkConfig.MinGasPrice); console.log(networkConfig.ChainID); @@ -63,7 +63,7 @@ console.log(networkConfig.ChainID); The following snippet fetches (from the Network) the **nonce** and the **balance** of an account, and updates the local representation of the account. -``` +```js import { Account } from "@multiversx/sdk-core"; const alice = new Account(addressOfAlice); @@ -80,14 +80,14 @@ console.log("Balance:", alice.balance.toString()); When sending a bunch of transactions, you usually have to first fetch the account nonce from the network (see above), then manage it locally (e.g. increment upon signing & broadcasting a transaction): -``` +```js alice.incrementNonce(); console.log("Nonce:", alice.nonce); ``` Alternatively, you can also use `setNonce` on a `Transaction` object: -``` +```js notYetSignedTx.setNonce(alice.getNonceThenIncrement()); ``` @@ -99,7 +99,7 @@ For further reference, please see [nonce management](https://docs.multiversx.com A `TokenTransfer` object for **EGLD transfers** (value movements): -``` +```js import { TokenTransfer } from "@multiversx/sdk-core"; let firstTransfer = TokenTransfer.egldFromAmount("1.5"); @@ -111,7 +111,7 @@ console.log(firstTransfer.toPrettyString(), secondTransfer.toPrettyString()); A `TokenTransfer` object for transferring **fungible** tokens: -``` +```js const identifier = "FOO-123456"; const numDecimals = 2; firstTransfer = TokenTransfer.fungibleFromAmount(identifier, "1.5", numDecimals); @@ -125,7 +125,7 @@ console.log(secondTransfer.toPrettyString()); // Will output: 40.00 FOO-123456. A `TokenTransfer` object for transferring **semi-fungible** tokens: -``` +```js let nonce = 3; let quantity = 50; let transfer = TokenTransfer.semiFungible(identifier, nonce, quantity); @@ -133,14 +133,14 @@ let transfer = TokenTransfer.semiFungible(identifier, nonce, quantity); A `TokenTransfer` object for transferring **non-fungible** tokens (the quantity doesn't need to be specified for NFTs, as the token is only one of its kind): -``` +```js nonce = 7; transfer = TokenTransfer.nonFungible(identifier, nonce); ``` A `TokenTransfer` object for transferring **meta-esdt** tokens: -``` +```js transfer = TokenTransfer.metaEsdtFromAmount(identifier, nonce, "0.1", numDecimals); ``` @@ -152,7 +152,7 @@ transfer = TokenTransfer.metaEsdtFromAmount(identifier, nonce, "0.1", numDecimal ### Preparing a simple transaction -``` +```js import { Transaction, TransactionPayload } from "@multiversx/sdk-core"; const tx = new Transaction({ @@ -171,7 +171,7 @@ tx.setNonce(alice.getNonceThenIncrement()); ### Broadcast using a network provider -``` +```js let txHash = await proxyNetworkProvider.sendTransaction(tx); console.log("Hash:", txHash); ``` @@ -186,7 +186,7 @@ Note that, for all purposes, **we recommend using [sdk-dapp](https://github.com/ ### Broadcast using `axios` -``` +```js import axios from "axios"; const data = readyToBroadcastTx.toSendable(); @@ -203,7 +203,7 @@ let txHash = response.data.txHash; ### Wait for transaction completion -``` +```js import { TransactionWatcher } from "@multiversx/sdk-core"; const watcher = new TransactionWatcher(apiNetworkProvider); @@ -212,14 +212,14 @@ const transactionOnNetwork = await watcher.awaitCompleted(tx); If only the `txHash` is available, then: -``` +```js const transactionOnNetwork = await watcher.awaitCompleted({ getHash: () => txHash }); console.log(transactionOnNetwork); ``` In order to wait for multiple transactions: -``` +```js await Promise.all([watcher.awaitCompleted(tx1), watcher.awaitCompleted(tx2), watcher.awaitCompleted(tx3)]); ``` @@ -231,7 +231,7 @@ For a different awaiting strategy, also see [extending sdk-js](https://docs.mult First, let's create a `TransferTransactionsFactory`. -``` +```js import { GasEstimator, TransferTransactionsFactory } from "@multiversx/sdk-core"; const factory = new TransferTransactionsFactory(new GasEstimator()); @@ -241,7 +241,7 @@ const factory = new TransferTransactionsFactory(new GasEstimator()); ### Single ESDT transfer -``` +```js import { TokenTransfer } from "@multiversx/sdk-core"; const transfer1 = TokenTransfer.fungibleFromAmount("TEST-8b028f", "100.00", 2); @@ -259,7 +259,7 @@ const tx1 = factory.createESDTTransfer({ ### Single NFT transfer -``` +```js const transfer2 = TokenTransfer.nonFungible("TEST-38f249", 1); const tx2 = factory.createESDTNFTTransfer({ @@ -275,7 +275,7 @@ const tx2 = factory.createESDTNFTTransfer({ ### Single SFT transfer -``` +```js const transfer3 = TokenTransfer.semiFungible("SEMI-9efd0f", 1, 5); const tx3 = factory.createESDTNFTTransfer({ @@ -291,7 +291,7 @@ const tx3 = factory.createESDTNFTTransfer({ ### Multi ESDT / NFT transfer -``` +```js const transfers = [transfer1, transfer2, transfer3]; const tx4 = factory.createMultiESDTNFTTransfer({ @@ -311,7 +311,7 @@ const tx4 = factory.createMultiESDTNFTTransfer({ ### Load the bytecode from a file -``` +```js import { Code } from "@multiversx/sdk-core"; import { promises } from "fs"; @@ -323,7 +323,7 @@ let code = Code.fromBuffer(buffer); ### Load the bytecode from an URL -``` +```js import axios from "axios"; let response = await axios.get("https://github.com/multiversx/mx-sdk-js-core/raw/main/src/testdata/counter.wasm", { @@ -344,7 +344,7 @@ code = Code.fromBuffer(buffer); Create a `SmartContract` object: -``` +```js import { SmartContract } from "@multiversx/sdk-core"; let contract = new SmartContract(); @@ -352,7 +352,7 @@ let contract = new SmartContract(); Prepare the deploy transaction: -``` +```js import { CodeMetadata } from "@multiversx/sdk-core"; const deployerAddress = addressOfAlice; @@ -372,7 +372,7 @@ Then, set the transaction nonce. Note that the account nonce must be synchronized beforehand. Also, locally increment the nonce of the deployer (optional). -``` +```js import { Account } from "@multiversx/sdk-core"; const deployer = new Account(deployerAddress); @@ -386,14 +386,14 @@ Then **sign the transaction** using a wallet / signing provider of your choice ( Upon signing, you would usually compute the contract address (deterministically computable), as follows: -``` +```js let contractAddress = SmartContract.computeAddress(deployTransaction.getSender(), deployTransaction.getNonce()); console.log("Contract address:", contractAddress.bech32()); ``` In order to broadcast the transaction and await its completion, use a network provider and a transaction watcher: -``` +```js import { TransactionWatcher } from "@multiversx/sdk-core"; await networkProvider.sendTransaction(deployTransaction); @@ -402,7 +402,7 @@ let transactionOnNetwork = await new TransactionWatcher(networkProvider).awaitCo In the end, parse the results: -``` +```js import { ResultsParser } from "@multiversx/sdk-core"; let { returnCode } = new ResultsParser().parseUntypedOutcome(transactionOnNetwork); @@ -417,7 +417,7 @@ console.log("Return code:", returnCode); ### Load the ABI from a file -``` +```js import { AbiRegistry, Address, SmartContract } from "@multiversx/sdk-core"; import { promises } from "fs"; @@ -432,7 +432,7 @@ let existingContract = new SmartContract({ address: existingContractAddress, abi ### Load the ABI from an URL -``` +```js import axios from "axios"; const response = await axios.get("https://github.com/multiversx/mx-sdk-js-core/raw/main/src/testdata/counter.abi.json"); @@ -448,7 +448,7 @@ existingContract = new SmartContract({ address: existingContractAddress, abi: ab ### When the ABI is not available -``` +```js import { AddressValue, BigUIntType, BinaryCodec, ResultsParser, SmartContract } from "@multiversx/sdk-core"; let legacyDelegationContract = new SmartContract({ @@ -475,7 +475,7 @@ console.log(decodedValue.valueOf().toFixed(0)); ### Using `Interaction`, when the ABI is not available -``` +```js import { Interaction } from "@multiversx/sdk-core"; let args = [new AddressValue(addressOfFirstDevnetDelegator)]; @@ -493,7 +493,7 @@ Then, parse the response as above. ### When the ABI is available -``` +```js import { AbiRegistry } from "@multiversx/sdk-core"; const legacyDelegationAbi = AbiRegistry.create({ @@ -528,7 +528,7 @@ console.log(values[0].valueOf().toFixed(0)); Prepare the interaction, check it, then build the query: -``` +```js legacyDelegationContract = new SmartContract({ address: legacyDelegationContractAddress, abi: legacyDelegationAbi @@ -540,7 +540,7 @@ query = interaction.check().buildQuery(); Then, run the query and parse the results: -``` +```js queryResponse = await networkProvider.queryContract(query); let typedBundle = new ResultsParser().parseQueryResponse(queryResponse, interaction.getEndpoint()); console.log(typedBundle.values[0].valueOf().toFixed(0)); @@ -548,7 +548,7 @@ console.log(typedBundle.values[0].valueOf().toFixed(0)); Depending on the context, reinterpret (cast) the results: -``` +```js let firstValueAsStruct = firstValue; ``` @@ -560,7 +560,7 @@ let firstValueAsStruct = firstValue; ### When the ABI is not available -``` +```js import { Address, AddressValue, SmartContract, U64Value } from "@multiversx/sdk-core"; let contractAddress = new Address("erd1qqqqqqqqqqqqqpgq5sup58y38q3pwyqklagxmuraetshrqwpd8ssh0ssph"); @@ -583,7 +583,7 @@ Then, sign, broadcast `tx` and wait for its completion. ### Using `Interaction`, when the ABI is not available -``` +```js import { Interaction, TokenTransfer, U32Value } from "@multiversx/sdk-core"; let args = [new U32Value(1), new U32Value(2), new U32Value(3)]; @@ -604,7 +604,7 @@ Then, sign, broadcast `tx` and wait for its completion. ### Using `Interaction`, when the ABI is available -``` +```js import { AbiRegistry } from "@multiversx/sdk-core"; let abiRegistry = AbiRegistry.create({ @@ -643,7 +643,7 @@ let tx3 = contract.methods.doSomethingWithValue([1, 2, 3]) Now let's see an example using variadic arguments, as well: -``` +```js import { StringValue, VariadicValue } from "@multiversx/sdk-core"; abiRegistry = AbiRegistry.create({ @@ -688,7 +688,7 @@ let tx4 = contract.methods.doSomething( Given an interaction: -``` +```js interaction = contract.methods.foobar([]); ``` @@ -696,7 +696,7 @@ One can apply token transfers to the smart contract call, as well. For single payments, do as follows: -``` +```js // Fungible token interaction.withSingleESDTTransfer(TokenTransfer.fungibleFromAmount("FOO-6ce17b", "1.5", 18)); @@ -706,7 +706,7 @@ interaction.withSingleESDTNFTTransfer(TokenTransfer.nonFungible("SDKJS-38f249", For multiple payments: -``` +```js interaction.withMultiESDTNFTTransfer([ TokenTransfer.fungibleFromAmount("FOO-6ce17b", "1.5", 18), TokenTransfer.nonFungible("SDKJS-38f249", 1) @@ -725,7 +725,7 @@ When the default `ResultsParser` misbehaves, please open an issue [on GitHub](ht ### When the ABI is not available -``` +```js import { ResultsParser } from "@multiversx/sdk-core"; let resultsParser = new ResultsParser(); @@ -740,7 +740,7 @@ console.log(untypedBundle.returnCode, untypedBundle.values.length); ### When the ABI is available -``` +```js let endpointDefinition = AbiRegistry.create({ "name": "counter", "endpoints": [{ @@ -759,13 +759,13 @@ console.log(typedBundle.returnCode, typedBundle.values.length); Above, `endpointDefinition` is manually constructed. However, in practice, it can be obtained from the `Interaction` object, if available in the context: -``` +```js endpointDefinition = interaction.getEndpoint(); ``` Alternatively, the `endpointDefinition` can also be obtained from the `SmartContract` object: -``` +```js let endpointDefinition = smartContract.getEndpoint("myFunction"); ``` @@ -781,7 +781,7 @@ For customizing the default parser, also see [extending sdk-js](/sdk-and-tools/s Example of decoding a transaction event having the identifier `deposit`: -``` +```js const abiContent = await promises.readFile("../contracts/example.abi.json", { encoding: "utf8" }); const abiObj = JSON.parse(abiContent); const abiRegistry = AbiRegistry.create(abiObj); @@ -805,7 +805,7 @@ console.log(JSON.stringify(outcome, null, 4)); Example of decoding a custom type (a structure) called `DepositEvent` from binary data: -``` +```js import { AbiRegistry, BinaryCodec } from "@multiversx/sdk-core"; import { promises } from "fs"; @@ -823,7 +823,7 @@ console.log(JSON.stringify(decodedValue, null, 4)); Example of decoding a custom type (a structure) called `Reward` from binary data: -``` +```js const rewardStructType = abiRegistry.getStruct("Reward"); data = Buffer.from("010000000445474c440000000201f400000000000003e80000000000000000", "hex"); @@ -842,7 +842,7 @@ For **dApps**, use the available **[signing providers](/sdk-and-tools/sdk-js/sdk Creating a `UserSigner` from a JSON wallet: -``` +```js import { UserSigner } from "@multiversx/sdk-wallet"; import { promises } from "fs"; @@ -853,14 +853,14 @@ let signer = UserSigner.fromWallet(walletObject, "password"); Creating a `UserSigner` from a PEM file: -``` +```js const pemText = await promises.readFile("../testwallets/alice.pem", { encoding: "utf8" }); signer = UserSigner.fromPem(pemText); ``` Signing a transaction: -``` +```js import { Transaction } from "@multiversx/sdk-core"; const transaction = new Transaction({ @@ -882,7 +882,7 @@ console.log("Transaction hash", transaction.getHash().toString()); Signing an arbitrary message: -``` +```js import { SignableMessage } from "@multiversx/sdk-core"; let message = new SignableMessage({ @@ -902,7 +902,7 @@ console.log("Message signature", message.getSignature().toString("hex")); Creating a `UserVerifier`: -``` +```js import { UserVerifier } from "@multiversx/sdk-wallet"; const aliceVerifier = UserVerifier.fromAddress(addressOfAlice); @@ -911,7 +911,7 @@ const bobVerifier = UserVerifier.fromAddress(addressOfBob); Suppose we have the following transaction: -``` +```js const tx = Transaction.fromPlainObject({ nonce: 42, value: "12345", @@ -930,7 +930,7 @@ const txSignature = tx.getSignature(); And / or the following message and signature: -``` +```js message = new SignableMessage({ message: Buffer.from("hello") }); serializedMessage = message.serializeForSigning(); messageSignature = Buffer.from("561bc58f1dc6b10de208b2d2c22c9a474ea5e8cabb59c3d3ce06bbda21cc46454aa71a85d5a60442bd7784effa2e062fcb8fb421c521f898abf7f5ec165e5d0f", "hex"); @@ -938,7 +938,7 @@ messageSignature = Buffer.from("561bc58f1dc6b10de208b2d2c22c9a474ea5e8cabb59c3d3 We can verify their signatures as follows: -``` +```js console.log("Is signature of Alice?", aliceVerifier.verify(serializedTx, txSignature)); console.log("Is signature of Alice?", aliceVerifier.verify(serializedMessage, messageSignature)); console.log("Is signature of Bob?", bobVerifier.verify(serializedTx, txSignature)); @@ -955,7 +955,7 @@ console.log("Is signature of Bob?", bobVerifier.verify(serializedMessage, messag In order to decode the metadata (function, arguments, transfers) from a transaction payload, do as follows: -``` +```js import { TransactionDecoder, TransactionMetadata } from "@multiversx/sdk-transaction-decoder"; let transactionOnNetwork = await networkProvider.getTransaction(txHash); diff --git a/docs/sdk-and-tools/sdk-js/sdk-js-cookbook-v13.md b/docs/sdk-and-tools/sdk-js/sdk-js-cookbook-v13.md index e080353dd..e9db37f12 100644 --- a/docs/sdk-and-tools/sdk-js/sdk-js-cookbook-v13.md +++ b/docs/sdk-and-tools/sdk-js/sdk-js-cookbook-v13.md @@ -21,7 +21,7 @@ This page is a work in progress. Please check back later for more content. Creating an API provider: -``` +```js import { ApiNetworkProvider } from "@multiversx/sdk-network-providers"; const apiNetworkProvider = new ApiNetworkProvider("https://devnet-api.multiversx.com"); @@ -29,7 +29,7 @@ const apiNetworkProvider = new ApiNetworkProvider("https://devnet-api.multiversx Creating a Proxy provider: -``` +```js import { ProxyNetworkProvider } from "@multiversx/sdk-network-providers"; const proxyNetworkProvider = new ProxyNetworkProvider("https://devnet-gateway.multiversx.com"); @@ -43,7 +43,7 @@ On this topic, please see [extending sdk-js](/sdk-and-tools/sdk-js/extending-sdk ## Fetching network parameters -``` +```js const networkConfig = await apiNetworkProvider.getNetworkConfig(); console.log(networkConfig.MinGasPrice); console.log(networkConfig.ChainID); @@ -55,7 +55,7 @@ console.log(networkConfig.ChainID); The following snippet fetches (from the Network) the **nonce** and the **balance** of an account, and updates the local representation of the account. -``` +```js import { Account } from "@multiversx/sdk-core"; const alice = new Account(addressOfAlice); @@ -70,7 +70,7 @@ console.log("Balance:", alice.balance.toString()); When sending a bunch of transactions, you usually have to first fetch the account nonce from the network (see above), then manage it locally (e.g. increment upon signing & broadcasting a transaction): -``` +```js alice.incrementNonce(); console.log("Nonce:", alice.nonce); ``` @@ -82,7 +82,7 @@ Since `sdk-core v13`, the [`Transaction`](https://multiversx.github.io/mx-sdk-js If you are using `sdk-core v13` or later, use `tx.nonce = ` to apply the nonce to a transaction. For `sdk-core v12` or earlier, use the legacy `tx.setNonce()` to apply the nonce to a transaction. -``` +```js notYetSignedTx.nonce = alice.getNonceThenIncrement(); ``` @@ -96,7 +96,7 @@ For further reference, please see [nonce management](/integrators/creating-trans Since `sdk-core v13`, the [`Transaction`](https://multiversx.github.io/mx-sdk-js-core/v13/classes/Transaction.html) class exhibits its state as public read-write properties. For example, you can access and set the `nonce` property, instead of using `getNonce` and `setNonce`. ::: -``` +```js import { Transaction } from "@multiversx/sdk-core"; const tx = new Transaction({ @@ -124,7 +124,7 @@ For the sake of simplicity, in this section we'll use a `UserSigner` object to s In real-world dApps, transactions are signed by end-users using their wallet, through a [signing provider](/sdk-and-tools/sdk-js/sdk-js-signing-providers). ::: -``` +```js import { TransactionComputer } from "@multiversx/sdk-core"; import { UserSigner } from "@multiversx/sdk-wallet"; import { promises } from "fs"; @@ -143,14 +143,14 @@ tx.signature = await signer.sign(serializedTx); In order to broadcast a transaction, use a network provider: -``` +```js const txHash = await apiNetworkProvider.sendTransaction(readyToBroadcastTx); console.log("TX hash:", txHash); ``` ### Wait for transaction completion -``` +```js import { TransactionWatcher } from "@multiversx/sdk-core"; const watcherUsingApi = new TransactionWatcher(apiNetworkProvider); @@ -160,7 +160,7 @@ const transactionOnNetworkUsingApi = await watcherUsingApi.awaitCompleted(txHash If, instead, you use a `ProxyNetworkProvider` to instantiate the [`TransactionWatcher`](https://multiversx.github.io/mx-sdk-js-core/v13/classes/TransactionWatcher.html), you'll need to patch the `getTransaction` method, so that it instructs the network provider to fetch the so-called _processing status_, as well (required by the watcher to detect transaction completion). -``` +```js const watcherUsingProxy = new TransactionWatcher({ getTransaction: async (hash) => { return await proxyNetworkProvider.getTransaction(hash, true); @@ -172,7 +172,7 @@ const transactionOnNetworkUsingProxy = await watcherUsingProxy.awaitCompleted(tx In order to wait for multiple transactions: -``` +```js await Promise.all([ watcherUsingApi.awaitCompleted(txHash1), watcherUsingApi.awaitCompleted(txHash2), @@ -187,7 +187,7 @@ they may not be immediately available. If that is an issue, you can configure the [`TransactionWatcher`](https://multiversx.github.io/mx-sdk-js-core/v13/classes/TransactionWatcher.html) to have additional **patience** before returning the transaction object. Below, we're adding a patience of 8 seconds: -``` +```js const watcherWithPatience = new TransactionWatcher(apiNetworkProvider, { patienceMilliseconds: 8000 }); ``` @@ -219,7 +219,7 @@ For formatting or parsing token amounts, see [formatting and parsing amounts](#f First, let's create a [`TransferTransactionsFactory`](https://multiversx.github.io/mx-sdk-js-core/v13/classes/TransferTransactionsFactory.html): -``` +```js import { Token, TokenTransfer, TransactionsFactoryConfig, TransferTransactionsFactory } from "@multiversx/sdk-core"; // The new approach of creating a "TransferTransactionsFactory": @@ -231,7 +231,7 @@ Now, we can use the factory to create transfer transactions. ### **EGLD** transfers (value movements) -``` +```js const tx1 = factory.createTransactionForNativeTokenTransfer({ sender: addressOfAlice, receiver: addressOfBob, @@ -244,7 +244,7 @@ tx1.nonce = 42n; ### Single ESDT transfer -``` +```js const tx2 = factory.createTransactionForESDTTokenTransfer({ sender: addressOfAlice, receiver: addressOfBob, @@ -261,7 +261,7 @@ tx2.nonce = 43n; ### Single NFT transfer -``` +```js const tx3 = factory.createTransactionForESDTTokenTransfer({ sender: addressOfAlice, receiver: addressOfBob, @@ -278,7 +278,7 @@ tx3.nonce = 44n; ### Single SFT transfer -``` +```js const tx4 = factory.createTransactionForESDTTokenTransfer({ sender: addressOfAlice, receiver: addressOfBob, @@ -295,7 +295,7 @@ tx4.nonce = 45n; ### Multi ESDT / NFT transfer -``` +```js const tx5 = factory.createTransactionForESDTTokenTransfer({ sender: addressOfAlice, receiver: addressOfBob, @@ -326,7 +326,7 @@ For formatting or parsing token amounts as numbers (with fixed number of decimal You can format amounts using `formatAmount` from `sdk-dapp`: -``` +```js import { formatAmount } from '@multiversx/sdk-dapp/utils/operations'; console.log("Format using sdk-dapp:", formatAmount({ @@ -338,7 +338,7 @@ console.log("Format using sdk-dapp:", formatAmount({ Or directly using `bignumber.js`: -``` +```js import BigNumber from "bignumber.js"; BigNumber.config({ ROUNDING_MODE: BigNumber.ROUND_FLOOR }); @@ -348,7 +348,7 @@ console.log("Format using bignumber.js:",new BigNumber("1500000000000000000").sh You can parse amounts using `parseAmount` from `sdk-dapp`: -``` +```js import { formatAmount } from '@multiversx/sdk-dapp/utils/operations'; console.log("Parse using sdk-dapp:", parseAmount("1.5", 18)); @@ -356,7 +356,7 @@ console.log("Parse using sdk-dapp:", parseAmount("1.5", 18)); Or directly using `bignumber.js`: -``` +```js console.log("Parse using bignumber.js:", new BigNumber("1.5").shiftedBy(18).decimalPlaces(0).toFixed(0)); ``` @@ -367,7 +367,7 @@ While contract interactions are possible without the ABI, they are easier to imp ### Load the ABI from a file -``` +```js import { AbiRegistry } from "@multiversx/sdk-core"; import { promises } from "fs"; @@ -378,7 +378,7 @@ let abi = AbiRegistry.create(abiObj); ### Load the ABI from an URL -``` +```js import axios from "axios"; const response = await axios.get("https://github.com/multiversx/mx-sdk-js-core/raw/main/src/testdata/counter.abi.json"); @@ -389,7 +389,7 @@ abi = AbiRegistry.create(response.data); If an ABI file isn't directly available, but you do have knowledge of the contract's endpoints and types, you can manually construct the ABI. Let's see a simple example: -``` +```js abi = AbiRegistry.create({ "endpoints": [{ "name": "add", @@ -401,7 +401,7 @@ abi = AbiRegistry.create({ An endpoint with both inputs and outputs: -``` +```js abi = AbiRegistry.create({ "endpoints": [ { @@ -431,7 +431,7 @@ abi = AbiRegistry.create({ ### Load the bytecode from a file -``` +```js import { Code } from "@multiversx/sdk-core"; const codeBuffer = await promises.readFile("../contracts/adder.wasm"); @@ -449,7 +449,7 @@ At some point in the future, [`SmartContract.deploy()`](https://multiversx.githu Now, let's create a [`SmartContractTransactionsFactory`](https://multiversx.github.io/mx-sdk-js-core/v13/classes/SmartContractTransactionsFactory.html): -``` +```js import { SmartContractTransactionsFactory, TransactionsFactoryConfig } from "@multiversx/sdk-core"; const factoryConfig = new TransactionsFactoryConfig({ chainID: "D" }); @@ -461,7 +461,7 @@ let factory = new SmartContractTransactionsFactory({ If the contract ABI is available, provide it to the factory: -``` +```js factory = new SmartContractTransactionsFactory({ config: factoryConfig, abi: abi @@ -470,7 +470,7 @@ factory = new SmartContractTransactionsFactory({ Now, prepare the deploy transaction: -``` +```js import { U32Value } from "@multiversx/sdk-core"; // For deploy arguments, use "TypedValue" objects if you haven't provided an ABI to the factory: @@ -491,14 +491,16 @@ When creating transactions using [`SmartContractTransactionsFactory`](https://mu you can still use [`TypedValue`](https://multiversx.github.io/mx-sdk-js-core/v13/classes/TypedValue.html) objects as arguments for deployments and interactions. Even further, you can use a mix of [`TypedValue`](https://multiversx.github.io/mx-sdk-js-core/v13/classes/TypedValue.html) objects and plain JavaScript values and objects. For example: -``` + +```js let args = [new U32Value(42), "hello", { foo: "bar" }, new TokenIdentifierValue("TEST-abcdef")]; ``` + ::: Then, as [previously seen](#working-with-accounts), set the transaction nonce (the account nonce must be synchronized beforehand). -``` +```js deployTransaction.nonce = deployer.getNonceThenIncrement(); ``` @@ -509,7 +511,7 @@ For the sake of simplicity, in this section we'll use a `UserSigner` object to s In real-world dApps, transactions are signed by end-users using their wallet, through a [signing provider](/sdk-and-tools/sdk-js/sdk-js-signing-providers). ::: -``` +```js const fileContent = await promises.readFile("../testwallets/alice.json", { encoding: "utf8" }); const walletObject = JSON.parse(fileContent); const signer = UserSigner.fromWallet(walletObject, "password"); @@ -522,7 +524,7 @@ deployTransaction.signature = await signer.sign(serializedTx); Then, broadcast the transaction and await its completion, as seen in the section [broadcasting transactions](#broadcasting-transactions): -``` +```js const txHash = await apiNetworkProvider.sendTransaction(deployTransaction); const transactionOnNetwork = await new TransactionWatcher(apiNetworkProvider).awaitCompleted(txHash); ``` @@ -532,7 +534,7 @@ const transactionOnNetwork = await new TransactionWatcher(apiNetworkProvider).aw Even before broadcasting, at the moment you know the _sender_ address and the _nonce_ for your deployment transaction, you can (deterministically) compute the (upcoming) address of the contract: -``` +```js import { AddressComputer } from "@multiversx/sdk-core"; const addressComputer = new AddressComputer(); @@ -559,7 +561,7 @@ Currently, for the JavaScript / TypeScript SDKs, the _converters_ and _adapters_ However, this might change in the future - see the [sdk-specs](https://github.com/multiversx/mx-sdk-specs). ::: -``` +```js import { SmartContractTransactionsOutcomeParser, TransactionsConverter } from "@multiversx/sdk-core"; const converter = new TransactionsConverter(); @@ -583,7 +585,7 @@ However, at some point in the (more distant) future, they will be deprecated and Now, let's create a [`SmartContractTransactionsFactory`](https://multiversx.github.io/mx-sdk-js-core/v13/classes/SmartContractTransactionsFactory.html): -``` +```js import { SmartContractTransactionsFactory, TransactionsFactoryConfig } from "@multiversx/sdk-core"; const factoryConfig = new TransactionsFactoryConfig({ chainID: "D" }); @@ -595,7 +597,7 @@ let factory = new SmartContractTransactionsFactory({ If the contract ABI is available, provide it to the factory: -``` +```js factory = new SmartContractTransactionsFactory({ config: factoryConfig, abi: abi @@ -607,7 +609,7 @@ factory = new SmartContractTransactionsFactory({ Now, let's prepare a contract transaction, to call the `add` function of our previously deployed smart contract: -``` +```js import { U32Value } from "@multiversx/sdk-core"; // For arguments, use "TypedValue" objects if you haven't provided an ABI to the factory: @@ -629,14 +631,16 @@ When creating transactions using [`SmartContractTransactionsFactory`](https://mu you can still use [`TypedValue`](https://multiversx.github.io/mx-sdk-js-core/v13/classes/TypedValue.html) objects as arguments for deployments and interactions. Even further, you can use a mix of [`TypedValue`](https://multiversx.github.io/mx-sdk-js-core/v13/classes/TypedValue.html) objects and plain JavaScript values and objects. For example: -``` + +```js let args = [new U32Value(42), "hello", { foo: "bar" }, new TokenIdentifierValue("TEST-abcdef")]; ``` + ::: Then, as [previously seen](#working-with-accounts), set the transaction nonce (the account nonce must be synchronized beforehand). -``` +```js transaction.nonce = alice.getNonceThenIncrement(); ``` @@ -647,7 +651,7 @@ For the sake of simplicity, in this section we'll use a `UserSigner` object to s In real-world dApps, transactions are signed by end-users using their wallet, through a [signing provider](/sdk-and-tools/sdk-js/sdk-js-signing-providers). ::: -``` +```js const fileContent = await promises.readFile("../testwallets/alice.json", { encoding: "utf8" }); const walletObject = JSON.parse(fileContent); const signer = UserSigner.fromWallet(walletObject, "password"); @@ -660,7 +664,7 @@ transaction.signature = await signer.sign(serializedTx); Then, broadcast the transaction and await its completion, as seen in the section [broadcasting transactions](#broadcasting-transactions): -``` +```js const txHash = await apiNetworkProvider.sendTransaction(transaction); const transactionOnNetwork = await new TransactionWatcher(apiNetworkProvider).awaitCompleted(txHash); ``` @@ -671,7 +675,7 @@ At times, you may want to send some tokens (native EGLD or ESDT) along with the For transfer & execute with native EGLD, prepare your transaction as follows: -``` +```js const transactionWithNativeTransfer = factory.createTransactionForExecute({ sender: addressOfAlice, contract: Address.fromBech32("erd1qqqqqqqqqqqqqpgq6qr0w0zzyysklfneh32eqp2cf383zc89d8sstnkl60"), @@ -686,7 +690,7 @@ Above, we're sending 1 EGLD along with the contract call. For transfer & execute with ESDT tokens, prepare your transaction as follows: -``` +```js const transactionWithTokenTransfer = factory.createTransactionForExecute({ sender: addressOfAlice, contract: Address.fromBech32("erd1qqqqqqqqqqqqqpgq6qr0w0zzyysklfneh32eqp2cf383zc89d8sstnkl60"), @@ -704,7 +708,7 @@ const transactionWithTokenTransfer = factory.createTransactionForExecute({ Or, for transferring multiple tokens (NFTs included): -``` +```js const transactionWithMultipleTokenTransfers = factory.createTransactionForExecute({ sender: addressOfAlice, contract: Address.fromBech32("erd1qqqqqqqqqqqqqpgq6qr0w0zzyysklfneh32eqp2cf383zc89d8sstnkl60"), @@ -741,7 +745,7 @@ Currently, for the JavaScript / TypeScript SDKs, the _converters_ and _adapters_ However, this might change in the future - see the [sdk-specs](https://github.com/multiversx/mx-sdk-specs). ::: -``` +```js import { SmartContractTransactionsOutcomeParser, TransactionsConverter } from "@multiversx/sdk-core"; const converter = new TransactionsConverter(); @@ -765,14 +769,14 @@ Suppose we'd like to decode a `startPerformAction` event emitted by the [**multi Let's fetch [a previously-processed transaction](https://devnet-explorer.multiversx.com/transactions/05d445cdd145ecb20374844dcc67f0b1e370b9aa28a47492402bc1a150c2bab4), to serve as an example, and convert it to a [`TransactionOutcome`](https://multiversx.github.io/mx-sdk-js-core/v13/classes/TransactionOutcome.html) (see above why): -``` +```js const transactionOnNetworkMultisig = await apiNetworkProvider.getTransaction("05d445cdd145ecb20374844dcc67f0b1e370b9aa28a47492402bc1a150c2bab4"); const transactionOutcomeMultisig = converter.transactionOnNetworkToOutcome(transactionOnNetworkMultisig); ``` Now, let's find and parse the event we are interested in: -``` +```js import { TransactionEventsParser, findEventsByFirstTopic } from "@multiversx/sdk-core"; const abiJsonMultisig = await promises.readFile("../contracts/multisig-full.abi.json", { encoding: "utf8" }); @@ -805,7 +809,7 @@ Currently, for the JavaScript / TypeScript SDKs, the _converters_ and _adapters_ However, this might change in the future - see the [sdk-specs](https://github.com/multiversx/mx-sdk-specs). ::: -``` +```js import { QueryRunnerAdapter, SmartContractQueriesController } from "@multiversx/sdk-core"; const queryRunner = new QueryRunnerAdapter({ @@ -819,7 +823,7 @@ let controller = new SmartContractQueriesController({ If the contract ABI is available, provide it to the controller: -``` +```js controller = new SmartContractQueriesController({ queryRunner: queryRunner, abi: abi @@ -828,7 +832,7 @@ controller = new SmartContractQueriesController({ Let's create a query object: -``` +```js const query = controller.createQuery({ contract: "erd1qqqqqqqqqqqqqpgq6qr0w0zzyysklfneh32eqp2cf383zc89d8sstnkl60", function: "getSum", @@ -838,7 +842,7 @@ const query = controller.createQuery({ Then, run the query against the network. You will get a [`SmartContractQueryResponse`](https://multiversx.github.io/mx-sdk-js-core/v13/classes/SmartContractQueryResponse.html) object. -``` +```js const response = await controller.runQuery(query); ``` @@ -848,7 +852,7 @@ The invocation of `controller.runQuery()` ultimately calls the VM query endpoint The response object contains the raw output of the query, which can be parsed as follows: -``` +```js const [sum] = controller.parseQueryResponse(response); console.log(sum); ``` @@ -858,7 +862,7 @@ console.log(sum); When needed, you can use the [`BinaryCodec`](https://multiversx.github.io/mx-sdk-js-core/v13/classes/BinaryCodec.html) to [decode and encode values](/developers/data/serialization-overview/) manually, leveraging contract ABIs: -``` +```js const abiJsonExample = await promises.readFile("../contracts/example.abi.json", { encoding: "utf8" }); const abiExample = AbiRegistry.create(JSON.parse(abiJsonExample)); @@ -874,7 +878,7 @@ The ABI files used within this cookbook are available [here](https://github.com/ Example of decoding a custom type (a structure) called `DepositEvent` from binary data: -``` +```js import { BinaryCodec } from "@multiversx/sdk-core"; const depositCustomType = abiExample.getCustomType("DepositEvent"); @@ -888,7 +892,7 @@ console.log(JSON.stringify(decodedValue, null, 4)); Example of decoding a custom type (a structure) called `Reward` from binary data: -``` +```js const rewardStructType = abiExample.getStruct("Reward"); data = Buffer.from("010000000445474c440000000201f400000000000003e80000000000000000", "hex"); @@ -899,7 +903,7 @@ console.log(JSON.stringify(decodedValue, null, 4)); Example of decoding a custom type (an enum) called `Action` (of [**multisig**](https://github.com/multiversx/mx-contracts-rs/tree/main/contracts/multisig) contract) from binary data: -``` +```js const actionStructType = abiMultisig.getEnum("Action"); data = Buffer.from("0500000000000000000500d006f73c4221216fa679bc559005584c4f1160e569e1000000012a0000000003616464000000010000000107", "hex"); @@ -912,7 +916,7 @@ console.log(JSON.stringify(decodedValue, null, 4)); Example of encoding a custom type (a struct) called `EsdtTokenPayment` (of [**multisig**](https://github.com/multiversx/mx-contracts-rs/tree/main/contracts/multisig) contract) into binary data: -``` +```js import { BigUIntValue, Field, Struct, TokenIdentifierValue, U64Value } from "@multiversx/sdk-core"; const paymentType = abiMultisig.getStruct("EsdtTokenPayment"); @@ -946,7 +950,7 @@ You might also be interested into the language-agnostic overview on [signing tra Creating a `UserSigner` from a JSON wallet: -``` +```js import { UserSigner } from "@multiversx/sdk-wallet"; import { promises } from "fs"; @@ -957,14 +961,14 @@ let signer = UserSigner.fromWallet(walletObject, "password"); Creating a `UserSigner` from a PEM file: -``` +```js const pemText = await promises.readFile("../testwallets/alice.pem", { encoding: "utf8" }); signer = UserSigner.fromPem(pemText); ``` Signing a transaction, as we've seen [before](#signing-a-transaction): -``` +```js import { Transaction, TransactionComputer } from "@multiversx/sdk-core"; const transaction = new Transaction({ @@ -985,7 +989,7 @@ console.log("Signature", Buffer.from(transaction.signature).toString("hex")); Signing an arbitrary message: -``` +```js import { Message, MessageComputer } from "@multiversx/sdk-core"; let message = new Message({ @@ -1003,7 +1007,7 @@ console.log("Signature", Buffer.from(message.signature).toString("hex")); Creating a `UserVerifier`: -``` +```js import { UserVerifier } from "@multiversx/sdk-wallet"; const aliceVerifier = UserVerifier.fromAddress(addressOfAlice); @@ -1012,7 +1016,7 @@ const bobVerifier = UserVerifier.fromAddress(addressOfBob); Verifying a signature: -``` +```js serializedTransaction = transactionComputer.computeBytesForVerifying(transaction); serializedMessage = messageComputer.computeBytesForVerifying(message); @@ -1028,7 +1032,7 @@ Generally speaking, signed [`Message`](https://multiversx.github.io/mx-sdk-js-co In order to prepare a message for transmission, you can use the [`MessageComputer.packMessage()`](https://multiversx.github.io/mx-sdk-js-core/v13/classes/MessageComputer.html#packMessage) utility method: -``` +```js const packedMessage = messageComputer.packMessage(message); console.log("Packed message", packedMessage); @@ -1036,7 +1040,7 @@ console.log("Packed message", packedMessage); Then, on the receiving side, you can use [`MessageComputer.unpackMessage()`](https://multiversx.github.io/mx-sdk-js-core/v13/classes/MessageComputer.html#unpackMessage) to reconstruct the message, prior verification: -``` +```js const unpackedMessage = messageComputer.unpackMessage(packedMessage); const serializedUnpackedMessage = messageComputer.computeBytesForVerifying(unpackedMessage); @@ -1055,13 +1059,13 @@ The function [`TransactionComputer.computeBytesForSigning()`](https://multiversx The behavior can be overridden by setting the _sign using hash_ flag of `transaction.options`: -``` +```js transactionComputer.applyOptionsForHashSigning(transaction); ``` Then, the transaction should be serialzed and signed as follows: -``` +```js const bytesToSign = transactionComputer.computeHashForSigning(transaction); transaction.signature = await signer.sign(bytesToSign); ``` diff --git a/docs/sdk-and-tools/sdk-js/sdk-js-cookbook-versions.md b/docs/sdk-and-tools/sdk-js/sdk-js-cookbook-versions.md index a376c68d0..202160448 100644 --- a/docs/sdk-and-tools/sdk-js/sdk-js-cookbook-versions.md +++ b/docs/sdk-and-tools/sdk-js/sdk-js-cookbook-versions.md @@ -13,5 +13,5 @@ The cookbook version corresponds to the version of the [**sdk-js-core**](https:/ Please follow the version you are interested in: - - [Cookbook v13 **(stable, current version)**](/sdk-and-tools/sdk-js/sdk-js-cookbook-v13) - - [Cookbook v12 **(legacy, previous version)**](/sdk-and-tools/sdk-js/sdk-js-cookbook-v12) +- [Cookbook v13 **(stable, current version)**](/sdk-and-tools/sdk-js/sdk-js-cookbook-v13) +- [Cookbook v12 **(legacy, previous version)**](/sdk-and-tools/sdk-js/sdk-js-cookbook-v12) diff --git a/docs/sdk-and-tools/sdk-js/sdk-js-signing-providers.md b/docs/sdk-and-tools/sdk-js/sdk-js-signing-providers.md index d159eec26..d127881bf 100644 --- a/docs/sdk-and-tools/sdk-js/sdk-js-signing-providers.md +++ b/docs/sdk-and-tools/sdk-js/sdk-js-signing-providers.md @@ -17,11 +17,11 @@ Note that for most purposes, **we recommend using [sdk-dapp](https://github.com/ Generally speaking, a signing provider is a component that supports the following use-cases: - - **Log in (trivial flow, not recommended)**: the user of a dApp is asked her MultiversX identity. The user reaches the wallet, unlocks it, and confirms the login. The flow continues back to the dApp, which is now informed about the user's blockchain address. Note, though, that this piece of information is not authenticated: the dApp receives a _hint_ about the user's address, not a _guarantee_ (proof). Sometimes (though rarely), this is enough. If in doubt, always have your users login using the **native authentication** flow (see below). - - **Log in using native authentication (recommended)**: once the user decides to log in, the dApp crafts a special piece of data called _the native authentication initial part_ - a shortly-lived artifact that contains, among others, a marker of the originating dApp and a marker of the target Network. The user is given this piece of data and she is asked to sign it, to prove her MultiversX identity. The user then reaches the wallet, which unwraps and (partly) displays the payload of _the native authentication initial part_. The user unlocks the wallet and confirms the login - under the hood, the _part_ is signed with the user's secret key. The flow continues back to the dApp, which now receives the user's blockchain address, along with a proof (signature). Then, the dApp (e.g. maybe a server-side component) can verify the signature to make sure that the user is indeed the owner of the address. - - **Log out**: once the user decides to log out from the dApp, the latter should ask the wallet to do so. Once the user is signed out, the flow continues back to the dApp. - - **Sign transactions**: while interacting with the dApp, the user might be asked to sign one or more transactions. The user reaches the wallet, unlocks it again if necessary, and confirms the signing. The flow continues back to the dApp, which receives the signed transactions, ready to be broadcasted to the Network. - - **Sign messages**: while interacting with the dApp, the user might be asked to sign an arbitrary message. The user reaches the wallet, unlocks it again if necessary, and confirms the signing. The flow continues back to the dApp, which receives the signed message. +- **Log in (trivial flow, not recommended)**: the user of a dApp is asked her MultiversX identity. The user reaches the wallet, unlocks it, and confirms the login. The flow continues back to the dApp, which is now informed about the user's blockchain address. Note, though, that this piece of information is not authenticated: the dApp receives a _hint_ about the user's address, not a _guarantee_ (proof). Sometimes (though rarely), this is enough. If in doubt, always have your users login using the **native authentication** flow (see below). +- **Log in using native authentication (recommended)**: once the user decides to log in, the dApp crafts a special piece of data called _the native authentication initial part_ - a shortly-lived artifact that contains, among others, a marker of the originating dApp and a marker of the target Network. The user is given this piece of data and she is asked to sign it, to prove her MultiversX identity. The user then reaches the wallet, which unwraps and (partly) displays the payload of _the native authentication initial part_. The user unlocks the wallet and confirms the login - under the hood, the _part_ is signed with the user's secret key. The flow continues back to the dApp, which now receives the user's blockchain address, along with a proof (signature). Then, the dApp (e.g. maybe a server-side component) can verify the signature to make sure that the user is indeed the owner of the address. +- **Log out**: once the user decides to log out from the dApp, the latter should ask the wallet to do so. Once the user is signed out, the flow continues back to the dApp. +- **Sign transactions**: while interacting with the dApp, the user might be asked to sign one or more transactions. The user reaches the wallet, unlocks it again if necessary, and confirms the signing. The flow continues back to the dApp, which receives the signed transactions, ready to be broadcasted to the Network. +- **Sign messages**: while interacting with the dApp, the user might be asked to sign an arbitrary message. The user reaches the wallet, unlocks it again if necessary, and confirms the signing. The flow continues back to the dApp, which receives the signed message. [comment]: # (mx-context-auto) diff --git a/docs/sdk-and-tools/sdk-nestjs/sdk-nestjs-auth.md b/docs/sdk-and-tools/sdk-nestjs/sdk-nestjs-auth.md index e988eb426..9796033db 100644 --- a/docs/sdk-and-tools/sdk-nestjs/sdk-nestjs-auth.md +++ b/docs/sdk-and-tools/sdk-nestjs/sdk-nestjs-auth.md @@ -18,7 +18,7 @@ This package contains a set of utilities commonly used for authentication purpos `sdk-nestjs-auth` is delivered via **npm** and it can be installed as follows: -``` +```bash npm install @multiversx/sdk-nestjs-auth ``` @@ -33,11 +33,10 @@ This package validates a payload signed by a MultiversX wallet. You can use the 3. Select a wallet you prefer to use from the modal dialog, and give it access to the page 4. **Done!** You can now copy the token and use it as a Bearer token in your requests. - To use it in your requests, you need to have an `Authorization` header with the value : +To use it in your requests, you need to have an `Authorization` header with the value : `Bearer `. - You also need to add an `origin` header with the value `https://utils.multiversx.com`. - +You also need to add an `origin` header with the value `https://utils.multiversx.com`. *Note: these steps are only needed while testing. In production, a frontend application will handle token generation* ## Utility @@ -118,6 +117,7 @@ NestJS guards can be controller-scoped, method-scoped, or global-scoped. Setting // your methods... } ``` + In the example above the `NativeAuthGuard` is controller-scoped. This means that all of the methods from `ProjectsController` will be protected by the guard. ```typescript @@ -156,11 +156,11 @@ In this case, the guard is method-scoped. Only `createProject` benefits from the } ``` - ### JWT Authenticate Guard +### JWT Authenticate Guard `JwtAuthenticateGuard` performs validation of a traditional [JSON web token](https://datatracker.ietf.org/doc/html/rfc7519). The usage is exactly the same as for the native auth guards. - ```typescript +```typescript import { JwtAuthenticateGuard } from "@multiversx/sdk-nestjs-auth"; @Controller('users') @@ -206,7 +206,8 @@ The package exposes 3 decorators : `NativeAuth`, `Jwt` and `NoAuth` ### NativeAuth Decorator The `NativeAuth` decorator accepts a single parameter. In can be one of the following values : - - `issued` - block timestamp + +- `issued` - block timestamp - `expires` - expiration time - `address` - address that signed the access token - `origin` - URL of the page that generated the token @@ -229,7 +230,7 @@ Below is an example showing how to use the decorator to extract the signers addr } ``` - ### Jwt Decorator +### Jwt Decorator The `Jwt` decorator works just like `NativeAuth`. The fields accessible inside it are dependent on the client that created the token, and are out of scope for this documentation. diff --git a/docs/sdk-and-tools/sdk-nestjs/sdk-nestjs-cache.md b/docs/sdk-and-tools/sdk-nestjs/sdk-nestjs-cache.md index 0ac1d1dba..fd28cd8a5 100644 --- a/docs/sdk-and-tools/sdk-nestjs/sdk-nestjs-cache.md +++ b/docs/sdk-and-tools/sdk-nestjs/sdk-nestjs-cache.md @@ -17,18 +17,20 @@ This package contains a set of utilities commonly used for caching purposes in t `sdk-nestjs-cache` is delivered via **npm** and it can be installed as follows: -``` +```bash npm install @multiversx/sdk-nestjs-cache ``` [comment]: # (mx-context-auto) ## Utility + The package exports two services: an **in-memory cache service** and **remote cache service**. [comment]: # (mx-context-auto) ## Table of contents + - [In Memory Cache](#in-memory-cache) - super fast in-memory caching system based on [LRU cache](https://www.npmjs.com/package/lru-cache) - [Redis Cache](#redis-cache) - Caching system based on [Redis](https://www.npmjs.com/package/@multiversx/sdk-nestjs-redis) - [Cache Service](#cache-service) - MultiversX caching system which combines in-memory and Redis cache, forming a two-layer caching system @@ -36,6 +38,7 @@ The package exports two services: an **in-memory cache service** and **remote ca [comment]: # (mx-context-auto) ## In memory cache + In memory cache, available through `InMemoryCacheService`, is used to read and write data from and into the memory storage of your Node.js instance. *Note that if you have multiple instances of your application you must sync the local cache across all your instances.* @@ -43,6 +46,7 @@ In memory cache, available through `InMemoryCacheService`, is used to read and w Let's take as an example a `ConfigService` that loads some non-crucial configuration from the database and can be cached for 10 seconds. Usage example: + ```typescript import { Injectable } from '@nestjs/common'; import { InMemoryCacheService } from '@multiversx/sdk-nestjs-cache'; @@ -66,6 +70,7 @@ export class ConfigService { } } ``` + When the `.loadConfiguration()` method is called for the first time, the `.getConfigurationFromDb()` method will be executed and the value returned from it will be set in cache with `configurationKey` key. If another `.loadConfiguration()` call comes in 10 seconds interval, the data will be returned from cache and `.getConfigurationFromDb()` will not be executed again. [comment]: # (mx-context-auto) @@ -141,6 +146,7 @@ When the `.loadConfiguration()` method is called for the first time, the `.getCo [comment]: # (mx-context-auto) ## Redis Cache + Redis cache, available through `RedisCacheService`, is a caching system build on top of Redis. It is used as a shared cache among multiple microservices. Let's build the same config loader class but with data shared across multiple clusters using Redis. The implementation is almost identical since both `InMemoryCache` and `RedisCache` have similar class structure. @@ -235,6 +241,7 @@ export class ConfigService { [comment]: # (mx-context-auto) ## Cache Service + Cache service is using both [In Memory Cache](#in-memory-cache) and [Redis Cache](#redis-cache) to form a two-layer caching system. Usage example: @@ -271,6 +278,7 @@ Whenever `.loadConfigurationMethod()` is called, the service will first look int All methods from `CacheService` use the two layer caching system except the ones that contains `local` and `remote` in their name. Those methods refer strictly to in memory cache and Redis cache. Examples: + - `.getLocal()`, `.setLocal()`, `.getOrSetLocal()` are the same methods as [In Memory Cache](#in-memory-cache) - `.getRemote()`, `.setRemove()`, `.getOrSetRemove()` are the same methods as [Redis Cache](#redis-cache) diff --git a/docs/sdk-and-tools/sdk-nestjs/sdk-nestjs-monitoring.md b/docs/sdk-and-tools/sdk-nestjs/sdk-nestjs-monitoring.md index f82581662..4e3351df1 100644 --- a/docs/sdk-and-tools/sdk-nestjs/sdk-nestjs-monitoring.md +++ b/docs/sdk-and-tools/sdk-nestjs/sdk-nestjs-monitoring.md @@ -18,18 +18,20 @@ The package relies on Prometheus to aggregate the metrics, and it is using [prom `sdk-nestjs-monitoring` is delivered via **npm,** and it can be installed as follows: -``` +```bash npm install @multiversx/sdk-nestjs-monitoring ``` [comment]: # (mx-context-auto) ## Utility + The package exports **performance profilers**, **interceptors** and **metrics**. [comment]: # (mx-context-auto) ### Performance profiler + `PerformanceProfiler` is a class exported by the package that allows you to measure the execution time of your code. ```typescript @@ -43,8 +45,9 @@ console.log(`doSomething() method execution time lasted ${profilerDurationInMs} ``` The `.stop()` method can receive two optional parameters: + - `description` - text used for default logging. Default: `undefined` -- `log` - boolean to determine if log should be printed. If `log` is set to true, the logging class used to print will be `Logger` from `"@nestjs/common"`.` `Default: `false` +- `log` - boolean to determine if log should be printed. If `log` is set to true, the logging class used to print will be `Logger` from `"@nestjs/common"`.``Default: `false` ```typescript import { PerformanceProfiler } from '@multiversx/sdk-nestjs-monitoring'; @@ -53,6 +56,7 @@ const profiler = new PerformanceProfiler(); await doSomething(); profiler.stop(`doSomething() execution time`, true); ``` + The output of the code above will be "`doSomething() execution time: 1.532ms`" --- @@ -60,6 +64,7 @@ The output of the code above will be "`doSomething() execution time: 1.532ms`" [comment]: # (mx-context-auto) ### Cpu Profiler + `CpuProfiler` is a class exported by the package that allows you to measure the CPU execution time of your code. Given that JavaScript is a single-threaded language, it's important to be mindful of the amount of CPU time allocated to certain operations, as excessive consumption can lead to slowdowns or even blockages in your process. ```typescript @@ -73,6 +78,7 @@ console.log(`doHttpRequest() method execution time lasted ${profilerDurationInMs ``` The `.stop()` method can receive two optional parameters: + - `description` - text used for default logging. Setting the description automatically triggers the printing of the `PerformanceProfiler` value. Default: `undefined` ```typescript @@ -86,6 +92,7 @@ const cpuProfiler = new CpuProfiler(); await doSomethingCpuIntensive(); cpuProfiler.stop(`doSomethingCpuIntensive() execution time`); ``` + The output of the code above will be
`doHttpRequest() execution time: 100ms, CPU time: 1ms` @@ -98,6 +105,7 @@ The output of the code above will be
[comment]: # (mx-context-auto) ## Interceptors + The package provides a series of [Nestjs Interceptors](https://docs.nestjs.com/interceptors) which will automatically log and set the CPU and overall duration for each request in a [Prometheus](https://prometheus.io) histogram ready to be scrapped by Prometheus. `LoggingInterceptor` interceptor will set the execution time of each request in a Prometheus histogram using [performance profilers](#performance-profiler). diff --git a/docs/sdk-and-tools/sdk-py/configuring-mxpy.md b/docs/sdk-and-tools/sdk-py/configuring-mxpy.md index 0a6c6db0e..0e57d4afd 100644 --- a/docs/sdk-and-tools/sdk-py/configuring-mxpy.md +++ b/docs/sdk-and-tools/sdk-py/configuring-mxpy.md @@ -17,7 +17,7 @@ mxpy's configuration is stored in the file `~/multiversx-sdk/mxpy.json`. In order to view the current configuration, one can issue the command `mxpy config dump`. Output example: -``` +```json { "dependencies.rust.tag": "" } diff --git a/docs/sdk-and-tools/sdk-py/mxpy-cli.md b/docs/sdk-and-tools/sdk-py/mxpy-cli.md index c9df3b27a..d2fff6282 100644 --- a/docs/sdk-and-tools/sdk-py/mxpy-cli.md +++ b/docs/sdk-and-tools/sdk-py/mxpy-cli.md @@ -13,7 +13,7 @@ The complete Command Line Interface is listed [**here**](https://github.com/mult For example: -``` +```sh mxpy --help mxpy tx --help mxpy tx new --help @@ -30,6 +30,7 @@ This page will guide you through the process of handling common tasks using **mx ### Upgrade using pipx In case you used **pipx** to install **mxpy**, to upgrade to a newer version, you can run the following command: + ```sh pipx upgrade multiversx-sdk-cli ``` @@ -54,11 +55,13 @@ Additionally, you might want to cleanup the shell profile files, to not alter an Using `mxpy` you can either check if a dependency is installed or install a new dependency. To check if a dependecy is installed you can use: + ```sh mxpy deps check ``` To install a new dependency you can use: + ```sh mxpy deps install ``` @@ -66,12 +69,14 @@ mxpy deps install Both `mxpy deps check ` and `mxpy deps install ` use the `` as a positional argument. To find out which dependencies can be managed using `mxpy` you can type one of the following commands and you will see which positional arguments it accepts: + ```sh mxpy deps check -h mxpy deps install -h ``` For example, in order to check if `rust` is installed you would type: + ```sh mxpy deps check rust ``` @@ -79,6 +84,7 @@ mxpy deps check rust When installing dependecies the `--overwrite` argument can be used to overwrite an existing version. For example, to install `rust`, you can simply type the command: + ```sh mxpy deps install rust ``` @@ -91,13 +97,15 @@ Generally speaking, the default `rust` version installed by `mxpy` is the one re :::note On Ubuntu (or Windows with WSL), you might need to install the following dependencies of Rust and `sc-meta` before running `mxpy deps install rust`: - + ```bash sudo apt-get install build-essential pkg-config libssl-dev ``` + ::: Here's how to install a specific version of `rust` (example): + ```sh mxpy deps install rust --overwrite ``` @@ -107,6 +115,7 @@ mxpy deps install rust --overwrite ## Creating wallets There are a couple available wallet formats: + - `raw-mnemonic` - secret phrase in plain text - `keystore-mnemonic` - secret phrase, as a password-encrypted JSON keystore file - `keystore-secret-key` - secret key (irreversibly derived from the secret phrase), as a password-encrypted JSON keystore file @@ -115,9 +124,11 @@ There are a couple available wallet formats: For this example, we are going to create a `keystore-mnemonic` wallet. Let's create a keystore wallet: + ```sh mxpy wallet new --format keystore-mnemonic --outfile test_wallet.json ``` + The wallet's mnemonic will appear, followed by a prompt to set a password for the file. Once you input the password and press "Enter", the file will be generated at the location specified by the `--outfile` argument. [comment]: # (mx-context-auto) @@ -127,16 +138,18 @@ The wallet's mnemonic will appear, followed by a prompt to set a password for th As you have read above, there are multiple ways in which you can store your secret keys. To convert a wallet from a type to another you can use: + ```sh mxpy wallet convert ``` :::info Keep in mind that the conversion isn't always possible (due to irreversible derivations of the secret phrase): - - `raw-mnemonic` can be converted to any other format - - `keystore-mnemonic` can be converted to any other format - - `keystore-secret-key` can only be converted to `pem` - - `pem` can only be converted to `keystore-secret-key` + +- `raw-mnemonic` can be converted to any other format +- `keystore-mnemonic` can be converted to any other format +- `keystore-secret-key` can only be converted to `pem` +- `pem` can only be converted to `keystore-secret-key` It's mandatory that you keep a backup of your secret phrase somewhere safe. ::: @@ -144,6 +157,7 @@ It's mandatory that you keep a backup of your secret phrase somewhere safe. Let's convert the previously created `keystore-mnemonic` to a `PEM` wallet. We discourage the use of PEM wallets for storing cryptocurrencies due to their lower security level. However, they prove to be highly convenient and user-friendly for application testing purposes. To convert the wallet we type the follwing command: + ```sh mxpy wallet convert --infile test_wallet.json --in-format keystore-mnemonic --outfile converted_wallet.pem --out-format pem ``` @@ -151,6 +165,7 @@ mxpy wallet convert --infile test_wallet.json --in-format keystore-mnemonic --ou After being prompted to enter the password you've previously set for the wallet the new `.pem` file will be created. The command arguments can be found [here](https://github.com/multiversx/mx-sdk-py-cli/blob/main/CLI.md#walletconvert) or by typing: + ```sh mxpy wallet convert --help ``` @@ -164,6 +179,7 @@ In order to deploy a smart contract on the network, you need to build it first. The contract we will be using for this examples can be found [here](https://github.com/multiversx/mx-contracts-rs/tree/main/contracts/adder). The `mxpy` command used for building contracts is: + ```sh mxpy contract build --path ``` @@ -173,6 +189,7 @@ If our working directory is already the contract's directory we can skip the `-- The generated `.wasm` file will be created in a directory called `output` inside the contract's directory. The command accepts a few parameters that you can check out [here](https://github.com/multiversx/mx-sdk-py-cli/blob/main/CLI.md#contractbuild) or by simply typing: + ```sh mxpy contract build --help ``` @@ -186,6 +203,7 @@ If you'd like to build a smart contract directly using `sc-meta` instead, please After you've built your smart contract, it can be deployed on the network. For deploying a smart contract the following command can be used: + ```sh mxpy contract deploy ``` @@ -197,6 +215,7 @@ The `--bytecode` argument specifies the path to your previously-built contract. For example, if your contract is in `~/contracts/adder`, the generated bytecode file `adder.wasm` will be in `~/contracts/adder/output`. So, when providing the `--bytecode` argument the path should be `~/contracts/adder/output/adder.wasm`. The `mxpy contract deploy` command needs a multitude of other parameters that can be checked out [here](https://github.com/multiversx/mx-sdk-py-cli/blob/main/CLI.md#contractdeploy) or by simply typing the following: + ```sh mxpy contract deploy --help ``` @@ -228,6 +247,7 @@ The `--pem` argument is used to provide the sender of the transaction, the payer After deploying our smart contract we can start interacting with it. The contract has a function called `add()` that we can call and it will increase the value stored in the contract with the value we provide. To call a function we use the `mxpy contract call` command. Here's an example of how we can do that: + ```sh mxpy contract call erd1qqqqqqqqqqqqqpgq3zrpqj3sulnc9xq95sljetxhf9s07pqtd8ssfkxjv4 \ --pem=~/multiversx-sdk/testwallets/latest/users/alice.pem --recall-nonce \ @@ -269,11 +289,13 @@ We've modified our adder contract to add `1` to every value added to the contrac Before deploying the contract we need to build it again to make sure we are using the latest version. We then deploy the newly built contract, then we call it and query it. First we build the contract: + ```sh mxpy contract build ``` Then we upgrade the contract by running: + ```sh mxpy contract upgrade erd1qqqqqqqqqqqqqpgq3zrpqj3sulnc9xq95sljetxhf9s07pqtd8ssfkxjv4 \ --bytecode ~/contracts/adder/output/adder.wasm \ @@ -286,6 +308,7 @@ mxpy contract upgrade erd1qqqqqqqqqqqqqpgq3zrpqj3sulnc9xq95sljetxhf9s07pqtd8ssfk We provide as a positional argument the contract's address that we want to upgrade, in our case the previously deployed adder contract. The `--bytecode` is used to provide the new code that will replace the old code. We also set the `--arguments` to `0` as we didn't change the constructor and the contract will start counting from `0` again. The rest of the arguments you know from all the previous operations we've done. Now let's add `5` to the contract one more time. We do so by running the following: + ```sh mxpy contract call erd1qqqqqqqqqqqqqpgq3zrpqj3sulnc9xq95sljetxhf9s07pqtd8ssfkxjv4 \ --pem=~/multiversx-sdk/testwallets/latest/users/alice.pem --recall-nonce \ @@ -295,6 +318,7 @@ mxpy contract call erd1qqqqqqqqqqqqqpgq3zrpqj3sulnc9xq95sljetxhf9s07pqtd8ssfkxjv ``` Now, if we query the contract we should see the value `6`. We added `5` in the contract but modified the contract code to add `1` to every value. Let's see! + ```sh mxpy contract query erd1qqqqqqqqqqqqqpgq3zrpqj3sulnc9xq95sljetxhf9s07pqtd8ssfkxjv4 --proxy https://devnet-gateway.multiversx.com --function getSum ``` @@ -310,6 +334,7 @@ Verifying a smart contract means ensuring that the contract deployed on the netw To learn more about reproducible builds, please follow [**this page**](/developers/reproducible-contract-builds). If you'd like to set up a Github Workflow that performs a reproducible build of your smart contract, follow the examples in [**this repository**](https://github.com/multiversx/mx-contracts-rs). The command used for verifying contracts is: + ```sh mxpy contract verify ``` @@ -339,6 +364,7 @@ The _packaged source_ passed as `--packaged-src` can be obtained either from [th ## Creating and sending transactions To create a new transaction we use the `mxpy tx new` command. Let's see how that works: + ```sh mxpy tx new --pem ~/multiversx-sdk/testwallets/latest/users/alice.pem --recall-nonce \ --receiver erd1spyavw0956vq68xj8y4tenjpq2wd5a9p2c6j8gsz7ztyrnpxrruqzu66jx \ @@ -365,9 +391,11 @@ Each guarded transaction needs an additional `50000` gas for the `gasLimit`. The :::note Here are the urls to our hosted co-signer services: -- Mainnet: https://tools.multiversx.com/guardian -- Devnet: https://devnet-tools.multiversx.com/guardian -- Testnet: https://testnet-tools.multiversx.com/guardian + +- Mainnet: [https://tools.multiversx.com/guardian](https://tools.multiversx.com/guardian) +- Devnet: [https://devnet-tools.multiversx.com/guardian](https://devnet-tools.multiversx.com/guardian) +- Testnet: [https://testnet-tools.multiversx.com/guardian](https://testnet-tools.multiversx.com/guardian) + ::: ```sh diff --git a/docs/tokens/nft-tokens.mdx b/docs/tokens/nft-tokens.mdx index e1ebacdbb..cd8f31e1a 100644 --- a/docs/tokens/nft-tokens.mdx +++ b/docs/tokens/nft-tokens.mdx @@ -736,7 +736,7 @@ Here is an example of an NFT identifier: `ABC-1a9c7d-05dc` The collection identifier is `ABC-1a9c7d` and the NFT nonce is `05dc`. Note that the `05dc` is hexadecimal encoded, it represents decimal 1500. -Also note that a MultiversX address is in bech32, so you will need to convert the address from bech32 to hexadecimal. This can be done with the `hex()` method of mx-sdk-js-core for address (all the methods for addresses can be found [here](https://github.com/multiversx/mx-sdk-js-core/blob/main/src/address.ts)) or manually with an external converter which you can find [here.](http://207.244.241.38/elrond-converters/#bech32-to-hex) +Also note that a MultiversX address is in bech32, so you will need to convert the address from bech32 to hexadecimal. This can be done with the `hex()` method of mx-sdk-js-core for address (all the methods for addresses can be found [here](https://github.com/multiversx/mx-sdk-js-core/blob/main/src/address.ts)) or manually with an external converter which you can find [here.](https://utils.multiversx.com/converters#addresses-bech32-to-hexadecimal) ::: [comment]: # (mx-context-auto) diff --git a/docs/validators/delegation-dashboard.md b/docs/validators/delegation-dashboard.md index 94e73354d..62630303b 100644 --- a/docs/validators/delegation-dashboard.md +++ b/docs/validators/delegation-dashboard.md @@ -11,7 +11,7 @@ This page describes the delegation dashboard, which is a tool that allows you to ## **Introduction** -Delegation Manager Dashboard is an open-source intuitive interface that anyone can deploy to engage their customers, partners, or friends and operate Elrond Validator nodes. +Delegation Manager Dashboard is an open-source intuitive interface that anyone can deploy to engage their customers, partners, or friends and operate MultiversX Validator nodes. With minimal effort and no coding skills, you can create a custom dashboard for your Validator node(s), and enable your community to start delegating their tokens to it. diff --git a/docs/wallet/webhooks.md b/docs/wallet/webhooks.md index 81ac6b0d5..fd9eb3a8d 100644 --- a/docs/wallet/webhooks.md +++ b/docs/wallet/webhooks.md @@ -15,7 +15,7 @@ The web wallet webhooks are links that point the user of the wallet to either lo This is useful when you need to find the user's wallet address. A common use case is that, starting from this address you can query the API for the wallet's balance or recent transactions. -__URL Parameters__ +### URL Parameters `https://wallet.multiversx.com/hook/login?callbackUrl=https://example.com/` @@ -25,9 +25,9 @@ __URL Parameters__ Upon a successful login, the user is redirected back to the callback URL along which the user's address is appended. -__Callback URL Parameters__ +### Callback URL Parameters -`https://example.com/?address=erd1cevsw7mq5uvqymjqzwqvpqtdrhckehwfz99n7praty3y7q2j7yps842mqh` +`https://example.com/?address=erd1axhx4kenjlae6sknq7zjg2g4fvzavv979r2fg425p62wkl84avtqsf7vvv` | Param | Description | | ------------- | ------------------------------- | @@ -39,7 +39,7 @@ __Callback URL Parameters__ This is useful when you need to prepopulate a transaction required to send an EGLD amount or pre-populate the transaction's data field with a smart contract function invocation. -__URL Parameters__ +### URL Parameters {#send-transaction-url-parameters} `https://wallet.multiversx.com/hook/transaction?receiver=erd1qqqqqqqqqqqqqpgqxwakt2g7u9atsnr03gqcgmhcv38pt7mkd94q6shuwt&value=0&gasLimit=250000000&data=claimRewards&callbackUrl=https://example.com/` @@ -51,9 +51,9 @@ __URL Parameters__ | data | OPTIONAL | The message (data) of the Transaction. | | callbackUrl | OPTIONAL | The URL the user should be redirected to after login. | -__Callback URL Parameters__ +### Callback URL Parameters {#send-transaction-callback-url-parameters} -`https://example.com/?status=success&txHash=48f68a2b1ca1c3a343cbe14c8b755934eb1a4bb3a4a5f7068bc8a0b52094cc89&address=erd1cevsw7mq5uvqymjqzwqvpqtdrhckehwfz99n7praty3y7q2j7yps842mqh` +`https://example.com/?status=success&txHash=48f68a2b1ca1c3a343cbe14c8b755934eb1a4bb3a4a5f7068bc8a0b52094cc89&address=erd1axhx4kenjlae6sknq7zjg2g4fvzavv979r2fg425p62wkl84avtqsf7vvv` | Param | Description | | ------------- | ----------------------------------------- | diff --git a/docusaurus.config.js b/docusaurus.config.js index f86b78352..32b5ad022 100644 --- a/docusaurus.config.js +++ b/docusaurus.config.js @@ -105,12 +105,12 @@ const config = { items: [ { href: "/developers/overview", - label: "Develop", + label: "Developers", position: "left", }, { href: "/validators/overview", - label: "Validate", + label: "Validators", position: "left", }, { @@ -119,30 +119,34 @@ const config = { position: "left", }, { - href: "/technology/architecture-overview", + href: "/learn/architecture-overview", label: "Learn", position: "left", }, { href: "https://github.com/multiversx", + label: "GitHub", position: "right", className: "header-github-link", "aria-label": "GitHub", }, { href: "https://discord.gg/multiversxbuilders", + label: "Discord", position: "right", className: "header-discord-link", "aria-label": "Discord", }, { href: "https://t.me/MultiversX", + label: "Telegram", position: "right", className: "header-telegram-link", "aria-label": "Chat", }, { type: "dropdown", + label: "Websites", position: "right", className: "header-app-change", "aria-label": "Websites", @@ -164,7 +168,7 @@ const config = { }, { label: "Bridge", - href: "https://ad-astra.multiversx.com", + href: "https://bridge.multiversx.com", target: "_blank", }, { @@ -187,9 +191,9 @@ const config = { copyright: `Copyright © ${new Date().getFullYear()} MultiversX. All rights reserved.`, }, prism: { - theme: prismThemes.vsDark, - darkTheme: prismThemes.oceanicNext, - additionalLanguages: ["rust", "tsx", "toml", "bash", "diff", "json"], + theme: prismThemes.vsLight, + darkTheme: prismThemes.vsDark, + additionalLanguages: ["rust", "tsx", "toml", "bash", "diff", "json", "solidity", "yaml"], }, algolia: { // The application ID provided by Algolia @@ -203,6 +207,16 @@ const config = { slugBase.replace(/<([^>]+?)([^>]*?)>(.*?)<\/\1>/gi, ""), }), + headTags: [ + { + tagName: "link", + attributes: { + rel: "preconnect", + href: "https://cdn.multiversx.com", + }, + }, + ], + plugins: [ [ "@docusaurus/plugin-client-redirects", @@ -478,6 +492,17 @@ const config = { }, }, ], + async function myPlugin(context, options) { + return { + name: "docusaurus-tailwindcss", + configurePostCss(postcssOptions) { + // Appends TailwindCSS and AutoPrefixer. + postcssOptions.plugins.push(require("tailwindcss")); + postcssOptions.plugins.push(require("autoprefixer")); + return postcssOptions; + }, + }; + }, ], }; diff --git a/homepage.js b/homepage.js new file mode 100644 index 000000000..9db31ea41 --- /dev/null +++ b/homepage.js @@ -0,0 +1,134 @@ +import { + faDiscord, + faTelegram, + faStackOverflow, +} from "@fortawesome/free-brands-svg-icons"; +import { faBook, faHammer, faServer } from "@fortawesome/free-solid-svg-icons"; + +const homepage = { + hero: { + title: "MultiversX Developer Docs", + subtitle: "Choose your path, you must.", + cards: [ + { + title: "Learn about MultiversX", + text: "Meet the blockchain that can offer true internet-scale performance.", + link: "/welcome/welcome-to-multiversx", + icon: faBook, + }, + { + title: "Start Building", + text: "Build your decentralized application in minutes.", + link: "/developers/overview", + icon: faHammer, + }, + { + title: "Run a validator node", + text: "Validate transactions, secure the network, and earn rewards.", + link: "/validators/overview", + icon: faServer, + }, + ], + }, + features: { + title: "Do more with MultiversX", + cards: [ + { + title: "Create a Token", + text: "Issue your own ESDT token, MultiversX's improved equivalent of ERC-20.", + link: "/tokens/intro", + }, + { + title: "Manage a Wallet", + text: "Create a wallet to send, receive and store MultiversX tokens.", + link: "/wallet/overview", + }, + { + title: "Integrate MultiversX", + text: "Follow our guide to integrate exchanges, wallets, and other platforms.", + link: "/integrators/overview", + }, + { + title: "Get the Architecture Overview", + text: "Explore MultiversX innovations.", + link: "/technology/architecture-overview", + }, + { + title: "Discover SpaceVM", + text: "A fast and secure virtual machine to power growth.", + link: "/learn/space-vm", + }, + { + title: "Get EGLD", + text: "You need EGLD or xEGLD in order to be able to interact with the MultiversX Network.", + link: "/learn/EGLD#getting-egld", + }, + { + title: "Tools & Resources", + text: "You can access the best set of tools that you may need for running your project.", + link: "https://multiversx.com/builders/builder-tools-resources", + }, + { + title: "Tutorials", + text: "A great start for anyone looking to learn.", + link: "https://multiversx.com/builders/build-your-first-multiversx-dapp-in-30-minutes", + }, + ], + }, + promo: { + title: "Build and deploy custom L2s or Appchains", + tag: "Sovereign Chains", + subtitle: + "Enable new types of use cases made possible by scalable, efficient, secure and dedicated blockchains - powered by the Sovereign Chain SDK.", + link: "sovereign/overview", + button: "Sovereign Chains Documentation", + }, + community: { + title: "Engage the developer community", + subtitle: + "Discover all places where the community gathers and the live community session happening.", + cards: [ + { + title: "Developer Discord", + text: "Connect with other developers building on MultiversX", + link: "https://discord.com/invite/multiversxbuilders", + icon: faDiscord, + }, + { + title: "Developer Telegram", + text: "Connect with other MultiversX Builders and developers", + link: "https://t.me/MultiversX", + icon: faTelegram, + }, + { + title: "Stack Overflow", + text: "Get answers to technical questions from the community", + link: "https://stackoverflow.com/questions/tagged/multiversx", + icon: faStackOverflow, + }, + ], + }, + resources: { + subtitle: "More resources:", + links: [ + { + text: "Developer Podcasts", + link: "https://open.spotify.com/show/4I6Xr5Mmd10ywvb2aj7e6Z", + }, + { + text: "Stack Overflow", + link: "https://stackoverflow.com/questions/tagged/multiversx", + }, + { + text: "Tech Talks from xDay 2023", + link: "https://www.youtube.com/watch?v=WoIa4sQuNDo", + }, + { + text: "@multiversx on X", + link: "https://twitter.com/MultiversX", + }, + ], + }, +}; + +export default homepage; diff --git a/package-lock.json b/package-lock.json index 153737b03..c267ac77e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,6 +12,10 @@ "@docusaurus/plugin-client-redirects": "3.4.0", "@docusaurus/preset-classic": "3.4.0", "@docusaurus/theme-mermaid": "3.4.0", + "@fortawesome/fontawesome-svg-core": "6.5.2", + "@fortawesome/free-brands-svg-icons": "6.5.2", + "@fortawesome/free-solid-svg-icons": "6.5.2", + "@fortawesome/react-fontawesome": "0.2.2", "@mdx-js/react": "3.0.1", "clsx": "2.1.1", "hast-util-is-element": "3.0.0", @@ -24,7 +28,10 @@ "devDependencies": { "@docusaurus/module-type-aliases": "3.4.0", "@docusaurus/types": "3.4.0", - "dotenv": "16.4.5" + "autoprefixer": "10.4.19", + "dotenv": "16.4.5", + "postcss": "8.4.39", + "tailwindcss": "3.4.4" }, "engines": { "node": ">=18.0" @@ -209,6 +216,18 @@ "@algolia/requester-common": "4.23.3" } }, + "node_modules/@alloc/quick-lru": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.2.0.tgz", + "integrity": "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/@ampproject/remapping": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", @@ -2774,6 +2793,63 @@ "node": ">=18.0" } }, + "node_modules/@fortawesome/fontawesome-common-types": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-6.5.2.tgz", + "integrity": "sha512-gBxPg3aVO6J0kpfHNILc+NMhXnqHumFxOmjYCFfOiLZfwhnnfhtsdA2hfJlDnj+8PjAs6kKQPenOTKj3Rf7zHw==", + "hasInstallScript": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/@fortawesome/fontawesome-svg-core": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-svg-core/-/fontawesome-svg-core-6.5.2.tgz", + "integrity": "sha512-5CdaCBGl8Rh9ohNdxeeTMxIj8oc3KNBgIeLMvJosBMdslK/UnEB8rzyDRrbKdL1kDweqBPo4GT9wvnakHWucZw==", + "hasInstallScript": true, + "dependencies": { + "@fortawesome/fontawesome-common-types": "6.5.2" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@fortawesome/free-brands-svg-icons": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/@fortawesome/free-brands-svg-icons/-/free-brands-svg-icons-6.5.2.tgz", + "integrity": "sha512-zi5FNYdmKLnEc0jc0uuHH17kz/hfYTg4Uei0wMGzcoCL/4d3WM3u1VMc0iGGa31HuhV5i7ZK8ZlTCQrHqRHSGQ==", + "hasInstallScript": true, + "dependencies": { + "@fortawesome/fontawesome-common-types": "6.5.2" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@fortawesome/free-solid-svg-icons": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/@fortawesome/free-solid-svg-icons/-/free-solid-svg-icons-6.5.2.tgz", + "integrity": "sha512-QWFZYXFE7O1Gr1dTIp+D6UcFUF0qElOnZptpi7PBUMylJh+vFmIedVe1Ir6RM1t2tEQLLSV1k7bR4o92M+uqlw==", + "hasInstallScript": true, + "dependencies": { + "@fortawesome/fontawesome-common-types": "6.5.2" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@fortawesome/react-fontawesome": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/@fortawesome/react-fontawesome/-/react-fontawesome-0.2.2.tgz", + "integrity": "sha512-EnkrprPNqI6SXJl//m29hpaNzOp1bruISWaOiRtkMi/xSvHJlzc2j2JAYS7egxt/EbjSNV/k6Xy0AQI6vB2+1g==", + "dependencies": { + "prop-types": "^15.8.1" + }, + "peerDependencies": { + "@fortawesome/fontawesome-svg-core": "~1 || ~6", + "react": ">=16.3" + } + }, "node_modules/@hapi/hoek": { "version": "9.3.0", "resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-9.3.0.tgz", @@ -2787,6 +2863,50 @@ "@hapi/hoek": "^9.0.0" } }, + "node_modules/@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "dev": true, + "dependencies": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@isaacs/cliui/node_modules/ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, "node_modules/@jest/schemas": { "version": "29.6.3", "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", @@ -2953,6 +3073,16 @@ "node": ">= 8" } }, + "node_modules/@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "dev": true, + "optional": true, + "engines": { + "node": ">=14" + } + }, "node_modules/@pnpm/config.env-replace": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@pnpm/config.env-replace/-/config.env-replace-1.1.0.tgz", @@ -4039,6 +4169,12 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, + "node_modules/any-promise": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", + "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==", + "dev": true + }, "node_modules/anymatch": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", @@ -4457,6 +4593,15 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/camelcase-css": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz", + "integrity": "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==", + "dev": true, + "engines": { + "node": ">= 6" + } + }, "node_modules/caniuse-api": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/caniuse-api/-/caniuse-api-3.0.0.tgz", @@ -6067,6 +6212,12 @@ "url": "https://github.com/sponsors/wooorm" } }, + "node_modules/didyoumean": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz", + "integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==", + "dev": true + }, "node_modules/diff": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/diff/-/diff-5.2.0.tgz", @@ -6086,6 +6237,12 @@ "node": ">=8" } }, + "node_modules/dlv": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz", + "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==", + "dev": true + }, "node_modules/dns-packet": { "version": "5.6.1", "resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-5.6.1.tgz", @@ -6901,6 +7058,34 @@ } } }, + "node_modules/foreground-child": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.2.1.tgz", + "integrity": "sha512-PXUUyLqrR2XCWICfv6ukppP96sdFwWbNEnfEMt7jNsISjMsvaLNinAHNDYyvkyU+SZG2BTSbT5NjG+vZslfGTA==", + "dev": true, + "dependencies": { + "cross-spawn": "^7.0.0", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/foreground-child/node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/fork-ts-checker-webpack-plugin": { "version": "6.5.3", "resolved": "https://registry.npmjs.org/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-6.5.3.tgz", @@ -8428,6 +8613,24 @@ "node": ">=0.10.0" } }, + "node_modules/jackspeak": { + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.2.tgz", + "integrity": "sha512-qH3nOSj8q/8+Eg8LUPOq3C+6HWkpUioIjDsq1+D4zY91oZvpPttw8GwtF1nReRYKXl+1AORyFqtm2f5Q1SB6/Q==", + "dev": true, + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "engines": { + "node": "14 >=14.21 || 16 >=16.20 || >=18" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" + } + }, "node_modules/jest-util": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", @@ -11534,6 +11737,15 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/minipass": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", + "dev": true, + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, "node_modules/mri": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/mri/-/mri-1.2.0.tgz", @@ -11567,6 +11779,17 @@ "multicast-dns": "cli.js" } }, + "node_modules/mz": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", + "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==", + "dev": true, + "dependencies": { + "any-promise": "^1.0.0", + "object-assign": "^4.0.1", + "thenify-all": "^1.0.0" + } + }, "node_modules/nanoid": { "version": "3.3.7", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", @@ -11700,6 +11923,15 @@ "node": ">=0.10.0" } }, + "node_modules/object-hash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz", + "integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==", + "dev": true, + "engines": { + "node": ">= 6" + } + }, "node_modules/object-inspect": { "version": "1.13.1", "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz", @@ -11890,6 +12122,12 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/package-json-from-dist": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.0.tgz", + "integrity": "sha512-dATvCeZN/8wQsGywez1mzHtTlP22H8OEfPrVMLNr4/eGa+ijtLn/6M5f0dY8UKNrC2O9UCU6SSoG3qRKnt7STw==", + "dev": true + }, "node_modules/param-case": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/param-case/-/param-case-3.0.4.tgz", @@ -12030,6 +12268,28 @@ "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" }, + "node_modules/path-scurry": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", + "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", + "dev": true, + "dependencies": { + "lru-cache": "^10.2.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + }, + "engines": { + "node": ">=16 || 14 >=14.18" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/path-scurry/node_modules/lru-cache": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", + "dev": true + }, "node_modules/path-to-regexp": { "version": "1.8.0", "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.8.0.tgz", @@ -12072,6 +12332,24 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, + "node_modules/pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/pirates": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz", + "integrity": "sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==", + "dev": true, + "engines": { + "node": ">= 6" + } + }, "node_modules/pkg-dir": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-7.0.0.tgz", @@ -12154,9 +12432,9 @@ } }, "node_modules/postcss": { - "version": "8.4.38", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.38.tgz", - "integrity": "sha512-Wglpdk03BSfXkHoQa3b/oulrotAkwrlLDRSOb9D0bN86FdRyE9lppSp33aHNPgBa0JKCoB+drFLZkQoRRYae5A==", + "version": "8.4.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.39.tgz", + "integrity": "sha512-0vzE+lAiG7hZl1/9I8yzKLx3aR9Xbof3fBHKunvMfOCYAtMhrsnccJY2iTURb9EZd5+pLuiNV9/c/GZJOHsgIw==", "funding": [ { "type": "opencollective", @@ -12173,7 +12451,7 @@ ], "dependencies": { "nanoid": "^3.3.7", - "picocolors": "^1.0.0", + "picocolors": "^1.0.1", "source-map-js": "^1.2.0" }, "engines": { @@ -12285,6 +12563,89 @@ "postcss": "^8.4.31" } }, + "node_modules/postcss-import": { + "version": "15.1.0", + "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-15.1.0.tgz", + "integrity": "sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==", + "dev": true, + "dependencies": { + "postcss-value-parser": "^4.0.0", + "read-cache": "^1.0.0", + "resolve": "^1.1.7" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "postcss": "^8.0.0" + } + }, + "node_modules/postcss-js": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-4.0.1.tgz", + "integrity": "sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw==", + "dev": true, + "dependencies": { + "camelcase-css": "^2.0.1" + }, + "engines": { + "node": "^12 || ^14 || >= 16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + "peerDependencies": { + "postcss": "^8.4.21" + } + }, + "node_modules/postcss-load-config": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-4.0.2.tgz", + "integrity": "sha512-bSVhyJGL00wMVoPUzAVAnbEoWyqRxkjv64tUl427SKnPrENtq6hJwUojroMz2VB+Q1edmi4IfrAPpami5VVgMQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "lilconfig": "^3.0.0", + "yaml": "^2.3.4" + }, + "engines": { + "node": ">= 14" + }, + "peerDependencies": { + "postcss": ">=8.0.9", + "ts-node": ">=9.0.0" + }, + "peerDependenciesMeta": { + "postcss": { + "optional": true + }, + "ts-node": { + "optional": true + } + } + }, + "node_modules/postcss-load-config/node_modules/yaml": { + "version": "2.4.5", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.4.5.tgz", + "integrity": "sha512-aBx2bnqDzVOyNKfsysjA2ms5ZlnjSAW2eG3/L5G/CSujfjLJTJsEw1bGw8kCf04KodQWk1pxlGnZ56CRxiawmg==", + "dev": true, + "bin": { + "yaml": "bin.mjs" + }, + "engines": { + "node": ">= 14" + } + }, "node_modules/postcss-loader": { "version": "7.3.4", "resolved": "https://registry.npmjs.org/postcss-loader/-/postcss-loader-7.3.4.tgz", @@ -12468,6 +12829,25 @@ "postcss": "^8.1.0" } }, + "node_modules/postcss-nested": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-6.0.1.tgz", + "integrity": "sha512-mEp4xPMi5bSWiMbsgoPfcP74lsWLHkQbZc3sY+jWYd65CUwXrUaTp0fmNpa01ZcETKlIgUdFN/MpS2xZtqL9dQ==", + "dev": true, + "dependencies": { + "postcss-selector-parser": "^6.0.11" + }, + "engines": { + "node": ">=12.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + "peerDependencies": { + "postcss": "^8.2.14" + } + }, "node_modules/postcss-normalize-charset": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/postcss-normalize-charset/-/postcss-normalize-charset-6.0.2.tgz", @@ -13219,6 +13599,15 @@ "react": ">=15" } }, + "node_modules/read-cache": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", + "integrity": "sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==", + "dev": true, + "dependencies": { + "pify": "^2.3.0" + } + }, "node_modules/readable-stream": { "version": "3.6.2", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", @@ -14389,6 +14778,27 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/string-width-cjs": { + "name": "string-width", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, "node_modules/string-width/node_modules/ansi-regex": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", @@ -14451,6 +14861,19 @@ "node": ">=8" } }, + "node_modules/strip-ansi-cjs": { + "name": "strip-ansi", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/strip-bom-string": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/strip-bom-string/-/strip-bom-string-1.0.0.tgz", @@ -14506,6 +14929,81 @@ "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.3.2.tgz", "integrity": "sha512-bhtUjWd/z6ltJiQwg0dUfxEJ+W+jdqQd8TbWLWyeIJHlnsqmGLRFFd8e5mA0AZi/zx90smXRlN66YMTcaSFifg==" }, + "node_modules/sucrase": { + "version": "3.35.0", + "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.35.0.tgz", + "integrity": "sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA==", + "dev": true, + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.2", + "commander": "^4.0.0", + "glob": "^10.3.10", + "lines-and-columns": "^1.1.6", + "mz": "^2.7.0", + "pirates": "^4.0.1", + "ts-interface-checker": "^0.1.9" + }, + "bin": { + "sucrase": "bin/sucrase", + "sucrase-node": "bin/sucrase-node" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/sucrase/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/sucrase/node_modules/commander": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", + "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", + "dev": true, + "engines": { + "node": ">= 6" + } + }, + "node_modules/sucrase/node_modules/glob": { + "version": "10.4.5", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", + "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", + "dev": true, + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/sucrase/node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", @@ -14565,6 +15063,64 @@ "node": ">= 10" } }, + "node_modules/tailwindcss": { + "version": "3.4.4", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.4.tgz", + "integrity": "sha512-ZoyXOdJjISB7/BcLTR6SEsLgKtDStYyYZVLsUtWChO4Ps20CBad7lfJKVDiejocV4ME1hLmyY0WJE3hSDcmQ2A==", + "dev": true, + "dependencies": { + "@alloc/quick-lru": "^5.2.0", + "arg": "^5.0.2", + "chokidar": "^3.5.3", + "didyoumean": "^1.2.2", + "dlv": "^1.1.3", + "fast-glob": "^3.3.0", + "glob-parent": "^6.0.2", + "is-glob": "^4.0.3", + "jiti": "^1.21.0", + "lilconfig": "^2.1.0", + "micromatch": "^4.0.5", + "normalize-path": "^3.0.0", + "object-hash": "^3.0.0", + "picocolors": "^1.0.0", + "postcss": "^8.4.23", + "postcss-import": "^15.1.0", + "postcss-js": "^4.0.1", + "postcss-load-config": "^4.0.1", + "postcss-nested": "^6.0.1", + "postcss-selector-parser": "^6.0.11", + "resolve": "^1.22.2", + "sucrase": "^3.32.0" + }, + "bin": { + "tailwind": "lib/cli.js", + "tailwindcss": "lib/cli.js" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/tailwindcss/node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/tailwindcss/node_modules/lilconfig": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.1.0.tgz", + "integrity": "sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==", + "dev": true, + "engines": { + "node": ">=10" + } + }, "node_modules/tapable": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", @@ -14705,6 +15261,27 @@ "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==" }, + "node_modules/thenify": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz", + "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==", + "dev": true, + "dependencies": { + "any-promise": "^1.0.0" + } + }, + "node_modules/thenify-all": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz", + "integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==", + "dev": true, + "dependencies": { + "thenify": ">= 3.1.0 < 4" + }, + "engines": { + "node": ">=0.8" + } + }, "node_modules/thunky": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/thunky/-/thunky-1.1.0.tgz", @@ -14781,6 +15358,12 @@ "node": ">=6.10" } }, + "node_modules/ts-interface-checker": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz", + "integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==", + "dev": true + }, "node_modules/tslib": { "version": "2.6.3", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.3.tgz", @@ -15780,6 +16363,44 @@ "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, + "node_modules/wrap-ansi-cjs": { + "name": "wrap-ansi", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/wrap-ansi-cjs/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/wrap-ansi/node_modules/ansi-regex": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", @@ -16078,6 +16699,12 @@ "@algolia/requester-common": "4.23.3" } }, + "@alloc/quick-lru": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.2.0.tgz", + "integrity": "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==", + "dev": true + }, "@ampproject/remapping": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", @@ -17847,6 +18474,43 @@ "tslib": "^2.6.0" } }, + "@fortawesome/fontawesome-common-types": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-6.5.2.tgz", + "integrity": "sha512-gBxPg3aVO6J0kpfHNILc+NMhXnqHumFxOmjYCFfOiLZfwhnnfhtsdA2hfJlDnj+8PjAs6kKQPenOTKj3Rf7zHw==" + }, + "@fortawesome/fontawesome-svg-core": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-svg-core/-/fontawesome-svg-core-6.5.2.tgz", + "integrity": "sha512-5CdaCBGl8Rh9ohNdxeeTMxIj8oc3KNBgIeLMvJosBMdslK/UnEB8rzyDRrbKdL1kDweqBPo4GT9wvnakHWucZw==", + "requires": { + "@fortawesome/fontawesome-common-types": "6.5.2" + } + }, + "@fortawesome/free-brands-svg-icons": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/@fortawesome/free-brands-svg-icons/-/free-brands-svg-icons-6.5.2.tgz", + "integrity": "sha512-zi5FNYdmKLnEc0jc0uuHH17kz/hfYTg4Uei0wMGzcoCL/4d3WM3u1VMc0iGGa31HuhV5i7ZK8ZlTCQrHqRHSGQ==", + "requires": { + "@fortawesome/fontawesome-common-types": "6.5.2" + } + }, + "@fortawesome/free-solid-svg-icons": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/@fortawesome/free-solid-svg-icons/-/free-solid-svg-icons-6.5.2.tgz", + "integrity": "sha512-QWFZYXFE7O1Gr1dTIp+D6UcFUF0qElOnZptpi7PBUMylJh+vFmIedVe1Ir6RM1t2tEQLLSV1k7bR4o92M+uqlw==", + "requires": { + "@fortawesome/fontawesome-common-types": "6.5.2" + } + }, + "@fortawesome/react-fontawesome": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/@fortawesome/react-fontawesome/-/react-fontawesome-0.2.2.tgz", + "integrity": "sha512-EnkrprPNqI6SXJl//m29hpaNzOp1bruISWaOiRtkMi/xSvHJlzc2j2JAYS7egxt/EbjSNV/k6Xy0AQI6vB2+1g==", + "requires": { + "prop-types": "^15.8.1" + } + }, "@hapi/hoek": { "version": "9.3.0", "resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-9.3.0.tgz", @@ -17860,6 +18524,37 @@ "@hapi/hoek": "^9.0.0" } }, + "@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "dev": true, + "requires": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "dev": true + }, + "strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, + "requires": { + "ansi-regex": "^6.0.1" + } + } + } + }, "@jest/schemas": { "version": "29.6.3", "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", @@ -17990,6 +18685,13 @@ "fastq": "^1.6.0" } }, + "@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "dev": true, + "optional": true + }, "@pnpm/config.env-replace": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@pnpm/config.env-replace/-/config.env-replace-1.1.0.tgz", @@ -18874,6 +19576,12 @@ "color-convert": "^2.0.1" } }, + "any-promise": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", + "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==", + "dev": true + }, "anymatch": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", @@ -19166,6 +19874,12 @@ "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==" }, + "camelcase-css": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz", + "integrity": "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==", + "dev": true + }, "caniuse-api": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/caniuse-api/-/caniuse-api-3.0.0.tgz", @@ -20271,6 +20985,12 @@ "dequal": "^2.0.0" } }, + "didyoumean": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz", + "integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==", + "dev": true + }, "diff": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/diff/-/diff-5.2.0.tgz", @@ -20284,6 +21004,12 @@ "path-type": "^4.0.0" } }, + "dlv": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz", + "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==", + "dev": true + }, "dns-packet": { "version": "5.6.1", "resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-5.6.1.tgz", @@ -20881,6 +21607,24 @@ "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz", "integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==" }, + "foreground-child": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.2.1.tgz", + "integrity": "sha512-PXUUyLqrR2XCWICfv6ukppP96sdFwWbNEnfEMt7jNsISjMsvaLNinAHNDYyvkyU+SZG2BTSbT5NjG+vZslfGTA==", + "dev": true, + "requires": { + "cross-spawn": "^7.0.0", + "signal-exit": "^4.0.1" + }, + "dependencies": { + "signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true + } + } + }, "fork-ts-checker-webpack-plugin": { "version": "6.5.3", "resolved": "https://registry.npmjs.org/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-6.5.3.tgz", @@ -21957,6 +22701,16 @@ "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==" }, + "jackspeak": { + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.2.tgz", + "integrity": "sha512-qH3nOSj8q/8+Eg8LUPOq3C+6HWkpUioIjDsq1+D4zY91oZvpPttw8GwtF1nReRYKXl+1AORyFqtm2f5Q1SB6/Q==", + "dev": true, + "requires": { + "@isaacs/cliui": "^8.0.2", + "@pkgjs/parseargs": "^0.11.0" + } + }, "jest-util": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", @@ -23787,6 +24541,12 @@ "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==" }, + "minipass": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", + "dev": true + }, "mri": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/mri/-/mri-1.2.0.tgz", @@ -23811,6 +24571,17 @@ "thunky": "^1.0.2" } }, + "mz": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", + "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==", + "dev": true, + "requires": { + "any-promise": "^1.0.0", + "object-assign": "^4.0.1", + "thenify-all": "^1.0.0" + } + }, "nanoid": { "version": "3.3.7", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", @@ -23902,6 +24673,12 @@ "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==" }, + "object-hash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz", + "integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==", + "dev": true + }, "object-inspect": { "version": "1.13.1", "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz", @@ -24026,6 +24803,12 @@ "semver": "^7.3.7" } }, + "package-json-from-dist": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.0.tgz", + "integrity": "sha512-dATvCeZN/8wQsGywez1mzHtTlP22H8OEfPrVMLNr4/eGa+ijtLn/6M5f0dY8UKNrC2O9UCU6SSoG3qRKnt7STw==", + "dev": true + }, "param-case": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/param-case/-/param-case-3.0.4.tgz", @@ -24137,6 +24920,24 @@ "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" }, + "path-scurry": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", + "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", + "dev": true, + "requires": { + "lru-cache": "^10.2.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + }, + "dependencies": { + "lru-cache": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", + "dev": true + } + } + }, "path-to-regexp": { "version": "1.8.0", "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.8.0.tgz", @@ -24170,6 +24971,18 @@ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==" }, + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", + "dev": true + }, + "pirates": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz", + "integrity": "sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==", + "dev": true + }, "pkg-dir": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-7.0.0.tgz", @@ -24227,12 +25040,12 @@ } }, "postcss": { - "version": "8.4.38", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.38.tgz", - "integrity": "sha512-Wglpdk03BSfXkHoQa3b/oulrotAkwrlLDRSOb9D0bN86FdRyE9lppSp33aHNPgBa0JKCoB+drFLZkQoRRYae5A==", + "version": "8.4.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.39.tgz", + "integrity": "sha512-0vzE+lAiG7hZl1/9I8yzKLx3aR9Xbof3fBHKunvMfOCYAtMhrsnccJY2iTURb9EZd5+pLuiNV9/c/GZJOHsgIw==", "requires": { "nanoid": "^3.3.7", - "picocolors": "^1.0.0", + "picocolors": "^1.0.1", "source-map-js": "^1.2.0" } }, @@ -24297,6 +25110,44 @@ "postcss-selector-parser": "^6.0.16" } }, + "postcss-import": { + "version": "15.1.0", + "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-15.1.0.tgz", + "integrity": "sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==", + "dev": true, + "requires": { + "postcss-value-parser": "^4.0.0", + "read-cache": "^1.0.0", + "resolve": "^1.1.7" + } + }, + "postcss-js": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-4.0.1.tgz", + "integrity": "sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw==", + "dev": true, + "requires": { + "camelcase-css": "^2.0.1" + } + }, + "postcss-load-config": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-4.0.2.tgz", + "integrity": "sha512-bSVhyJGL00wMVoPUzAVAnbEoWyqRxkjv64tUl427SKnPrENtq6hJwUojroMz2VB+Q1edmi4IfrAPpami5VVgMQ==", + "dev": true, + "requires": { + "lilconfig": "^3.0.0", + "yaml": "^2.3.4" + }, + "dependencies": { + "yaml": { + "version": "2.4.5", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.4.5.tgz", + "integrity": "sha512-aBx2bnqDzVOyNKfsysjA2ms5ZlnjSAW2eG3/L5G/CSujfjLJTJsEw1bGw8kCf04KodQWk1pxlGnZ56CRxiawmg==", + "dev": true + } + } + }, "postcss-loader": { "version": "7.3.4", "resolved": "https://registry.npmjs.org/postcss-loader/-/postcss-loader-7.3.4.tgz", @@ -24404,6 +25255,15 @@ "icss-utils": "^5.0.0" } }, + "postcss-nested": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-6.0.1.tgz", + "integrity": "sha512-mEp4xPMi5bSWiMbsgoPfcP74lsWLHkQbZc3sY+jWYd65CUwXrUaTp0fmNpa01ZcETKlIgUdFN/MpS2xZtqL9dQ==", + "dev": true, + "requires": { + "postcss-selector-parser": "^6.0.11" + } + }, "postcss-normalize-charset": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/postcss-normalize-charset/-/postcss-normalize-charset-6.0.2.tgz", @@ -24913,6 +25773,15 @@ "tiny-warning": "^1.0.0" } }, + "read-cache": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", + "integrity": "sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==", + "dev": true, + "requires": { + "pify": "^2.3.0" + } + }, "readable-stream": { "version": "3.6.2", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", @@ -25814,6 +26683,25 @@ } } }, + "string-width-cjs": { + "version": "npm:string-width@4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "dependencies": { + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + } + } + }, "stringify-entities": { "version": "4.0.4", "resolved": "https://registry.npmjs.org/stringify-entities/-/stringify-entities-4.0.4.tgz", @@ -25841,6 +26729,15 @@ "ansi-regex": "^5.0.1" } }, + "strip-ansi-cjs": { + "version": "npm:strip-ansi@6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "requires": { + "ansi-regex": "^5.0.1" + } + }, "strip-bom-string": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/strip-bom-string/-/strip-bom-string-1.0.0.tgz", @@ -25878,6 +26775,61 @@ "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.3.2.tgz", "integrity": "sha512-bhtUjWd/z6ltJiQwg0dUfxEJ+W+jdqQd8TbWLWyeIJHlnsqmGLRFFd8e5mA0AZi/zx90smXRlN66YMTcaSFifg==" }, + "sucrase": { + "version": "3.35.0", + "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.35.0.tgz", + "integrity": "sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA==", + "dev": true, + "requires": { + "@jridgewell/gen-mapping": "^0.3.2", + "commander": "^4.0.0", + "glob": "^10.3.10", + "lines-and-columns": "^1.1.6", + "mz": "^2.7.0", + "pirates": "^4.0.1", + "ts-interface-checker": "^0.1.9" + }, + "dependencies": { + "brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0" + } + }, + "commander": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", + "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", + "dev": true + }, + "glob": { + "version": "10.4.5", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", + "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", + "dev": true, + "requires": { + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" + } + }, + "minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "dev": true, + "requires": { + "brace-expansion": "^2.0.1" + } + } + } + }, "supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", @@ -25917,6 +26869,53 @@ } } }, + "tailwindcss": { + "version": "3.4.4", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.4.tgz", + "integrity": "sha512-ZoyXOdJjISB7/BcLTR6SEsLgKtDStYyYZVLsUtWChO4Ps20CBad7lfJKVDiejocV4ME1hLmyY0WJE3hSDcmQ2A==", + "dev": true, + "requires": { + "@alloc/quick-lru": "^5.2.0", + "arg": "^5.0.2", + "chokidar": "^3.5.3", + "didyoumean": "^1.2.2", + "dlv": "^1.1.3", + "fast-glob": "^3.3.0", + "glob-parent": "^6.0.2", + "is-glob": "^4.0.3", + "jiti": "^1.21.0", + "lilconfig": "^2.1.0", + "micromatch": "^4.0.5", + "normalize-path": "^3.0.0", + "object-hash": "^3.0.0", + "picocolors": "^1.0.0", + "postcss": "^8.4.23", + "postcss-import": "^15.1.0", + "postcss-js": "^4.0.1", + "postcss-load-config": "^4.0.1", + "postcss-nested": "^6.0.1", + "postcss-selector-parser": "^6.0.11", + "resolve": "^1.22.2", + "sucrase": "^3.32.0" + }, + "dependencies": { + "glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "requires": { + "is-glob": "^4.0.3" + } + }, + "lilconfig": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.1.0.tgz", + "integrity": "sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==", + "dev": true + } + } + }, "tapable": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", @@ -26009,6 +27008,24 @@ "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==" }, + "thenify": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz", + "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==", + "dev": true, + "requires": { + "any-promise": "^1.0.0" + } + }, + "thenify-all": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz", + "integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==", + "dev": true, + "requires": { + "thenify": ">= 3.1.0 < 4" + } + }, "thunky": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/thunky/-/thunky-1.1.0.tgz", @@ -26062,6 +27079,12 @@ "resolved": "https://registry.npmjs.org/ts-dedent/-/ts-dedent-2.2.0.tgz", "integrity": "sha512-q5W7tVM71e2xjHZTlgfTDoPF/SmqKG5hddq9SzR49CH2hayqRKJtQ4mtRlSxKaJlR/+9rEM+mnBHf7I2/BQcpQ==" }, + "ts-interface-checker": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz", + "integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==", + "dev": true + }, "tslib": { "version": "2.6.3", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.3.tgz", @@ -26755,6 +27778,36 @@ } } }, + "wrap-ansi-cjs": { + "version": "npm:wrap-ansi@7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "requires": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "dependencies": { + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + } + } + } + }, "wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", diff --git a/package.json b/package.json index 5d3df7000..463b998f5 100644 --- a/package.json +++ b/package.json @@ -25,6 +25,10 @@ "@docusaurus/plugin-client-redirects": "3.4.0", "@docusaurus/preset-classic": "3.4.0", "@docusaurus/theme-mermaid": "3.4.0", + "@fortawesome/fontawesome-svg-core": "6.5.2", + "@fortawesome/free-brands-svg-icons": "6.5.2", + "@fortawesome/free-solid-svg-icons": "6.5.2", + "@fortawesome/react-fontawesome": "0.2.2", "@mdx-js/react": "3.0.1", "clsx": "2.1.1", "hast-util-is-element": "3.0.0", @@ -37,7 +41,10 @@ "devDependencies": { "@docusaurus/module-type-aliases": "3.4.0", "@docusaurus/types": "3.4.0", - "dotenv": "16.4.5" + "autoprefixer": "10.4.19", + "dotenv": "16.4.5", + "postcss": "8.4.39", + "tailwindcss": "3.4.4" }, "browserslist": { "production": [ diff --git a/src/components/Community/index.jsx b/src/components/Community/index.jsx new file mode 100644 index 000000000..1c379a5b3 --- /dev/null +++ b/src/components/Community/index.jsx @@ -0,0 +1,19 @@ +import React from "react"; + +import Section from "../Section"; +import homepage from "../../../homepage"; + +const Community = () => { + const { community } = homepage; + + return ( +
+ ); +}; + +export default Community; diff --git a/src/components/Features/index.jsx b/src/components/Features/index.jsx new file mode 100644 index 000000000..7204704c4 --- /dev/null +++ b/src/components/Features/index.jsx @@ -0,0 +1,19 @@ +import React from "react"; + +import Section from "../Section"; +import homepage from "../../../homepage"; + +const Features = () => { + const { features } = homepage; + + return ( +
+ ); +}; + +export default Features; diff --git a/src/components/Hero/index.jsx b/src/components/Hero/index.jsx new file mode 100644 index 000000000..49e37668c --- /dev/null +++ b/src/components/Hero/index.jsx @@ -0,0 +1,26 @@ +import React from "react"; + +import Section from "../Section"; +import homepage from "../../../homepage"; + +const Hero = () => { + const { hero } = homepage; + + return ( + <> +
+
+

+ {hero.title} +

+

+ {hero.subtitle} +

+
+
+
+ + ); +}; + +export default Hero; diff --git a/src/components/Homepage/helpers.js b/src/components/Homepage/helpers.js new file mode 100644 index 000000000..01715be54 --- /dev/null +++ b/src/components/Homepage/helpers.js @@ -0,0 +1,43 @@ +export const debounce = (callback, delay = 100) => { + let timeoutId; + return (...args) => { + clearTimeout(timeoutId); + timeoutId = setTimeout(() => { + timeoutId = null; + callback(...args); + }, delay); + }; +}; + +export const throttle = (callback, limit = 100) => { + let wait = false; + return () => { + if (!wait) { + callback.call(); + wait = true; + setTimeout(() => { + wait = false; + }, limit); + } + }; +}; + +export function handleScroll(ref) { + if (ref.current === null) { + return; + } + + if (window.scrollY > 60) { + const transparency = Math.min(window.scrollY / 250, 0.75); + const blur = Math.min(window.scrollY / 750, 0.375); + + document.documentElement.style.setProperty( + "--navbar-transparency", + transparency + ); + document.documentElement.style.setProperty("--navbar-blur", `${blur}rem`); + } else { + document.documentElement.style.setProperty("--navbar-transparency", 0); + document.documentElement.style.setProperty("--navbar-blur", 0); + } +} diff --git a/src/components/Homepage/homepage.css b/src/components/Homepage/homepage.css new file mode 100644 index 000000000..ae253e24a --- /dev/null +++ b/src/components/Homepage/homepage.css @@ -0,0 +1,101 @@ +html:not(.docs-wrapper):not(.search-page-wrapper) { + --navbar-transparency: 0; + --navbar-blur: 0; +} + +html[data-theme="dark"]:not(.docs-wrapper):not(.search-page-wrapper) { + --ifm-background-color: theme(colors.neutral.925); +} + +html[data-has-hydrated="true"][data-theme="dark"]:not(.docs-wrapper):not( + .search-page-wrapper + ) + .navbar { + background-color: rgba(14, 14, 14, var(--navbar-transparency, 0.75)); +} + +html[data-has-hydrated="true"]:not(.docs-wrapper):not(.search-page-wrapper) + #__docusaurus { + background: image-set( + url("/img/theme/astronaut.webp") 1x, + url("/img/theme/astronaut@2x.webp") 2x + ) + right -20px top 40px no-repeat, + image-set( + url("/img/theme/glow-light.webp") 1x, + url("/img/theme/glow-light@2x.webp") 2x + ) + right -180px top -150px no-repeat, + var(--ifm-background-color); + background-size: 680px, 1200px, auto; + background-blend-mode: normal, difference, normal; +} + +html[data-has-hydrated="true"][data-theme="dark"]:not(.docs-wrapper):not( + .search-page-wrapper + ) + #__docusaurus { + background: image-set( + url("/img/theme/astronaut.webp") 1x, + url("/img/theme/astronaut@2x.webp") 2x + ) + right -20px top 40px no-repeat, + image-set( + url("/img/theme/glow-dark.webp") 1x, + url("/img/theme/glow-dark@2x.webp") 2x + ) + right -180px top -150px no-repeat, + var(--ifm-background-color); + background-size: 680px, 1200px, auto; + background-blend-mode: normal, lighten, normal; +} + +@media only screen and (max-width: 428px) { + html[data-has-hydrated="true"]:not(.docs-wrapper):not(.search-page-wrapper) + #__docusaurus, + html[data-has-hydrated="true"][data-theme="dark"]:not(.docs-wrapper):not( + .search-page-wrapper + ) + #__docusaurus { + background-position: right -20px top 190px, right -100px top 140px; + background-size: 64vw, 160vw, auto; + } +} + +@media only screen and (min-width: 429px) and (max-width: 992px) { + html[data-has-hydrated="true"]:not(.docs-wrapper):not(.search-page-wrapper) + #__docusaurus, + html[data-has-hydrated="true"][data-theme="dark"]:not(.docs-wrapper):not( + .search-page-wrapper + ) + #__docusaurus { + background-position: right -20px top 120px, right -150px top 20px; + background-size: 70vw, 120vw, auto; + } +} + +.section-shadow { + box-shadow: 0 0.625rem 0.563rem 0 rgba(0, 0, 0, 0.06), + 0 0.25rem 0.25rem 0 rgba(0, 0, 0, 0.08); +} + +.section-small-shadow { + box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.1), 0 1px 2px -1px rgba(0, 0, 0, 0.1); +} +.title-shadow { + text-shadow: 0 0 0.5rem var(--ifm-background-color); +} + +.btn-teal:hover, +.btn-teal:active, +.btn-teal:focus { + box-shadow: 0 0 0.5rem 1px rgba(0, 255, 224, 0.6); +} + +[data-theme="dark"] .has-icon-gradient .card-icon path { + fill: url("#icon-gradient") var(--ifm-color-primary); +} + +.community-card .card-icon { + font-size: 3rem; +} diff --git a/src/components/Homepage/index.jsx b/src/components/Homepage/index.jsx new file mode 100644 index 000000000..11a84b977 --- /dev/null +++ b/src/components/Homepage/index.jsx @@ -0,0 +1,64 @@ +import React, { useEffect, useRef } from "react"; +import clsx from "clsx"; + +import Community from "../Community"; +import Features from "../Features"; +import Hero from "../Hero"; +import Promo from "../Promo"; +import Resources from "../Resources"; + +import "./homepage.css"; +import { debounce, handleScroll, throttle } from "./helpers"; + +export default function Homepage() { + const ref = useRef(null); + + useEffect(() => { + if (ref.current !== null) { + if (window.scrollY > 100) { + document.documentElement.style.setProperty("--navbar-transparency", 0.75); + document.documentElement.style.setProperty("--navbar-blur", 0.375); + } + + window.addEventListener( + "scroll", + throttle(debounce(() => handleScroll(ref))) + ); + return () => + window.removeEventListener( + "scroll", + throttle(debounce(() => handleScroll(ref))) + ); + } + }, []); + + return ( +
+ +
+ + + + + +
+
+ ); +} diff --git a/src/components/HomepageFeatures/index.js b/src/components/HomepageFeatures/index.js deleted file mode 100644 index 2982247f8..000000000 --- a/src/components/HomepageFeatures/index.js +++ /dev/null @@ -1,101 +0,0 @@ -import React from "react"; -import clsx from "clsx"; -import Link from "@docusaurus/Link"; -import styles from "./styles.module.css"; - -const FeatureList = [ - { - title: "Discover MultiversX", - content: - "Meet the blockchain that can offer true internet-scale performance.", - docName: "welcome/welcome-to-multiversx", - icon: "💡", - }, - { - title: "Start Building", - content: "Build your decentralized application in minutes.", - docName: "developers/overview", - icon: "🛠️", - }, - { - title: "Sovereign Chains", - content: "Discover and deploy your Sovereign Chain.", - docName: "sovereign/overview", - icon: "⛓️", - }, - { - title: "Run a Validator Node", - content: "Validate transactions, secure the network, and earn rewards.", - docName: "validators/overview", - icon: "🖥", - }, - { - title: "Integrate a Platform", - content: - "Follow our guide to integrate exchanges, wallets, and other platforms.", - docName: "integrators/overview", - icon: "🏛", - }, - { - title: "Manage a Wallet", - content: "Create a wallet to send, receive and store MultiversX tokens.", - docName: "wallet/overview", - icon: "📱", - }, - { - title: "Create a Token", - content: - "Issue your own ESDT token, MultiversX's improved equivalent of ERC-20.", - docName: "tokens/intro", - icon: "🔷", - }, - { - title: "Learn How MultiversX Works", - content: - "Explore Adaptive state sharding, Secure Proof of Stake, and the MultiversX WASM VM.", - docName: "learn/architecture-overview", - icon: "🔬", - }, -]; - -function Feature({ docName, title, content, icon }) { - return ( -
- -

- {icon} - {title} -

-

{content}

- -
- ); -} - -function HomepageHeader() { - return ( -
-
-

Welcome to the MultiversX docs!

-

Choose your path you must.

-
-
- ); -} - -export default function HomepageFeatures() { - return ( -
- -
-
-
- {FeatureList.map((props, idx) => ( - - ))} -
-
-
-
- ); -} diff --git a/src/components/HomepageFeatures/styles.module.css b/src/components/HomepageFeatures/styles.module.css deleted file mode 100644 index 9b89f63cb..000000000 --- a/src/components/HomepageFeatures/styles.module.css +++ /dev/null @@ -1,70 +0,0 @@ -.features { - display: flex; - align-items: center; - padding: 2rem 0; - width: 100%; -} - -.row { - justify-content: center; -} -.icon { - font-size: 1.5rem; -} - -[data-theme="dark"] .card { - box-shadow: 0 8px 24px 4px rgba(28, 29, 29, 0.85); -} -.card { - height: 100%; - color: var(--ifm-font-color-base); - border-radius: 0.65rem; - box-shadow: 0 8px 24px 4px rgba(228, 229, 229, 0.85); - transition-property: all; - transition-duration: 0.2s; - padding: 1.5rem 1.8rem 1.7rem; -} -.card h3 { - font-size: 1.063rem; - color: var(--ifm-color-primary); - font-family: Montserrat, sans-serif; -} -.card p { - margin-bottom: 0; -} -.card:hover { - text-decoration: none; -} -.card:hover p { - color: var(--ifm-color-primary); -} - -.heroBanner { - padding: 3rem 0 1rem; - text-align: center; - position: relative; - overflow: hidden; -} -.heroBanner h1 { - font-weight: 600; - font-size: 2rem; - line-height: 2rem; - margin-bottom: 0.5rem; - font-family: Montserrat, sans-serif; - color: var(--ifm-color-primary); -} -.heroBanner p { - font-weight: 400; - font-family: Montserrat, sans-serif; - color: #727272; - font-size: 1.25rem; - font-weight: 600; - line-height: 1.25; - margin-bottom: 0; -} - -@media screen and (max-width: 996px) { - .heroBanner { - padding: 2rem; - } -} diff --git a/src/components/Promo/index.jsx b/src/components/Promo/index.jsx new file mode 100644 index 000000000..9d158f1c8 --- /dev/null +++ b/src/components/Promo/index.jsx @@ -0,0 +1,69 @@ +import React from "react"; +import Link from "@docusaurus/Link"; +import clsx from "clsx"; +import { faArrowRight } from "@fortawesome/free-solid-svg-icons"; +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; + +import homepage from "../../../homepage"; +import "./promo.css"; + +const Promo = () => { + const { promo } = homepage; + + return ( +
+ +
+
+
+
+
+ {promo.tag} +
+
+
+
+ {promo.title} +
+
+ {promo.subtitle} +
+
+ {promo.link && ( +
+ +
+
+ {promo.button} +
+
+
+ +
+ +
+ )} +
+
+ ); +}; + +export default Promo; diff --git a/src/components/Promo/promo.css b/src/components/Promo/promo.css new file mode 100644 index 000000000..b70ad308b --- /dev/null +++ b/src/components/Promo/promo.css @@ -0,0 +1,20 @@ +.promo { + background: #00272c; +} +.promo video { + mix-blend-mode: lighten; +} +[data-theme="dark"] .promo { + background: url("/videos/sov-animation-loop-header-poster-00001.jpg"); +} +[data-theme="dark"] .promo video { + mix-blend-mode: unset; +} +.promo-shadow { + background-color: rgba(0, 39, 44, 0.85); + box-shadow: 0 0 40px 40px rgba(0, 39, 44, 0.85); +} +[data-theme="dark"] .promo-shadow { + background-color: rgba(0, 0, 0, 0.75); + box-shadow: 0 0 40px 40px rgba(0, 0, 0, 0.75); +} diff --git a/src/components/Resources/index.jsx b/src/components/Resources/index.jsx new file mode 100644 index 000000000..4e734bdd8 --- /dev/null +++ b/src/components/Resources/index.jsx @@ -0,0 +1,18 @@ +import React from "react"; + +import Section from "../Section"; +import homepage from "../../../homepage"; + +const Resources = () => { + const { resources } = homepage; + + return ( +
+ ); +}; + +export default Resources; diff --git a/src/components/Section/external.svg b/src/components/Section/external.svg new file mode 100644 index 000000000..0918c682d --- /dev/null +++ b/src/components/Section/external.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/src/components/Section/index.jsx b/src/components/Section/index.jsx new file mode 100644 index 000000000..2897f1a61 --- /dev/null +++ b/src/components/Section/index.jsx @@ -0,0 +1,159 @@ +import React from "react"; +import Link from "@docusaurus/Link"; +import { faArrowRight } from "@fortawesome/free-solid-svg-icons"; +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +import clsx from "clsx"; + +import ExternalIcon from "./external.svg"; + +const SectionCard = ({ + title = "", + text = "", + link, + icon, + isSmallCard = false, + className, +}) => { + if (isSmallCard) { + return ( + +
+
+
+
+ {title} +
+
+ +
+
+
+
+ {text} +
+
+ + ); + } + + return ( + +
+
+ {icon && ( +
+ +
+ )} +
+
+ {title} +
+
+ +
+
+
+
{text}
+
+ + ); +}; + +const SectionLink = ({ text = "", link, className }) => { + return ( + + {text} + + + ); +}; + +const Section = ({ + title, + subtitle, + className = "", + cards = [], + cardsClassname = "", + hasSmallCards = false, + links = [], + linksClassname = "", +}) => { + return ( +
+
+ {title && ( +

+ {title} +

+ )} + {subtitle && ( +

{subtitle}

+ )} +
+ {cards.length > 0 && ( +
+ {cards.map((card) => ( + + ))} +
+ )} + {links.length > 0 && ( +
    + {links.map((link) => ( +
  • + +
  • + ))} +
+ )} +
+ ); +}; + +export default Section; diff --git a/src/css/custom.css b/src/css/custom.css index d23c25522..14b91b464 100644 --- a/src/css/custom.css +++ b/src/css/custom.css @@ -4,9 +4,47 @@ * work well for content-centric websites. */ +/* -------------------- Start Fonts -------------------- */ + +@font-face { + font-family: "Roobert"; + src: url("https://cdn.multiversx.com/fonts/roobert/regular.woff2") + format("woff2"), + url("https://cdn.multiversx.com/fonts/roobert/regular.woff") format("woff"), + url("https://cdn.multiversx.com/fonts/roobert/regular.otf") + format("opentype"); + font-style: normal; + font-weight: 400; +} + +@font-face { + font-family: "Roobert"; + src: url("https://cdn.multiversx.com/fonts/roobert/medium.woff2") + format("woff2"), + url("https://cdn.multiversx.com/fonts/roobert/medium.woff") format("woff"), + url("https://cdn.multiversx.com/fonts/roobert/medium.otf") + format("opentype"); + font-style: normal; + font-weight: 500; +} + +@font-face { + font-family: "Roobert"; + src: url("https://cdn.multiversx.com/fonts/roobert/semibold.woff2") + format("woff2"), + url("https://cdn.multiversx.com/fonts/roobert/semibold.woff") format("woff"), + url("https://cdn.multiversx.com/fonts/roobert/semibold.otf") + format("opentype"); + font-style: normal; + font-weight: 600; +} + +/* -------------------- End Fonts -------------------- */ + /* You can override the default Infima variables here. */ :root { - --ifm-color-primary: #00947e; + --ifm-background-color: theme(colors.neutral.100); + --ifm-color-primary: #098ea0; --ifm-color-primary-dark: #006553; --ifm-color-primary-darker: #004b3c; --ifm-color-primary-darkest: #00392c; @@ -14,7 +52,8 @@ --ifm-color-primary-lighter: #00c4ac; --ifm-color-primary-lightest: #23f7dd; --ifm-code-font-size: 95%; - --docusaurus-highlighted-code-line-bg: rgba(0, 0, 0, 0.1); + + --ifm-heading-font-family: theme(fontFamily.sans); --ifm-h1-font-size: 2rem; --ifm-h2-font-size: 1.5rem; @@ -24,25 +63,40 @@ --ifm-h6-font-size: 0.75rem; --ifm-heading-font-weight: 600; - --ifm-footer-padding-vertical: 1.25rem; + --ifm-navbar-link-color: theme(colors.neutral.850); + --ifm-navbar-link-hover-color: theme(colors.primary.DEFAULT); + --ifm-navbar-item-padding-horizontal: 0.5rem; + + --docusaurus-highlighted-code-line-bg: rgba(0, 0, 0, 0.1); } /* For readability concerns, you should choose a lighter palette in dark mode. */ -[data-theme="dark"] { - --ifm-color-primary: #23f7dd; - --ifm-color-primary-dark: #21af90; - --ifm-color-primary-darker: #1fa588; - --ifm-color-primary-darkest: #1a8870; - --ifm-color-primary-light: #29d5b0; - --ifm-color-primary-lighter: #32d8b4; - --ifm-color-primary-lightest: #4fddbf; +html[data-theme="dark"] { --docusaurus-highlighted-code-line-bg: rgba(0, 0, 0, 0.3); - --ifm-footer-background-color: #242526; - --docsearch-hit-active-color: #242526 !important; + --ifm-background-color: theme(colors.neutral.900); + --ifm-color-primary: theme(colors.teal.400); + --ifm-color-primary-dark: theme(colors.teal.500); + --ifm-color-primary-darker: theme(colors.teal.600); + --ifm-color-primary-darkest: theme(colors.teal.800); + --ifm-color-primary-light: theme(colors.teal.300); + --ifm-color-primary-lighter: theme(colors.teal.200); + --ifm-color-primary-lightest: theme(colors.teal.100); + + --ifm-footer-background-color: var(--ifm-background-color); + --ifm-navbar-link-color: theme(colors.neutral.400); + --ifm-navbar-link-hover-color: theme(colors.neutral.100); } +/* -------------------- Start Tailwind -------------------- */ + +@tailwind base; +@tailwind components; +@tailwind utilities; + +/* ---------------------- End Tailwind -------------------- */ + /* -------------------- Start Overrides ------------------- */ .plugin-pages #docusaurus_skipToContent_fallback { @@ -99,71 +153,163 @@ h2.anchor code { font-weight: 500; margin-top: 0.25rem; } + +/* -------------------- End Overrides ------------------- */ + +/* -------------------- Start Navbar ------------------- */ + +html.docs-wrapper { + --navbar-transparency: 0.75 !important; + --navbar-blur: 0.375rem !important; +} + +.navbar { + background-color: rgba(245, 245, 245, var(--navbar-transparency, 0.75)); + font-family: theme(fontFamily.sans); + /* border-bottom: 1px solid theme(colors.neutral.200); */ +} +[data-theme="dark"] .navbar { + background-color: rgba(23, 23, 23, var(--navbar-transparency, 0.75)); + /* border-bottom: 1px solid theme(colors.neutral.850); */ +} +.navbar:not(.navbar-sidebar--show) { + backdrop-filter: blur(var(--navbar-blur, 0.375rem)); +} +.navbar__items:not(.navbar__items--right) .navbar__item.navbar__link { + --ifm-navbar-item-padding-horizontal: 1rem; + + font-size: 15px; + letter-spacing: -0.3px; +} + +.table-center-content { + text-align: center; + vertical-align: middle; +} + +.navbar__logo { + align-items: center; + justify-content: center; + display: flex; +} +.navbar__logo img { + height: 1.5rem; +} + .table-of-contents__link .badge, .anchor .navbar__items--right .dropdown.dropdown--right + div { order: 4; margin-right: 0.5rem; } .navbar__items--right .dropdown.dropdown--right { + --ifm-navbar-item-padding-horizontal: 0.5rem; + --ifm-navbar-item-padding-vertical: 0.5rem; order: 5; } -.table-center-content { - text-align: center; - vertical-align: middle; +div[class*="colorModeToggle"] { + order: 4; +} +div[class*="colorModeToggle"] .clean-btn { + order: 4; + --ifm-color-emphasis-200: theme(colors.neutral.300); + padding: 0.375rem; +} +[data-theme="dark"] div[class*="colorModeToggle"] .clean-btn { + --ifm-color-emphasis-200: theme(colors.neutral.700); } -/* -------------------- End Overrides ------------------- */ +.navbar__items--right .dropdown.dropdown--right, +div[class*="colorModeToggle"] .clean-btn { + cursor: pointer; + display: flex; + align-items: center; + gap: 0.625rem; + border-radius: 0.375rem; + backdrop-filter: blur(16px); + background-color: theme(colors.neutral.200); +} + +.navbar__items--right .dropdown.dropdown--right:hover, +div[class*="colorModeToggle"] .clean-btn:hover { + background-color: theme(colors.neutral.300); +} + +[data-theme="dark"] .navbar__items--right .dropdown.dropdown--right, +[data-theme="dark"] div[class*="colorModeToggle"] .clean-btn { + background-color: theme(colors.neutral.850); +} + +[data-theme="dark"] .navbar__items--right .dropdown.dropdown--right:hover, +[data-theme="dark"] div[class*="colorModeToggle"] .clean-btn:hover { + background-color: theme(colors.neutral.700); +} + +@media only screen and (max-width: 998px) { + .navbar__items--right .dropdown.dropdown--right { + display: none; + } +} + +.navbar__items--right { + display: flex; + align-items: center; + gap: 0.5rem; +} -/* -------------------- Start Navbar Icons ------------------- */ +.header-telegram-link, +.header-github-link, +.header-discord-link, +.header-app-change { + --ifm-navbar-item-padding-horizontal: 0.5rem; + --ifm-navbar-item-padding-vertical: 0.5rem; +} .header-telegram-link:hover, .header-github-link:hover, .header-discord-link:hover, -.header-app-change-link:hover { +.header-app-change:hover { opacity: 0.6; } -.header-discord-link::before { +.header-discord-link::before, +.header-github-link::before, +.header-telegram-link::before { content: ""; - width: 24px; - height: 24px; + width: 1.25rem; + height: 1.25rem; display: flex; - background: url("data:image/svg+xml,%3Csvg viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M19.952,5.672c-1.904-1.531-4.916-1.79-5.044-1.801c-0.201-0.017-0.392,0.097-0.474,0.281 c-0.006,0.012-0.072,0.163-0.145,0.398c1.259,0.212,2.806,0.64,4.206,1.509c0.224,0.139,0.293,0.434,0.154,0.659 c-0.09,0.146-0.247,0.226-0.407,0.226c-0.086,0-0.173-0.023-0.252-0.072C15.584,5.38,12.578,5.305,12,5.305S8.415,5.38,6.011,6.872 c-0.225,0.14-0.519,0.07-0.659-0.154c-0.14-0.225-0.07-0.519,0.154-0.659c1.4-0.868,2.946-1.297,4.206-1.509 c-0.074-0.236-0.14-0.386-0.145-0.398C9.484,3.968,9.294,3.852,9.092,3.872c-0.127,0.01-3.139,0.269-5.069,1.822 C3.015,6.625,1,12.073,1,16.783c0,0.083,0.022,0.165,0.063,0.237c1.391,2.443,5.185,3.083,6.05,3.111c0.005,0,0.01,0,0.015,0 c0.153,0,0.297-0.073,0.387-0.197l0.875-1.202c-2.359-0.61-3.564-1.645-3.634-1.706c-0.198-0.175-0.217-0.477-0.042-0.675 c0.175-0.198,0.476-0.217,0.674-0.043c0.029,0.026,2.248,1.909,6.612,1.909c4.372,0,6.591-1.891,6.613-1.91 c0.198-0.172,0.5-0.154,0.674,0.045c0.174,0.198,0.155,0.499-0.042,0.673c-0.07,0.062-1.275,1.096-3.634,1.706l0.875,1.202 c0.09,0.124,0.234,0.197,0.387,0.197c0.005,0,0.01,0,0.015,0c0.865-0.027,4.659-0.667,6.05-3.111 C22.978,16.947,23,16.866,23,16.783C23,12.073,20.985,6.625,19.952,5.672z M8.891,14.87c-0.924,0-1.674-0.857-1.674-1.913 s0.749-1.913,1.674-1.913s1.674,0.857,1.674,1.913S9.816,14.87,8.891,14.87z M15.109,14.87c-0.924,0-1.674-0.857-1.674-1.913 s0.749-1.913,1.674-1.913c0.924,0,1.674,0.857,1.674,1.913S16.033,14.87,15.109,14.87z'/%3E%3C/svg%3E") +} + +.header-discord-link::before { + background: url("data:image/svg+xml,%3Csvg viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath fill='%23262626' d='M19.952,5.672c-1.904-1.531-4.916-1.79-5.044-1.801c-0.201-0.017-0.392,0.097-0.474,0.281 c-0.006,0.012-0.072,0.163-0.145,0.398c1.259,0.212,2.806,0.64,4.206,1.509c0.224,0.139,0.293,0.434,0.154,0.659 c-0.09,0.146-0.247,0.226-0.407,0.226c-0.086,0-0.173-0.023-0.252-0.072C15.584,5.38,12.578,5.305,12,5.305S8.415,5.38,6.011,6.872 c-0.225,0.14-0.519,0.07-0.659-0.154c-0.14-0.225-0.07-0.519,0.154-0.659c1.4-0.868,2.946-1.297,4.206-1.509 c-0.074-0.236-0.14-0.386-0.145-0.398C9.484,3.968,9.294,3.852,9.092,3.872c-0.127,0.01-3.139,0.269-5.069,1.822 C3.015,6.625,1,12.073,1,16.783c0,0.083,0.022,0.165,0.063,0.237c1.391,2.443,5.185,3.083,6.05,3.111c0.005,0,0.01,0,0.015,0 c0.153,0,0.297-0.073,0.387-0.197l0.875-1.202c-2.359-0.61-3.564-1.645-3.634-1.706c-0.198-0.175-0.217-0.477-0.042-0.675 c0.175-0.198,0.476-0.217,0.674-0.043c0.029,0.026,2.248,1.909,6.612,1.909c4.372,0,6.591-1.891,6.613-1.91 c0.198-0.172,0.5-0.154,0.674,0.045c0.174,0.198,0.155,0.499-0.042,0.673c-0.07,0.062-1.275,1.096-3.634,1.706l0.875,1.202 c0.09,0.124,0.234,0.197,0.387,0.197c0.005,0,0.01,0,0.015,0c0.865-0.027,4.659-0.667,6.05-3.111 C22.978,16.947,23,16.866,23,16.783C23,12.073,20.985,6.625,19.952,5.672z M8.891,14.87c-0.924,0-1.674-0.857-1.674-1.913 s0.749-1.913,1.674-1.913s1.674,0.857,1.674,1.913S9.816,14.87,8.891,14.87z M15.109,14.87c-0.924,0-1.674-0.857-1.674-1.913 s0.749-1.913,1.674-1.913c0.924,0,1.674,0.857,1.674,1.913S16.033,14.87,15.109,14.87z'/%3E%3C/svg%3E") no-repeat; + width: 1.5rem; + height: 1.5rem; } [data-theme="dark"] .header-discord-link::before { - background: url("data:image/svg+xml,%3Csvg viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath fill='white' d='M19.952,5.672c-1.904-1.531-4.916-1.79-5.044-1.801c-0.201-0.017-0.392,0.097-0.474,0.281 c-0.006,0.012-0.072,0.163-0.145,0.398c1.259,0.212,2.806,0.64,4.206,1.509c0.224,0.139,0.293,0.434,0.154,0.659 c-0.09,0.146-0.247,0.226-0.407,0.226c-0.086,0-0.173-0.023-0.252-0.072C15.584,5.38,12.578,5.305,12,5.305S8.415,5.38,6.011,6.872 c-0.225,0.14-0.519,0.07-0.659-0.154c-0.14-0.225-0.07-0.519,0.154-0.659c1.4-0.868,2.946-1.297,4.206-1.509 c-0.074-0.236-0.14-0.386-0.145-0.398C9.484,3.968,9.294,3.852,9.092,3.872c-0.127,0.01-3.139,0.269-5.069,1.822 C3.015,6.625,1,12.073,1,16.783c0,0.083,0.022,0.165,0.063,0.237c1.391,2.443,5.185,3.083,6.05,3.111c0.005,0,0.01,0,0.015,0 c0.153,0,0.297-0.073,0.387-0.197l0.875-1.202c-2.359-0.61-3.564-1.645-3.634-1.706c-0.198-0.175-0.217-0.477-0.042-0.675 c0.175-0.198,0.476-0.217,0.674-0.043c0.029,0.026,2.248,1.909,6.612,1.909c4.372,0,6.591-1.891,6.613-1.91 c0.198-0.172,0.5-0.154,0.674,0.045c0.174,0.198,0.155,0.499-0.042,0.673c-0.07,0.062-1.275,1.096-3.634,1.706l0.875,1.202 c0.09,0.124,0.234,0.197,0.387,0.197c0.005,0,0.01,0,0.015,0c0.865-0.027,4.659-0.667,6.05-3.111 C22.978,16.947,23,16.866,23,16.783C23,12.073,20.985,6.625,19.952,5.672z M8.891,14.87c-0.924,0-1.674-0.857-1.674-1.913 s0.749-1.913,1.674-1.913s1.674,0.857,1.674,1.913S9.816,14.87,8.891,14.87z M15.109,14.87c-0.924,0-1.674-0.857-1.674-1.913 s0.749-1.913,1.674-1.913c0.924,0,1.674,0.857,1.674,1.913S16.033,14.87,15.109,14.87z'/%3E%3C/svg%3E") + background: url("data:image/svg+xml,%3Csvg viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath fill='%23F5F5F5' d='M19.952,5.672c-1.904-1.531-4.916-1.79-5.044-1.801c-0.201-0.017-0.392,0.097-0.474,0.281 c-0.006,0.012-0.072,0.163-0.145,0.398c1.259,0.212,2.806,0.64,4.206,1.509c0.224,0.139,0.293,0.434,0.154,0.659 c-0.09,0.146-0.247,0.226-0.407,0.226c-0.086,0-0.173-0.023-0.252-0.072C15.584,5.38,12.578,5.305,12,5.305S8.415,5.38,6.011,6.872 c-0.225,0.14-0.519,0.07-0.659-0.154c-0.14-0.225-0.07-0.519,0.154-0.659c1.4-0.868,2.946-1.297,4.206-1.509 c-0.074-0.236-0.14-0.386-0.145-0.398C9.484,3.968,9.294,3.852,9.092,3.872c-0.127,0.01-3.139,0.269-5.069,1.822 C3.015,6.625,1,12.073,1,16.783c0,0.083,0.022,0.165,0.063,0.237c1.391,2.443,5.185,3.083,6.05,3.111c0.005,0,0.01,0,0.015,0 c0.153,0,0.297-0.073,0.387-0.197l0.875-1.202c-2.359-0.61-3.564-1.645-3.634-1.706c-0.198-0.175-0.217-0.477-0.042-0.675 c0.175-0.198,0.476-0.217,0.674-0.043c0.029,0.026,2.248,1.909,6.612,1.909c4.372,0,6.591-1.891,6.613-1.91 c0.198-0.172,0.5-0.154,0.674,0.045c0.174,0.198,0.155,0.499-0.042,0.673c-0.07,0.062-1.275,1.096-3.634,1.706l0.875,1.202 c0.09,0.124,0.234,0.197,0.387,0.197c0.005,0,0.01,0,0.015,0c0.865-0.027,4.659-0.667,6.05-3.111 C22.978,16.947,23,16.866,23,16.783C23,12.073,20.985,6.625,19.952,5.672z M8.891,14.87c-0.924,0-1.674-0.857-1.674-1.913 s0.749-1.913,1.674-1.913s1.674,0.857,1.674,1.913S9.816,14.87,8.891,14.87z M15.109,14.87c-0.924,0-1.674-0.857-1.674-1.913 s0.749-1.913,1.674-1.913c0.924,0,1.674,0.857,1.674,1.913S16.033,14.87,15.109,14.87z'/%3E%3C/svg%3E") no-repeat; } .header-github-link::before { - content: ""; - width: 24px; - height: 24px; - display: flex; - background: url("data:image/svg+xml,%3Csvg viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12'/%3E%3C/svg%3E") + background: url("data:image/svg+xml,%3Csvg viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath fill='%23262626' d='M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12'/%3E%3C/svg%3E") no-repeat; } [data-theme="dark"] .header-github-link::before { - background: url("data:image/svg+xml,%3Csvg viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath fill='white' d='M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12'/%3E%3C/svg%3E") + background: url("data:image/svg+xml,%3Csvg viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath fill='%23F5F5F5' d='M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12'/%3E%3C/svg%3E") no-repeat; } .header-telegram-link::before { - content: ""; - width: 24px; - height: 24px; - display: flex; - margin-top: 4px; - background: url("data:image/svg+xml;base64,IDxzdmcKICAgICAgICAgICAgY2xhc3NOYW1lPSJhcHAtaWNvbiIKICAgICAgICAgICAgcm9sZT0iaW1nIgogICAgICAgICAgICB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciCiAgICAgICAgICAgIHZpZXdCb3g9IjAgMCAyMiAxOSIKICAgICAgICAgID4KICAgICAgICAgICAgPHBhdGgKICAgICAgICAgICAgICBmaWxsUnVsZT0iZXZlbm9kZCIKICAgICAgICAgICAgICBkPSJNLjQ2MSA4Ljg5NGw0LjkgMS44MjkgMS44OTcgNi4xYy4xMjEuMzkuNi41MzUuOTE3LjI3NWwyLjczLTIuMjI2YS44MTUuODE1IDAgMCAxIC45OTQtLjAyOGw0LjkyNyAzLjU3N2MuMzQuMjQ3LjgyLjA2LjkwNS0uMzVMMjEuMzQuNzEyYS41NzguNTc4IDAgMCAwLS43NzQtLjY1NkwuNDU2IDcuODEzYS41NzguNTc4IDAgMCAwIC4wMDUgMS4wOHptNi40OTIuODU1bDkuNTc3LTUuODk4Yy4xNzItLjEwNi4zNDkuMTI3LjIwMS4yNjRsLTcuOTA0IDcuMzQ3YTEuNjQgMS42NCAwIDAgMC0uNTA4Ljk4bC0uMjY5IDEuOTk1Yy0uMDM1LjI2Ny0uNDEuMjkzLS40ODMuMDM2TDYuNTMgMTAuODM0YS45NjQuOTY0IDAgMCAxIC40MjItMS4wODV6IgogICAgICAgICAgICA+PC9wYXRoPgogICAgICAgICAgPC9zdmc+") + background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 496 512'%3E%3C!--!Font Awesome Free 6.6.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2024 Fonticons, Inc.--%3E%3Cpath fill='%23262626' d='M248 8C111 8 0 119 0 256S111 504 248 504 496 393 496 256 385 8 248 8zM363 176.7c-3.7 39.2-19.9 134.4-28.1 178.3-3.5 18.6-10.3 24.8-16.9 25.4-14.4 1.3-25.3-9.5-39.3-18.7-21.8-14.3-34.2-23.2-55.3-37.2-24.5-16.1-8.6-25 5.3-39.5 3.7-3.8 67.1-61.5 68.3-66.7 .2-.7 .3-3.1-1.2-4.4s-3.6-.8-5.1-.5q-3.3 .7-104.6 69.1-14.8 10.2-26.9 9.9c-8.9-.2-25.9-5-38.6-9.1-15.5-5-27.9-7.7-26.8-16.3q.8-6.7 18.5-13.7 108.4-47.2 144.6-62.3c68.9-28.6 83.2-33.6 92.5-33.8 2.1 0 6.6 .5 9.6 2.9a10.5 10.5 0 0 1 3.5 6.7A43.8 43.8 0 0 1 363 176.7z'/%3E%3C/svg%3E") no-repeat; } [data-theme="dark"] .header-telegram-link::before { - background: url("data:image/svg+xml;base64,IDxzdmcKICBjbGFzc05hbWU9ImFwcC1pY29uIgogIHJvbGU9ImltZyIKICB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciCiAgdmlld0JveD0iMCAwIDIyIDE5Igo+CiAgPHBhdGgKICAgIGZpbGxSdWxlPSJldmVub2RkIgogICAgZD0iTS40NjEgOC44OTRsNC45IDEuODI5IDEuODk3IDYuMWMuMTIxLjM5LjYuNTM1LjkxNy4yNzVsMi43My0yLjIyNmEuODE1LjgxNSAwIDAgMSAuOTk0LS4wMjhsNC45MjcgMy41NzdjLjM0LjI0Ny44Mi4wNi45MDUtLjM1TDIxLjM0LjcxMmEuNTc4LjU3OCAwIDAgMC0uNzc0LS42NTZMLjQ1NiA3LjgxM2EuNTc4LjU3OCAwIDAgMCAuMDA1IDEuMDh6bTYuNDkyLjg1NWw5LjU3Ny01Ljg5OGMuMTcyLS4xMDYuMzQ5LjEyNy4yMDEuMjY0bC03LjkwNCA3LjM0N2ExLjY0IDEuNjQgMCAwIDAtLjUwOC45OGwtLjI2OSAxLjk5NWMtLjAzNS4yNjctLjQxLjI5My0uNDgzLjAzNkw2LjUzIDEwLjgzNGEuOTY0Ljk2NCAwIDAgMSAuNDIyLTEuMDg1eiIgZmlsbD0iI2ZmZiIKICA+PC9wYXRoPgo8L3N2Zz4=") + background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 496 512'%3E%3C!--!Font Awesome Free 6.6.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2024 Fonticons, Inc.--%3E%3Cpath fill='%23F5F5F5' d='M248 8C111 8 0 119 0 256S111 504 248 504 496 393 496 256 385 8 248 8zM363 176.7c-3.7 39.2-19.9 134.4-28.1 178.3-3.5 18.6-10.3 24.8-16.9 25.4-14.4 1.3-25.3-9.5-39.3-18.7-21.8-14.3-34.2-23.2-55.3-37.2-24.5-16.1-8.6-25 5.3-39.5 3.7-3.8 67.1-61.5 68.3-66.7 .2-.7 .3-3.1-1.2-4.4s-3.6-.8-5.1-.5q-3.3 .7-104.6 69.1-14.8 10.2-26.9 9.9c-8.9-.2-25.9-5-38.6-9.1-15.5-5-27.9-7.7-26.8-16.3q.8-6.7 18.5-13.7 108.4-47.2 144.6-62.3c68.9-28.6 83.2-33.6 92.5-33.8 2.1 0 6.6 .5 9.6 2.9a10.5 10.5 0 0 1 3.5 6.7A43.8 43.8 0 0 1 363 176.7z'/%3E%3C/svg%3E") no-repeat; } @@ -172,30 +318,55 @@ h2.anchor code { } .header-app-change::before { content: ""; - width: 20px; - height: 20px; + width: 1rem; + height: 1rem; display: flex; - background: url("data:image/svg+xml;base64,PHN2ZwogIGNsYXNzTmFtZT0iYXBwLWljb24gYXBwLXN3aXRjaGVyLWljb24iCiAgcm9sZT0iaW1nIgogIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIKICB2aWV3Qm94PSIwIDAgNTEyIDUxMiIKICBhcmlhLWxhYmVsPSJNZW51Igo+CiAgPHBhdGggZD0iTTE0OS4zMzMgNTZ2ODBjMCAxMy4yNTUtMTAuNzQ1IDI0LTI0IDI0SDI0Yy0xMy4yNTUgMC0yNC0xMC43NDUtMjQtMjRWNTZjMC0xMy4yNTUgMTAuNzQ1LTI0IDI0LTI0aDEwMS4zMzNjMTMuMjU1IDAgMjQgMTAuNzQ1IDI0IDI0em0xODEuMzM0IDI0MHYtODBjMC0xMy4yNTUtMTAuNzQ1LTI0LTI0LTI0SDIwNS4zMzNjLTEzLjI1NSAwLTI0IDEwLjc0NS0yNCAyNHY4MGMwIDEzLjI1NSAxMC43NDUgMjQgMjQgMjRoMTAxLjMzM2MxMy4yNTYgMCAyNC4wMDEtMTAuNzQ1IDI0LjAwMS0yNHptMzItMjQwdjgwYzAgMTMuMjU1IDEwLjc0NSAyNCAyNCAyNEg0ODhjMTMuMjU1IDAgMjQtMTAuNzQ1IDI0LTI0VjU2YzAtMTMuMjU1LTEwLjc0NS0yNC0yNC0yNEgzODYuNjY3Yy0xMy4yNTUgMC0yNCAxMC43NDUtMjQgMjR6bS0zMiA4MFY1NmMwLTEzLjI1NS0xMC43NDUtMjQtMjQtMjRIMjA1LjMzM2MtMTMuMjU1IDAtMjQgMTAuNzQ1LTI0IDI0djgwYzAgMTMuMjU1IDEwLjc0NSAyNCAyNCAyNGgxMDEuMzMzYzEzLjI1NiAwIDI0LjAwMS0xMC43NDUgMjQuMDAxLTI0em0tMjA1LjMzNCA1NkgyNGMtMTMuMjU1IDAtMjQgMTAuNzQ1LTI0IDI0djgwYzAgMTMuMjU1IDEwLjc0NSAyNCAyNCAyNGgxMDEuMzMzYzEzLjI1NSAwIDI0LTEwLjc0NSAyNC0yNHYtODBjMC0xMy4yNTUtMTAuNzQ1LTI0LTI0LTI0ek0wIDM3NnY4MGMwIDEzLjI1NSAxMC43NDUgMjQgMjQgMjRoMTAxLjMzM2MxMy4yNTUgMCAyNC0xMC43NDUgMjQtMjR2LTgwYzAtMTMuMjU1LTEwLjc0NS0yNC0yNC0yNEgyNGMtMTMuMjU1IDAtMjQgMTAuNzQ1LTI0IDI0em0zODYuNjY3LTU2SDQ4OGMxMy4yNTUgMCAyNC0xMC43NDUgMjQtMjR2LTgwYzAtMTMuMjU1LTEwLjc0NS0yNC0yNC0yNEgzODYuNjY3Yy0xMy4yNTUgMC0yNCAxMC43NDUtMjQgMjR2ODBjMCAxMy4yNTUgMTAuNzQ1IDI0IDI0IDI0em0wIDE2MEg0ODhjMTMuMjU1IDAgMjQtMTAuNzQ1IDI0LTI0di04MGMwLTEzLjI1NS0xMC43NDUtMjQtMjQtMjRIMzg2LjY2N2MtMTMuMjU1IDAtMjQgMTAuNzQ1LTI0IDI0djgwYzAgMTMuMjU1IDEwLjc0NSAyNCAyNCAyNHpNMTgxLjMzMyAzNzZ2ODBjMCAxMy4yNTUgMTAuNzQ1IDI0IDI0IDI0aDEwMS4zMzNjMTMuMjU1IDAgMjQtMTAuNzQ1IDI0LTI0di04MGMwLTEzLjI1NS0xMC43NDUtMjQtMjQtMjRIMjA1LjMzM2MtMTMuMjU1IDAtMjQgMTAuNzQ1LTI0IDI0eiI+PC9wYXRoPgo8L3N2Zz4=") + background: url("data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNCAxNCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZD0iTTYgMS41VjQuNUM2IDUuMzQzNzUgNS4zMTI1IDYgNC41IDZIMS41QzAuNjU2MjUgNiAwIDUuMzQzNzUgMCA0LjVWMS41QzAgMC42ODc1IDAuNjU2MjUgMCAxLjUgMEg0LjVDNS4zMTI1IDAgNiAwLjY4NzUgNiAxLjVaTTYgOS41VjEyLjVDNiAxMy4zNDM4IDUuMzEyNSAxNCA0LjUgMTRIMS41QzAuNjU2MjUgMTQgMCAxMy4zNDM4IDAgMTIuNVY5LjVDMCA4LjY4NzUgMC42NTYyNSA4IDEuNSA4SDQuNUM1LjMxMjUgOCA2IDguNjg3NSA2IDkuNVpNOCAxLjVDOCAwLjY4NzUgOC42NTYyNSAwIDkuNSAwSDEyLjVDMTMuMzEyNSAwIDE0IDAuNjg3NSAxNCAxLjVWNC41QzE0IDUuMzQzNzUgMTMuMzEyNSA2IDEyLjUgNkg5LjVDOC42NTYyNSA2IDggNS4zNDM3NSA4IDQuNVYxLjVaTTE0IDkuNVYxMi41QzE0IDEzLjM0MzggMTMuMzEyNSAxNCAxMi41IDE0SDkuNUM4LjY1NjI1IDE0IDggMTMuMzQzOCA4IDEyLjVWOS41QzggOC42ODc1IDguNjU2MjUgOCA5LjUgOEgxMi41QzEzLjMxMjUgOCAxNCA4LjY4NzUgMTQgOS41WiIgZmlsbD0iIzI2MjYyNiIvPgo8L3N2Zz4K") no-repeat; } [data-theme="dark"] .header-app-change::before { - background: url("data:image/svg+xml;base64,PHN2ZwogIGNsYXNzTmFtZT0iYXBwLWljb24gYXBwLXN3aXRjaGVyLWljb24iCiAgcm9sZT0iaW1nIgogIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIKICB2aWV3Qm94PSIwIDAgNTEyIDUxMiIKICBhcmlhLWxhYmVsPSJNZW51Igo+CiAgPHBhdGggZD0iTTE0OS4zMzMgNTZ2ODBjMCAxMy4yNTUtMTAuNzQ1IDI0LTI0IDI0SDI0Yy0xMy4yNTUgMC0yNC0xMC43NDUtMjQtMjRWNTZjMC0xMy4yNTUgMTAuNzQ1LTI0IDI0LTI0aDEwMS4zMzNjMTMuMjU1IDAgMjQgMTAuNzQ1IDI0IDI0em0xODEuMzM0IDI0MHYtODBjMC0xMy4yNTUtMTAuNzQ1LTI0LTI0LTI0SDIwNS4zMzNjLTEzLjI1NSAwLTI0IDEwLjc0NS0yNCAyNHY4MGMwIDEzLjI1NSAxMC43NDUgMjQgMjQgMjRoMTAxLjMzM2MxMy4yNTYgMCAyNC4wMDEtMTAuNzQ1IDI0LjAwMS0yNHptMzItMjQwdjgwYzAgMTMuMjU1IDEwLjc0NSAyNCAyNCAyNEg0ODhjMTMuMjU1IDAgMjQtMTAuNzQ1IDI0LTI0VjU2YzAtMTMuMjU1LTEwLjc0NS0yNC0yNC0yNEgzODYuNjY3Yy0xMy4yNTUgMC0yNCAxMC43NDUtMjQgMjR6bS0zMiA4MFY1NmMwLTEzLjI1NS0xMC43NDUtMjQtMjQtMjRIMjA1LjMzM2MtMTMuMjU1IDAtMjQgMTAuNzQ1LTI0IDI0djgwYzAgMTMuMjU1IDEwLjc0NSAyNCAyNCAyNGgxMDEuMzMzYzEzLjI1NiAwIDI0LjAwMS0xMC43NDUgMjQuMDAxLTI0em0tMjA1LjMzNCA1NkgyNGMtMTMuMjU1IDAtMjQgMTAuNzQ1LTI0IDI0djgwYzAgMTMuMjU1IDEwLjc0NSAyNCAyNCAyNGgxMDEuMzMzYzEzLjI1NSAwIDI0LTEwLjc0NSAyNC0yNHYtODBjMC0xMy4yNTUtMTAuNzQ1LTI0LTI0LTI0ek0wIDM3NnY4MGMwIDEzLjI1NSAxMC43NDUgMjQgMjQgMjRoMTAxLjMzM2MxMy4yNTUgMCAyNC0xMC43NDUgMjQtMjR2LTgwYzAtMTMuMjU1LTEwLjc0NS0yNC0yNC0yNEgyNGMtMTMuMjU1IDAtMjQgMTAuNzQ1LTI0IDI0em0zODYuNjY3LTU2SDQ4OGMxMy4yNTUgMCAyNC0xMC43NDUgMjQtMjR2LTgwYzAtMTMuMjU1LTEwLjc0NS0yNC0yNC0yNEgzODYuNjY3Yy0xMy4yNTUgMC0yNCAxMC43NDUtMjQgMjR2ODBjMCAxMy4yNTUgMTAuNzQ1IDI0IDI0IDI0em0wIDE2MEg0ODhjMTMuMjU1IDAgMjQtMTAuNzQ1IDI0LTI0di04MGMwLTEzLjI1NS0xMC43NDUtMjQtMjQtMjRIMzg2LjY2N2MtMTMuMjU1IDAtMjQgMTAuNzQ1LTI0IDI0djgwYzAgMTMuMjU1IDEwLjc0NSAyNCAyNCAyNHpNMTgxLjMzMyAzNzZ2ODBjMCAxMy4yNTUgMTAuNzQ1IDI0IDI0IDI0aDEwMS4zMzNjMTMuMjU1IDAgMjQtMTAuNzQ1IDI0LTI0di04MGMwLTEzLjI1NS0xMC43NDUtMjQtMjQtMjRIMjA1LjMzM2MtMTMuMjU1IDAtMjQgMTAuNzQ1LTI0IDI0eiIgZmlsbD0iI2ZmZiI+PC9wYXRoPgo8L3N2Zz4=") - no-repeat; -} -[data-theme="dark"] .header-app-change:hover::before { - background: url("data:image/svg+xml;base64,PHN2ZwogIGNsYXNzTmFtZT0iYXBwLWljb24gYXBwLXN3aXRjaGVyLWljb24iCiAgcm9sZT0iaW1nIgogIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIKICB2aWV3Qm94PSIwIDAgNTEyIDUxMiIKICBhcmlhLWxhYmVsPSJNZW51Igo+CiAgPHBhdGggZD0iTTE0OS4zMzMgNTZ2ODBjMCAxMy4yNTUtMTAuNzQ1IDI0LTI0IDI0SDI0Yy0xMy4yNTUgMC0yNC0xMC43NDUtMjQtMjRWNTZjMC0xMy4yNTUgMTAuNzQ1LTI0IDI0LTI0aDEwMS4zMzNjMTMuMjU1IDAgMjQgMTAuNzQ1IDI0IDI0em0xODEuMzM0IDI0MHYtODBjMC0xMy4yNTUtMTAuNzQ1LTI0LTI0LTI0SDIwNS4zMzNjLTEzLjI1NSAwLTI0IDEwLjc0NS0yNCAyNHY4MGMwIDEzLjI1NSAxMC43NDUgMjQgMjQgMjRoMTAxLjMzM2MxMy4yNTYgMCAyNC4wMDEtMTAuNzQ1IDI0LjAwMS0yNHptMzItMjQwdjgwYzAgMTMuMjU1IDEwLjc0NSAyNCAyNCAyNEg0ODhjMTMuMjU1IDAgMjQtMTAuNzQ1IDI0LTI0VjU2YzAtMTMuMjU1LTEwLjc0NS0yNC0yNC0yNEgzODYuNjY3Yy0xMy4yNTUgMC0yNCAxMC43NDUtMjQgMjR6bS0zMiA4MFY1NmMwLTEzLjI1NS0xMC43NDUtMjQtMjQtMjRIMjA1LjMzM2MtMTMuMjU1IDAtMjQgMTAuNzQ1LTI0IDI0djgwYzAgMTMuMjU1IDEwLjc0NSAyNCAyNCAyNGgxMDEuMzMzYzEzLjI1NiAwIDI0LjAwMS0xMC43NDUgMjQuMDAxLTI0em0tMjA1LjMzNCA1NkgyNGMtMTMuMjU1IDAtMjQgMTAuNzQ1LTI0IDI0djgwYzAgMTMuMjU1IDEwLjc0NSAyNCAyNCAyNGgxMDEuMzMzYzEzLjI1NSAwIDI0LTEwLjc0NSAyNC0yNHYtODBjMC0xMy4yNTUtMTAuNzQ1LTI0LTI0LTI0ek0wIDM3NnY4MGMwIDEzLjI1NSAxMC43NDUgMjQgMjQgMjRoMTAxLjMzM2MxMy4yNTUgMCAyNC0xMC43NDUgMjQtMjR2LTgwYzAtMTMuMjU1LTEwLjc0NS0yNC0yNC0yNEgyNGMtMTMuMjU1IDAtMjQgMTAuNzQ1LTI0IDI0em0zODYuNjY3LTU2SDQ4OGMxMy4yNTUgMCAyNC0xMC43NDUgMjQtMjR2LTgwYzAtMTMuMjU1LTEwLjc0NS0yNC0yNC0yNEgzODYuNjY3Yy0xMy4yNTUgMC0yNCAxMC43NDUtMjQgMjR2ODBjMCAxMy4yNTUgMTAuNzQ1IDI0IDI0IDI0em0wIDE2MEg0ODhjMTMuMjU1IDAgMjQtMTAuNzQ1IDI0LTI0di04MGMwLTEzLjI1NS0xMC43NDUtMjQtMjQtMjRIMzg2LjY2N2MtMTMuMjU1IDAtMjQgMTAuNzQ1LTI0IDI0djgwYzAgMTMuMjU1IDEwLjc0NSAyNCAyNCAyNHpNMTgxLjMzMyAzNzZ2ODBjMCAxMy4yNTUgMTAuNzQ1IDI0IDI0IDI0aDEwMS4zMzNjMTMuMjU1IDAgMjQtMTAuNzQ1IDI0LTI0di04MGMwLTEzLjI1NS0xMC43NDUtMjQtMjQtMjRIMjA1LjMzM2MtMTMuMjU1IDAtMjQgMTAuNzQ1LTI0IDI0eiIgZmlsbD0iIzIzRjdERCI+PC9wYXRoPgo8L3N2Zz4=") + background: url("data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNCAxNCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZD0iTTYgMS41VjQuNUM2IDUuMzQzNzUgNS4zMTI1IDYgNC41IDZIMS41QzAuNjU2MjUgNiAwIDUuMzQzNzUgMCA0LjVWMS41QzAgMC42ODc1IDAuNjU2MjUgMCAxLjUgMEg0LjVDNS4zMTI1IDAgNiAwLjY4NzUgNiAxLjVaTTYgOS41VjEyLjVDNiAxMy4zNDM4IDUuMzEyNSAxNCA0LjUgMTRIMS41QzAuNjU2MjUgMTQgMCAxMy4zNDM4IDAgMTIuNVY5LjVDMCA4LjY4NzUgMC42NTYyNSA4IDEuNSA4SDQuNUM1LjMxMjUgOCA2IDguNjg3NSA2IDkuNVpNOCAxLjVDOCAwLjY4NzUgOC42NTYyNSAwIDkuNSAwSDEyLjVDMTMuMzEyNSAwIDE0IDAuNjg3NSAxNCAxLjVWNC41QzE0IDUuMzQzNzUgMTMuMzEyNSA2IDEyLjUgNkg5LjVDOC42NTYyNSA2IDggNS4zNDM3NSA4IDQuNVYxLjVaTTE0IDkuNVYxMi41QzE0IDEzLjM0MzggMTMuMzEyNSAxNCAxMi41IDE0SDkuNUM4LjY1NjI1IDE0IDggMTMuMzQzOCA4IDEyLjVWOS41QzggOC42ODc1IDguNjU2MjUgOCA5LjUgOEgxMi41QzEzLjMxMjUgOCAxNCA4LjY4NzUgMTQgOS41WiIgZmlsbD0iI0Y1RjVGNSIvPgo8L3N2Zz4K") no-repeat; } -/* -------------------- End Navbar Icons ------------------- */ - -/* -------------------- Start Navbar ------------------- */ -.navbar .navbar__items .navbar__brand + .navbar__item { - margin-left: calc(50% - 245px); -} -.navbar__brand { - margin-left: 1rem; +@media only screen and (min-width: 998px) { + .header-telegram-link, + .header-github-link, + .header-discord-link, + .header-app-change { + font-size: 0; + color: transparent; + } + .header-telegram-link svg, + .header-github-link svg, + .header-discord-link svg, + .header-app-change svg { + display: none; + } + + .header-telegram-link, + .header-github-link, + .header-discord-link, + .header-app-change { + font-size: 0; + color: transparent; + } +} +@media only screen and (max-width: 998px) { + .header-telegram-link, + .header-github-link, + .header-discord-link, + .header-app-change { + padding-left: 40px; + } + .header-discord-link::before, + .header-github-link::before, + .header-telegram-link::before, + .header-app-change::before { + position: absolute; + left: 20px; + } } /* -------------------- End Navbar ------------------- */ @@ -217,6 +388,102 @@ h2.anchor code { } /* -------------------- End Footer ------------------- */ +/* ------------------- Start Docsearch ------------------- */ + +.DocSearch { + --docsearch-primary-color: theme(colors.primary.DEFAULT); + --docsearch-text-color: theme(colors.neutral.800); + --docsearch-spacing: 12px; + --docsearch-icon-stroke-width: 1.4; + --docsearch-highlight-color: var(--docsearch-primary-color); + --docsearch-muted-color: theme(colors.neutral.800); + --docsearch-container-background: rgba(101, 108, 133, 0.8); + --docsearch-logo-color: #5468ff; + --docsearch-modal-width: 560px; + --docsearch-modal-height: 600px; + --docsearch-modal-background: #f5f6f7; + --docsearch-modal-shadow: 0 0.625rem 9px 0 rgba(0, 0, 0, 0.06), + 00.25rem0.25rem 0 rgba(0, 0, 0, 0.08); + --docsearch-searchbox-height: 56px; + --docsearch-searchbox-background: theme(colors.neutral.200); + --docsearch-searchbox-focus-background: #fff; + --docsearch-searchbox-shadow: inset 0 0 0 1px var(--docsearch-primary-color); + --docsearch-hit-height: 56px; + --docsearch-hit-color: #444950; + --docsearch-hit-active-color: #fff; + --docsearch-hit-background: #fff; + --docsearch-hit-shadow: 0 1px 3px 0 #d4d9e1; + --docsearch-key-gradient: rgba(0, 0, 0, 0.55); + --docsearch-key-shadow: none; + --docsearch-key-pressed-shadow: none; + --docsearch-footer-height: 44px; + --docsearch-footer-background: theme(colors.neutral.200); + --docsearch-footer-shadow: none; +} +html[data-theme="dark"] .DocSearch { + --docsearch-hit-active-color: var(--ifm-background-color); + --docsearch-text-color: #fff; + --docsearch-container-background: rgba(9, 10, 17, 0.8); + --docsearch-modal-background: theme(colors.neutral.900); + --docsearch-modal-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.1), + 0 1px 2px -1px rgba(0, 0, 0, 0.1); + --docsearch-searchbox-background: theme(colors.neutral.850); + --docsearch-searchbox-focus-background: theme(colors.neutral.700); + --docsearch-hit-color: #bec3c9; + --docsearch-hit-shadow: none; + --docsearch-hit-background: #090a11; + --docsearch-footer-background: theme(colors.neutral.800); + --docsearch-footer-shadow: none; + --docsearch-logo-color: #fff; + --docsearch-muted-color: #fff; + --docsearch-key-gradient: rgba(255, 255, 255, 0.15); +} + +.navbar .DocSearch-Button { + display: flex; + width: 200px; + padding: 0.375rem 0.375rem 0.375rem 0.5rem; + align-items: center; + gap: 0.625rem; + border-radius: 0.375rem; + height: 2rem; +} +@media only screen and (max-width: 768px) { + .navbar .DocSearch-Button { + width: 32px; + } +} +.navbar .DocSearch-Search-Icon { + width: 1rem; + height: 1rem; + opacity: 0.8; +} +.navbar .DocSearch-Button-Placeholder { + font-family: theme(fontFamily.sans); + font-size: 0.875rem; + font-weight: 500; + line-height: 1rem; + letter-spacing: -0.14px; + opacity: 0.56; +} +.DocSearch-Commands-Key, +.navbar .DocSearch-Button-Key { + --docsearch-muted-color: #fff; + + border-radius: 0.25rem; + top: 0; + border-bottom: 0; + box-shadow: none; + padding-bottom: 0; + font-weight: 600; +} + +/* -------------------- End Docsearch ------------------- */ + +/* ====================================== GLOBAL ================================ */ + +/* ------------------- Start Tabs ------------------- */ + .tabs-container .tabs { font-weight: var(--ifm-font-weight-regular); border-bottom: none; @@ -254,6 +521,48 @@ h2.anchor code { margin: 0 !important; } +/* -------------------- End Tabs ------------------- */ + +/* -------------------- Start Table ------------------- */ + +table { + display: table; + border-radius: 0.5rem; + + border-spacing: 0; + border-collapse: separate; + border: var(--ifm-table-border-width) solid var(--ifm-table-border-color); + overflow: hidden; +} + +table th, +table td { + border: 0; +} + +table th:not(:last-child), +table td:not(:last-child) { + border-right: var(--ifm-table-border-width) solid + var(--ifm-table-border-color); +} + +table > thead > tr:not(:last-child) > th, +table > thead > tr:not(:last-child) > td, +table > tbody > tr:not(:last-child) > th, +table > tbody > tr:not(:last-child) > td, +table > tfoot > tr:not(:last-child) > th, +table > tfoot > tr:not(:last-child) > td, +table > tr:not(:last-child) > td, +table > tr:not(:last-child) > th, +table > thead:not(:last-child), +table > tbody:not(:last-child), +table > tfoot:not(:last-child) { + border-bottom: var(--ifm-table-border-width) solid + var(--ifm-table-border-color); +} + +/* -------------------- End Table ------------------- */ + /* -------------------- Start Markdown ------------------- */ .markdown { --ifm-h1-vertical-rhythm-top: 2; diff --git a/src/pages/index.js b/src/pages/index.js index 8175cb69e..b3b2207fd 100644 --- a/src/pages/index.js +++ b/src/pages/index.js @@ -1,7 +1,6 @@ import React from "react"; -import useDocusaurusContext from "@docusaurus/useDocusaurusContext"; import Layout from "@theme/Layout"; -import HomepageFeatures from "@site/src/components/HomepageFeatures"; +import Homepage from "@site/src/components/Homepage"; export default function Home() { return ( @@ -9,7 +8,7 @@ export default function Home() { title="Docs" description="A highly scalable, fast and secure blockchain platform for distributed apps, enterprise use cases and the new internet economy." > - + ); } diff --git a/src/theme/Footer/index.js b/src/theme/Footer/index.js index 061e622a8..1ef96aa01 100644 --- a/src/theme/Footer/index.js +++ b/src/theme/Footer/index.js @@ -2,14 +2,14 @@ import React from "react"; import { useThemeConfig } from "@docusaurus/theme-common"; import FooterLinks from "@theme/Footer/Links"; import FooterLogo from "@theme/Footer/Logo"; -import FooterCopyright from "@theme/Footer/Copyright"; import FooterLayout from "@theme/Footer/Layout"; + function Footer() { const { footer } = useThemeConfig(); if (!footer) { return null; } - const { copyright, links, logo, style } = footer; + const { links, logo, style } = footer; return ( - + diff --git a/static/img/theme/astronaut.webp b/static/img/theme/astronaut.webp new file mode 100644 index 000000000..4ae9f0bdb Binary files /dev/null and b/static/img/theme/astronaut.webp differ diff --git a/static/img/theme/astronaut@2x.webp b/static/img/theme/astronaut@2x.webp new file mode 100644 index 000000000..cee822429 Binary files /dev/null and b/static/img/theme/astronaut@2x.webp differ diff --git a/static/img/theme/astronaut@3x.webp b/static/img/theme/astronaut@3x.webp new file mode 100644 index 000000000..2cf25c276 Binary files /dev/null and b/static/img/theme/astronaut@3x.webp differ diff --git a/static/img/theme/glow-dark.webp b/static/img/theme/glow-dark.webp new file mode 100644 index 000000000..301e1e7d3 Binary files /dev/null and b/static/img/theme/glow-dark.webp differ diff --git a/static/img/theme/glow-dark@2x.webp b/static/img/theme/glow-dark@2x.webp new file mode 100644 index 000000000..3c69ee76d Binary files /dev/null and b/static/img/theme/glow-dark@2x.webp differ diff --git a/static/img/theme/glow-light.webp b/static/img/theme/glow-light.webp new file mode 100644 index 000000000..62c9e1235 Binary files /dev/null and b/static/img/theme/glow-light.webp differ diff --git a/static/img/theme/glow-light@2x.webp b/static/img/theme/glow-light@2x.webp new file mode 100644 index 000000000..69cb83ea4 Binary files /dev/null and b/static/img/theme/glow-light@2x.webp differ diff --git a/static/videos/sov-animation-loop-header-poster-00001.jpg b/static/videos/sov-animation-loop-header-poster-00001.jpg new file mode 100644 index 000000000..09da3c390 Binary files /dev/null and b/static/videos/sov-animation-loop-header-poster-00001.jpg differ diff --git a/static/videos/sov-animation-loop-header-transcode.mp4 b/static/videos/sov-animation-loop-header-transcode.mp4 new file mode 100644 index 000000000..5b9265b0b Binary files /dev/null and b/static/videos/sov-animation-loop-header-transcode.mp4 differ diff --git a/static/videos/sov-animation-loop-header-transcode.webm b/static/videos/sov-animation-loop-header-transcode.webm new file mode 100644 index 000000000..874185a54 Binary files /dev/null and b/static/videos/sov-animation-loop-header-transcode.webm differ diff --git a/tailwind.config.cjs b/tailwind.config.cjs new file mode 100644 index 000000000..42e6b3b39 --- /dev/null +++ b/tailwind.config.cjs @@ -0,0 +1,33 @@ +const { fontFamily } = require("tailwindcss/defaultTheme"); + +/** @type {import('tailwindcss').Config} */ +module.exports = { + corePlugins: { + preflight: false, + container: false, + }, + + darkMode: ["selector", '[data-theme="dark"]'], + content: ["./src/**/*.{jsx,tsx,html}"], + plugins: [], + theme: { + extend: { + fontFamily: { + sans: ["Roobert", "system-ui", ...fontFamily.sans], + }, + colors: { + neutral: { + 850: "#212121", + 925: "#0E0E0E", + 1000: "#080808", + }, + teal: { + 400: "#23f7dd", + }, + primary: { + DEFAULT: "var(--ifm-color-primary)", + }, + }, + }, + }, +};