From 101cd7ec39d01cdd82e5d56c021c92dde7ca7986 Mon Sep 17 00:00:00 2001 From: Benjamin Kurrek <57506486+BenKurrek@users.noreply.github.com> Date: Wed, 23 Feb 2022 17:14:32 -0700 Subject: [PATCH 001/150] Changed navbar for nft standard to be shorter and more informative (#322) --- specs/Standards/NonFungibleToken/ApprovalManagement.md | 2 +- specs/Standards/NonFungibleToken/Core.md | 2 +- specs/Standards/NonFungibleToken/Enumeration.md | 2 +- specs/Standards/NonFungibleToken/Event.md | 2 +- specs/Standards/NonFungibleToken/Metadata.md | 2 +- specs/Standards/NonFungibleToken/Payout.md | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/specs/Standards/NonFungibleToken/ApprovalManagement.md b/specs/Standards/NonFungibleToken/ApprovalManagement.md index ca59d6a61..ce19661b2 100644 --- a/specs/Standards/NonFungibleToken/ApprovalManagement.md +++ b/specs/Standards/NonFungibleToken/ApprovalManagement.md @@ -1,4 +1,4 @@ -# Non-Fungible Token Approval Management +# Approval Management ## [NEP-178](https://github.com/near/NEPs/discussions/178) diff --git a/specs/Standards/NonFungibleToken/Core.md b/specs/Standards/NonFungibleToken/Core.md index 1e531155a..5e45b7096 100644 --- a/specs/Standards/NonFungibleToken/Core.md +++ b/specs/Standards/NonFungibleToken/Core.md @@ -1,4 +1,4 @@ -# Non-Fungible Token +# Core Functionality ## [NEP-171](https://github.com/near/NEPs/discussions/171) diff --git a/specs/Standards/NonFungibleToken/Enumeration.md b/specs/Standards/NonFungibleToken/Enumeration.md index abae7596d..38093c825 100644 --- a/specs/Standards/NonFungibleToken/Enumeration.md +++ b/specs/Standards/NonFungibleToken/Enumeration.md @@ -1,4 +1,4 @@ -# Non-Fungible Token Enumeration +# Enumeration ## [NEP-181](https://github.com/near/NEPs/discussions/181) diff --git a/specs/Standards/NonFungibleToken/Event.md b/specs/Standards/NonFungibleToken/Event.md index 3ec42965e..b472ada2c 100644 --- a/specs/Standards/NonFungibleToken/Event.md +++ b/specs/Standards/NonFungibleToken/Event.md @@ -1,4 +1,4 @@ -# Non-Fungible Token Event +# Events Version `1.0.0` diff --git a/specs/Standards/NonFungibleToken/Metadata.md b/specs/Standards/NonFungibleToken/Metadata.md index 04d74f5f8..0f2638431 100644 --- a/specs/Standards/NonFungibleToken/Metadata.md +++ b/specs/Standards/NonFungibleToken/Metadata.md @@ -1,4 +1,4 @@ -# Non-Fungible Token Metadata +# Metadata ## [NEP-177](https://github.com/near/NEPs/discussions/177) diff --git a/specs/Standards/NonFungibleToken/Payout.md b/specs/Standards/NonFungibleToken/Payout.md index 78dba86b7..86f31f9e8 100644 --- a/specs/Standards/NonFungibleToken/Payout.md +++ b/specs/Standards/NonFungibleToken/Payout.md @@ -1,4 +1,4 @@ -# Standard for a Multiple-Recipient-Payout mechanic on NFT Contracts +# Royalties and Payouts ## (NEP-199) From 5bdefce6fc21ad4d43ea36291d658ca35a77f03f Mon Sep 17 00:00:00 2001 From: Benjamin Kurrek <57506486+BenKurrek@users.noreply.github.com> Date: Fri, 25 Feb 2022 21:14:03 -0500 Subject: [PATCH 002/150] Consistent NFT Standard Token Struct Field Names (#315) * Renamed id to token_id and approvals to approved_account_ids in the token struct for NFTs * Update ApprovalManagement.md --- .../NonFungibleToken/ApprovalManagement.md | 58 ++++++++++--------- specs/Standards/NonFungibleToken/Core.md | 10 ++-- specs/Standards/NonFungibleToken/Metadata.md | 6 +- 3 files changed, 41 insertions(+), 33 deletions(-) diff --git a/specs/Standards/NonFungibleToken/ApprovalManagement.md b/specs/Standards/NonFungibleToken/ApprovalManagement.md index ce19661b2..cc7bbcaac 100644 --- a/specs/Standards/NonFungibleToken/ApprovalManagement.md +++ b/specs/Standards/NonFungibleToken/ApprovalManagement.md @@ -2,7 +2,7 @@ ## [NEP-178](https://github.com/near/NEPs/discussions/178) -Version `1.0.0` +Version `1.1.0` ## Summary @@ -21,7 +21,7 @@ However, some Non-Fungible Token developers, marketplaces, dApps, or artists may Prior art: - Ethereum's [ERC-721] -- [NEP-4](https://github.com/near/NEPs/pull/4), NEAR's old NFT standard that does not include approvals per token ID +- [NEP-4](https://github.com/near/NEPs/pull/4), NEAR's old NFT standard that does not include approved_account_ids per token ID ## Example Scenarios @@ -75,9 +75,9 @@ Alice approves Bob to transfer her token. The response: { - "id": "1", + "token_id": "1", "owner_id": "alice.near", - "approvals": { + "approved_account_ids": { "bob": 1, } } @@ -234,23 +234,23 @@ Again, note that no previous approvers will get cross-contract calls in this cas ## Reference-level explanation -The `Token` structure returned by `nft_token` must include an `approvals` field, which is a map of account IDs to approval IDs. Using TypeScript's [Record type](https://www.typescriptlang.org/docs/handbook/utility-types.html#recordkeystype) notation: +The `Token` structure returned by `nft_token` must include an `approved_account_ids` field, which is a map of account IDs to approval IDs. Using TypeScript's [Record type](https://www.typescriptlang.org/docs/handbook/utility-types.html#recordkeystype) notation: ```diff - type Token = { - id: string, +type Token = { + token_id: string, owner_id: string, -+ approvals: Record, - }; ++ approved_account_ids: Record, + } ``` Example token data: ```json { - "id": "1", + "token_id": "1", "owner_id": "alice.near", - "approvals": { + "approved_account_ids": { "bob.near": 1, "carol.near": 2, } @@ -271,26 +271,26 @@ Note that while this describes an honest mistake, the possibility of such a bug To avoid this possibility, the NFT contract generates a unique approval ID each time it approves an account. Then when calling `nft_transfer` or `nft_transfer_call`, the approved account passes `approval_id` with this value to make sure the underlying state of the token hasn't changed from what the approved account expects. -Keeping with the example above, say the initial approval of the second marketplace generated the following `approvals` data: +Keeping with the example above, say the initial approval of the second marketplace generated the following `approved_account_ids` data: ```json { - "id": "1", + "token_id": "1", "owner_id": "alice.near", - "approvals": { + "approved_account_ids": { "marketplace_1.near": 1, "marketplace_2.near": 2, } } ``` -But after the transfers and re-approval described above, the token might have `approvals` as: +But after the transfers and re-approval described above, the token might have `approved_account_ids` as: ```json { - "id": "1", + "token_id": "1", "owner_id": "alice.near", - "approvals": { + "approved_account_ids": { "marketplace_2.near": 3, } } @@ -330,7 +330,7 @@ The NFT contract must implement the following methods: // // Arguments: // * `token_id`: the token for which to add an approval -// * `account_id`: the account to add to `approvals` +// * `account_id`: the account to add to `approved_account_ids` // * `msg`: optional string to be passed to `nft_on_approve` // // Returns void, if no `msg` given. Otherwise, returns promise call to @@ -352,7 +352,7 @@ function nft_approve( // // Arguments: // * `token_id`: the token for which to revoke an approval -// * `account_id`: the account to remove from `approvals` +// * `account_id`: the account to remove from `approved_account_ids` function nft_revoke( token_id: string, account_id: string @@ -364,11 +364,11 @@ function nft_revoke( // * Caller of the method must attach a deposit of 1 yoctoⓃ for security // purposes // * If contract requires >1yN deposit on `nft_approve`, contract -// MUST refund all associated storage deposit when owner revokes approvals +// MUST refund all associated storage deposit when owner revokes approved_account_ids // * Contract MUST panic if called by someone other than token owner // // Arguments: -// * `token_id`: the token with approvals to revoke +// * `token_id`: the token with approved_account_ids to revoke function nft_revoke_all(token_id: string) {} /****************/ @@ -380,7 +380,7 @@ function nft_revoke_all(token_id: string) {} // // Arguments: // * `token_id`: the token for which to revoke an approval -// * `approved_account_id`: the account to check the existence of in `approvals` +// * `approved_account_id`: the account to check the existence of in `approved_account_ids` // * `approval_id`: an optional approval ID to check against current approval ID for given account // // Returns: @@ -404,11 +404,11 @@ What does this mean? First, it's useful to understand what we mean by "single-block gas limit". This refers to the [hard cap on gas per block at the protocol layer](https://docs.near.org/docs/concepts/gas#thinking-in-gas). This number will increase over time. -Removing data from a contract uses gas, so if an NFT had a large enough number of approvals, `nft_revoke_all` would fail, because calling it would exceed the maximum gas. +Removing data from a contract uses gas, so if an NFT had a large enough number of approved_account_ids, `nft_revoke_all` would fail, because calling it would exceed the maximum gas. -Contracts must prevent this by capping the number of approvals for a given token. However, it is up to contract authors to determine a sensible cap for their contract (and the single block gas limit at the time they deploy). Since contract implementations can vary, some implementations will be able to support a larger number of approvals than others, even with the same maximum gas per block. +Contracts must prevent this by capping the number of approved_account_ids for a given token. However, it is up to contract authors to determine a sensible cap for their contract (and the single block gas limit at the time they deploy). Since contract implementations can vary, some implementations will be able to support a larger number of approved_account_ids than others, even with the same maximum gas per block. -Contract authors may choose to set a cap of something small and safe like 10 approvals, or they could dynamically calculate whether a new approval would break future calls to `nft_revoke_all`. But every contract MUST ensure that they never break the functionality of `nft_revoke_all`. +Contract authors may choose to set a cap of something small and safe like 10 approved_account_ids, or they could dynamically calculate whether a new approval would break future calls to `nft_revoke_all`. But every contract MUST ensure that they never break the functionality of `nft_revoke_all`. ### Approved Account Contract Interface @@ -439,8 +439,12 @@ function nft_on_approve( Note that the NFT contract will fire-and-forget this call, ignoring any return values or errors generated. This means that even if the approved account does not have a contract or does not implement `nft_on_approve`, the approval will still work correctly from the point of view of the NFT contract. -Further note that there is no parallel `nft_on_revoke` when revoking either a single approval or when revoking all. This is partially because scheduling many `nft_on_revoke` calls when revoking all approvals could incur prohibitive [gas fees](https://docs.near.org/docs/concepts/gas). Apps and contracts which cache NFT approvals can therefore not rely on having up-to-date information, and should periodically refresh their caches. Since this will be the necessary reality for dealing with `nft_revoke_all`, there is no reason to complicate `nft_revoke` with an `nft_on_revoke` call. +Further note that there is no parallel `nft_on_revoke` when revoking either a single approval or when revoking all. This is partially because scheduling many `nft_on_revoke` calls when revoking all approved_account_ids could incur prohibitive [gas fees](https://docs.near.org/docs/concepts/gas). Apps and contracts which cache NFT approved_account_ids can therefore not rely on having up-to-date information, and should periodically refresh their caches. Since this will be the necessary reality for dealing with `nft_revoke_all`, there is no reason to complicate `nft_revoke` with an `nft_on_revoke` call. ### No incurred cost for core NFT behavior -NFT contracts should be implemented in a way to avoid extra gas fees for serialization & deserialization of `approvals` for calls to `nft_*` methods other than `nft_token`. See `near-contract-standards` [implementation of `ft_metadata` using `LazyOption`](https://github.com/near/near-sdk-rs/blob/c2771af7fdfe01a4e8414046752ee16fb0d29d39/examples/fungible-token/ft/src/lib.rs#L71) as a reference example. +NFT contracts should be implemented in a way to avoid extra gas fees for serialization & deserialization of `approved_account_ids` for calls to `nft_*` methods other than `nft_token`. See `near-contract-standards` [implementation of `ft_metadata` using `LazyOption`](https://github.com/near/near-sdk-rs/blob/c2771af7fdfe01a4e8414046752ee16fb0d29d39/examples/fungible-token/ft/src/lib.rs#L71) as a reference example. + +## Errata + +* **2022-02-03**: updated `Token` struct field names. `id` was changed to `token_id` and `approvals` was changed to `approved_account_ids`. This is to be consistent with current implementations of the standard and the rust SDK docs. diff --git a/specs/Standards/NonFungibleToken/Core.md b/specs/Standards/NonFungibleToken/Core.md index 5e45b7096..36aafcbac 100644 --- a/specs/Standards/NonFungibleToken/Core.md +++ b/specs/Standards/NonFungibleToken/Core.md @@ -2,7 +2,7 @@ ## [NEP-171](https://github.com/near/NEPs/discussions/171) -Version `1.0.1` +Version `1.0.2` ## Summary @@ -47,9 +47,9 @@ Prior art: // extensions such as Approval Management, Metadata, or other // attributes may be included in this structure. type Token = { - id: string, - owner_id: string, -} + token_id: string, + owner_id: string, + } /******************/ /* CHANGE METHODS */ @@ -202,6 +202,8 @@ function nft_on_transfer( ## Errata +* **2022-02-03**: updated `Token` struct field names. `id` was changed to `token_id`. This is to be consistent with current implementations of the standard and the rust SDK docs. + * **2021-12-20**: updated `nft_resolve_transfer` argument `approved_account_ids` to be type `null|Record` instead of `null|string[]`. This gives contracts a way to restore the original approved accounts and their approval IDs. More information can be found in [this](https://github.com/near/NEPs/issues/301) discussion. * **2021-07-16**: updated `nft_transfer_call` argument `approval_id` to be type `number|null` instead of `string|null`. As stated, approval IDs are not expected to exceed the JSON limit of 2^53. diff --git a/specs/Standards/NonFungibleToken/Metadata.md b/specs/Standards/NonFungibleToken/Metadata.md index 0f2638431..c0b2aa69e 100644 --- a/specs/Standards/NonFungibleToken/Metadata.md +++ b/specs/Standards/NonFungibleToken/Metadata.md @@ -2,7 +2,7 @@ ## [NEP-177](https://github.com/near/NEPs/discussions/177) -Version `2.0.0` +Version `2.0.1` ## Summary @@ -62,7 +62,7 @@ A new attribute MUST be added to each `Token` struct: ```diff type Token = { - id: string, + token_id: string, owner_id: string, + metadata: TokenMetadata, } @@ -115,6 +115,8 @@ Contracts should be implemented in a way to avoid extra gas fees for serializati ## Errata +* **2022-02-03**: updated `Token` struct field names. `id` was changed to `token_id`. This is to be consistent with current implementations of the standard and the rust SDK docs. + The first version (`1.0.0`) had confusing language regarding the fields: - `issued_at` - `expires_at` From f7bf2df46756a1b1b54704b5585e38fd56314761 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dami=C3=A1n=20Parrino?= Date: Tue, 8 Mar 2022 22:19:04 -0300 Subject: [PATCH 003/150] Fix Fees.md navigation (#331) * Add category Add category * Update ApprovalManagement.md --- specs/RuntimeSpec/Fees/_category_.json | 10 +++++++ .../NonFungibleToken/ApprovalManagement.md | 26 +++++++++++++++++++ 2 files changed, 36 insertions(+) create mode 100644 specs/RuntimeSpec/Fees/_category_.json diff --git a/specs/RuntimeSpec/Fees/_category_.json b/specs/RuntimeSpec/Fees/_category_.json new file mode 100644 index 000000000..d99a69433 --- /dev/null +++ b/specs/RuntimeSpec/Fees/_category_.json @@ -0,0 +1,10 @@ +{ + "position": 6, + "label": "Runtime fees", + "collapsible": true, + "collapsed": true, + "link": { + "type": "generated-index", + "title": "Runtime fees" + } +} diff --git a/specs/Standards/NonFungibleToken/ApprovalManagement.md b/specs/Standards/NonFungibleToken/ApprovalManagement.md index cc7bbcaac..7cf4b5d42 100644 --- a/specs/Standards/NonFungibleToken/ApprovalManagement.md +++ b/specs/Standards/NonFungibleToken/ApprovalManagement.md @@ -59,9 +59,11 @@ Alice approves Bob to transfer her token. 1. Alice calls `nft::nft_approve({ "token_id": "1", "account_id": "bob" })`. She attaches 1 yoctoⓃ, (.000000000000000000000001Ⓝ). Using [NEAR CLI](https://docs.near.org/docs/tools/near-cli) to make this call, the command would be: + ```bash near call nft nft_approve \ '{ "token_id": "1", "account_id": "bob" }' \ --accountId alice --depositYocto 1 + ``` The response: @@ -69,11 +71,14 @@ Alice approves Bob to transfer her token. 2. Alice calls view method `nft_token`: + ```bash near view nft nft_token \ '{ "token_id": "1" }' + ``` The response: + ```bash { "token_id": "1", "owner_id": "alice.near", @@ -81,11 +86,14 @@ Alice approves Bob to transfer her token. "bob": 1, } } + ``` 3. Alice calls view method `nft_is_approved`: + ```bash near view nft nft_is_approved \ '{ "token_id": "1", "approved_account_id": "bob" }' + ``` The response: @@ -105,22 +113,26 @@ Alice approves Market to transfer one of her tokens and passes `msg` so that NFT 1. Using near-cli: + ```bash near call nft nft_approve '{ "token_id": "1", "account_id": "market", "msg": "{\"action\": \"list\", \"price\": \"100\", \"token\": \"nDAI\" }" }' --accountId alice --depositYocto 1 + ``` At this point, near-cli will hang until the cross-contract call chain fully resolves, which would also be true if Alice used a Market frontend using [near-api-js](https://docs.near.org/docs/develop/front-end/near-api-js). Alice's part is done, though. The rest happens behind the scenes. 2. `nft` schedules a call to `nft_on_approve` on `market`. Using near-cli notation for easy cross-reference with the above, this would look like: + ```bash near call market nft_on_approve '{ "token_id": "1", "owner_id": "alice", "approval_id": 2, "msg": "{\"action\": \"list\", \"price\": \"100\", \"token\": \"nDAI\" }" }' --accountId nft + ``` 3. `market` now knows that it can sell Alice's token for 100 [nDAI](https://explorer.mainnet.near.org/accounts/6b175474e89094c44da98b954eedeac495271d0f.factory.bridge.near), and that when it transfers it to a buyer using `nft_transfer`, it can pass along the given `approval_id` to ensure that Alice hasn't changed her mind. It can schedule any further cross-contract calls it wants, and if it returns these promises correctly, Alice's initial near-cli call will resolve with the outcome from the final step in the chain. If Alice actually made this call from a Market frontend, the frontend can use this return value for something useful. @@ -141,27 +153,33 @@ Not to worry, though, she checks `nft_is_approved` and sees that she did success 1. Using near-cli: + ```bash near call nft nft_approve '{ "token_id": "1", "account_id": "bazaar", "msg": "{\"action\": \"list\", \"price\": \"100\", \"token\": \"nDAI\" }" }' --accountId alice --depositYocto 1 + ``` 2. `nft` schedules a call to `nft_on_approve` on `market`. Using near-cli notation for easy cross-reference with the above, this would look like: + ```bash near call bazaar nft_on_approve '{ "token_id": "1", "owner_id": "alice", "approval_id": 3, "msg": "{\"action\": \"list\", \"price\": \"100\", \"token\": \"nDAI\" }" }' --accountId nft + ``` 3. 💥 `bazaar` doesn't implement this method, so the call results in an error. Alice sees this error in the output from near-cli. 4. Alice checks if the approval itself worked, despite the error on the cross-contract call: + ```bash near view nft nft_is_approved \ '{ "token_id": "1", "approved_account_id": "bazaar" }' + ``` The response: @@ -179,11 +197,13 @@ Bob buys Alice's token via Market. Bob probably does this via Market's frontend, Using near-cli notation for consistency: +```bash near call nft nft_transfer '{ "receiver_id": "bob", "token_id": "1", "approval_id": 2, }' --accountId market --depositYocto 1 +``` ### 5. Approval IDs, edge case @@ -197,11 +217,13 @@ Bob signs some transaction which results in the `bazaar` contract calling `nft_t Using near-cli notation for consistency: +```bash near call nft nft_transfer '{ "receiver_id": "bob", "token_id": "1", "approval_id": 3, }' --accountId bazaar --depositYocto 1 +``` ### 6. Revoke one @@ -211,10 +233,12 @@ Alice revokes Market's approval for this token. Using near-cli: +```bash near call nft nft_revoke '{ "account_id": "market", "token_id": "1", }' --accountId alice --depositYocto 1 +``` Note that `market` will not get a cross-contract call in this case. The implementors of the Market app should implement [cron](https://en.wikipedia.org/wiki/Cron)-type functionality to intermittently check that Market still has the access they expect. @@ -226,9 +250,11 @@ Alice revokes all approval for this token. Using near-cli: +```bash near call nft nft_revoke_all '{ "token_id": "1", }' --accountId alice --depositYocto 1 +``` Again, note that no previous approvers will get cross-contract calls in this case. From e040e55fbe015ea0e012c1606ac7fcc843db5aa7 Mon Sep 17 00:00:00 2001 From: Simonas Kazlauskas Date: Mon, 14 Mar 2022 11:26:17 +0000 Subject: [PATCH 004/150] Add a RuntimeSpec for contract preparation (#324) --- specs/RuntimeSpec/FunctionCall.md | 345 ++++++++++++++++-------------- specs/RuntimeSpec/Preparation.md | 273 +++++++++++++++++++++++ 2 files changed, 462 insertions(+), 156 deletions(-) create mode 100644 specs/RuntimeSpec/Preparation.md diff --git a/specs/RuntimeSpec/FunctionCall.md b/specs/RuntimeSpec/FunctionCall.md index 880664b78..7b6bd7968 100644 --- a/specs/RuntimeSpec/FunctionCall.md +++ b/specs/RuntimeSpec/FunctionCall.md @@ -1,5 +1,7 @@ # Function Call -In this section we provide an explanation how the `FunctionCall` action execution works, what are the inputs and what are the outputs. Suppose runtime received the following ActionReceipt: + +In this section we provide an explanation how the `FunctionCall` action execution works, what are +the inputs and what are the outputs. Suppose runtime received the following ActionReceipt: ```rust ActionReceipt { @@ -13,37 +15,56 @@ ActionReceipt { actions: [FunctionCall { gas: 100000, deposit: 100000u128, method_name: "exchange", args: "{arg1, arg2, ...}", ... }], } ``` -### input_data_ids to PromiseResult's -`ActionReceipt.input_data_ids` must be satisfied before execution (see [Receipt Matching](#receipt-matching)). Each of `ActionReceipt.input_data_ids` will be converted to the `PromiseResult::Successful(Vec)` if `data_id.data` is `Some(Vec)` otherwise if `data_id.data` is `None` promise will be `PromiseResult::Failed`. +### `input_data_ids` to `PromiseResult`s + +`ActionReceipt.input_data_ids` must be satisfied before execution (see +[Receipt Matching](#receipt-matching)). Each of `ActionReceipt.input_data_ids` will be converted to +the `PromiseResult::Successful(Vec)` if `data_id.data` is `Some(Vec)` otherwise if +`data_id.data` is `None` promise will be `PromiseResult::Failed`. ## Input + The `FunctionCall` executes in the `receiver_id` account environment. -- a vector of [Promise Results](#promise-results) which can be accessed by a `promise_result` import [PromisesAPI](Components/BindingsSpec/PromisesAPI.md) `promise_result`) -- the original Transaction `signer_id`, `signer_public_key` data from the ActionReceipt (e.g. `method_name`, `args`, `predecessor_id`, `deposit`, `prepaid_gas` (which is `gas` in FunctionCall)) +- a vector of [Promise Results](#promise-results) which can be accessed by a `promise_result` + import [PromisesAPI](Components/BindingsSpec/PromisesAPI.md) `promise_result`) +- the original Transaction `signer_id`, `signer_public_key` data from the ActionReceipt (e.g. + `method_name`, `args`, `predecessor_id`, `deposit`, `prepaid_gas` (which is `gas` in + FunctionCall)) - a general blockchain data (e.g. `block_index`, `block_timestamp`) - read data from the account storage -A full list of the data available for the contract can be found in [Context API](Components/BindingsSpec/ContextAPI.md) and [Trie](Components/BindingsSpec/TrieAPI.md) +A full list of the data available for the contract can be found in [Context +API](Components/BindingsSpec/ContextAPI.md) and [Trie](Components/BindingsSpec/TrieAPI.md) ## Execution -First of all, runtime does prepare the Wasm binary to be executed: -- loads the contract code from the `receiver_id` [account](../DataStructures/Account.md#account) storage -- deserializes and validates the `code` Wasm binary (see `prepare::prepare_contract`) -- injects the gas counting function `gas` which will charge gas on the beginning of the each code block -- instantiates [Bindings Spec](Components/BindingsSpec/BindingsSpec.md) with binary and calls the `FunctionCall.method_name` exported function +In order to implement this action, the runtime will: -During execution, VM does the following: +- load the contract code from the `receiver_id` [account](../DataStructures/Account.md#account)’s + storage; +- parse, validate and instrument the contract code (see [Preparation](./Preparation.md)); +- optionally, convert the contract code to a different executable format; +- instantiate the WASM module, linking runtime-provided functions defined in the + [Bindings Spec](Components/BindingsSpec/BindingsSpec.md) & running the start function; and +- invoke the function that has been exported from the wasm module with the name matching + that specified in the `FunctionCall.method_name` field. -- counts burnt gas on execution -- counts used gas (which is `burnt gas` + gas attached to the new created receipts) -- counts how accounts storage usage increased by the call -- collects logs produced by the contract -- sets the return data -- creates new receipts through [PromisesAPI](Components/BindingsSpec/PromisesAPI.md) +Note that some of these steps may be executed during the +[`DeployContractAction`](./Actions.md#DeployContractAction) instead. This is largely an +optimization of the `FunctionCall` gas fee, and must not result in an observable behavioral +difference of the `FunctionCall` action. + +During the execution of the contract, the runtime will: + +- count burnt gas on execution; +- count used gas (which is `burnt gas` + gas attached to the new created receipts); +- measure the increase in account’s storage usage as a result of this call; +- collect logs produced by the contract; +- set the return data; and +- create new receipts through [PromisesAPI](Components/BindingsSpec/PromisesAPI.md). ## Output @@ -51,177 +72,189 @@ The output of the `FunctionCall`: - storage updates - changes to the account trie storage which will be applied on a successful call - `burnt_gas`, `used_gas` - see [Runtime Fees](Fees/Fees.md) -- `balance` - unspent account balance (account balance could be spent on deposits of newly created `FunctionCall`s or [`TransferAction`s](Actions.md#transferaction) to other contracts) +- `balance` - unspent account balance (account balance could be spent on deposits of newly created + `FunctionCall`s or [`TransferAction`s](Actions.md#transferaction) to other contracts) - `storage_usage` - storage_usage after ActionReceipt application -- `logs` - during contract execution, utf8/16 string log records could be created. Logs are not persistent currently. -- `new_receipts` - new `ActionReceipts` created during the execution. These receipts are going to be sent to the respective `receiver_id`s (see [Receipt Matching explanation](#receipt-matching)) -- result could be either [`ReturnData::Value(Vec)`](#value-result) or [`ReturnData::ReceiptIndex(u64)`](#receiptindex-result)` +- `logs` - during contract execution, utf8/16 string log records could be created. Logs are not + persistent currently. +- `new_receipts` - new `ActionReceipts` created during the execution. These receipts are going to + be sent to the respective `receiver_id`s (see [Receipt Matching explanation](#receipt-matching)) +- result could be either [`ReturnData::Value(Vec)`](#value-result) or + [`ReturnData::ReceiptIndex(u64)`](#receiptindex-result)` ### Value Result -If applied `ActionReceipt` contains [`output_data_receivers`](Receipts.md#output_data_receivers), runtime will create `DataReceipt` for each of `data_id` and `receiver_id` and `data` equals returned value. Eventually, these `DataReceipt` will be delivered to the corresponding receivers. +If applied `ActionReceipt` contains [`output_data_receivers`](Receipts.md#output_data_receivers), +runtime will create `DataReceipt` for each of `data_id` and `receiver_id` and `data` equals +returned value. Eventually, these `DataReceipt` will be delivered to the corresponding receivers. ### ReceiptIndex Result -Successful result could not return any Value, but generates a bunch of new ActionReceipts instead. One example could be a callback. In this case, we assume the the new Receipt will send its Value Result to the [`output_data_receivers`](Receipts.md#output_data_receivers) of the current `ActionReceipt`. +Successful result could not return any Value, but generates a bunch of new ActionReceipts instead. +One example could be a callback. In this case, we assume the the new Receipt will send its Value +Result to the [`output_data_receivers`](Receipts.md#output_data_receivers) of the current +`ActionReceipt`. ### Errors -As with other actions, errors can be divided into two categories: validation error and execution error. +As with other actions, errors can be divided into two categories: validation error and execution +error. #### Validation Error - If there is zero gas attached to the function call, a -```rust -/// The attached amount of gas in a FunctionCall action has to be a positive number. -FunctionCallZeroAttachedGas, -``` -error will be returned + ```rust + /// The attached amount of gas in a FunctionCall action has to be a positive number. + FunctionCallZeroAttachedGas, + ``` + error will be returned -- If the length of the method name to be called exceeds `max_length_method_name`, a genesis parameter whose current value -is `256`, a -```rust -/// The length of the method name exceeded the limit in a Function Call action. -FunctionCallMethodNameLengthExceeded { length: u64, limit: u64 } -``` -error is returned. +- If the length of the method name to be called exceeds `max_length_method_name`, a genesis + parameter whose current value is `256`, a + ```rust + /// The length of the method name exceeded the limit in a Function Call action. + FunctionCallMethodNameLengthExceeded { length: u64, limit: u64 } + ``` + error is returned. -- If the length of the argument to the function call exceeds `max_arguments_length`, a genesis parameter whose current -value is `4194304` (4MB), a -```rust -/// The length of the arguments exceeded the limit in a Function Call action. -FunctionCallArgumentsLengthExceeded { length: u64, limit: u64 } -``` -error is returned. +- If the length of the argument to the function call exceeds `max_arguments_length`, a genesis + parameter whose current value is `4194304` (4MB), a + ```rust + /// The length of the arguments exceeded the limit in a Function Call action. + FunctionCallArgumentsLengthExceeded { length: u64, limit: u64 } + ``` + error is returned. #### Execution Error -There can be three types of errors returned when applying a function call action: +There are three types of errors which may occur when applying a function call action: `FunctionCallError`, `ExternalError`, and `StorageError`. * `FunctionCallError` includes everything from around the execution of the wasm binary, from compiling wasm to native to traps occurred while executing the compiled native binary. More specifically, it includes the following errors: -```rust -pub enum FunctionCallError { - /// Wasm compilation error - CompilationError(CompilationError), - /// Wasm binary env link error - LinkError { - msg: String, - }, - /// Import/export resolve error - MethodResolveError(MethodResolveError), - /// A trap happened during execution of a binary - WasmTrap(WasmTrap), - WasmUnknownError, - HostError(HostError), -} -``` + ```rust + pub enum FunctionCallError { + /// Wasm compilation error + CompilationError(CompilationError), + /// Wasm binary env link error + LinkError { + msg: String, + }, + /// Import/export resolve error + MethodResolveError(MethodResolveError), + /// A trap happened during execution of a binary + WasmTrap(WasmTrap), + WasmUnknownError, + HostError(HostError), + } + ``` - `CompilationError` includes errors that can occur during the compilation of wasm binary. - `LinkError` is returned when wasmer runtime is unable to link the wasm module with provided imports. - `MethodResolveError` occurs when the method in the action cannot be found in the contract code. - `WasmTrap` error happens when a trap occurs during the execution of the binary. Traps here include -```rust -pub enum WasmTrap { - /// An `unreachable` opcode was executed. - Unreachable, - /// Call indirect incorrect signature trap. - IncorrectCallIndirectSignature, - /// Memory out of bounds trap. - MemoryOutOfBounds, - /// Call indirect out of bounds trap. - CallIndirectOOB, - /// An arithmetic exception, e.g. divided by zero. - IllegalArithmetic, - /// Misaligned atomic access trap. - MisalignedAtomicAccess, - /// Breakpoint trap. - BreakpointTrap, - /// Stack overflow. - StackOverflow, - /// Generic trap. - GenericTrap, -} -``` + ```rust + pub enum WasmTrap { + /// An `unreachable` opcode was executed. + Unreachable, + /// Call indirect incorrect signature trap. + IncorrectCallIndirectSignature, + /// Memory out of bounds trap. + MemoryOutOfBounds, + /// Call indirect out of bounds trap. + CallIndirectOOB, + /// An arithmetic exception, e.g. divided by zero. + IllegalArithmetic, + /// Misaligned atomic access trap. + MisalignedAtomicAccess, + /// Breakpoint trap. + BreakpointTrap, + /// Stack overflow. + StackOverflow, + /// Generic trap. + GenericTrap, + } + ``` - `WasmUnknownError` occurs when something inside wasmer goes wrong - `HostError` includes errors that might be returned during the execution of a host function. Those errors are -```rust -pub enum HostError { - /// String encoding is bad UTF-16 sequence - BadUTF16, - /// String encoding is bad UTF-8 sequence - BadUTF8, - /// Exceeded the prepaid gas - GasExceeded, - /// Exceeded the maximum amount of gas allowed to burn per contract - GasLimitExceeded, - /// Exceeded the account balance - BalanceExceeded, - /// Tried to call an empty method name - EmptyMethodName, - /// Smart contract panicked - GuestPanic { panic_msg: String }, - /// IntegerOverflow happened during a contract execution - IntegerOverflow, - /// `promise_idx` does not correspond to existing promises - InvalidPromiseIndex { promise_idx: u64 }, - /// Actions can only be appended to non-joint promise. - CannotAppendActionToJointPromise, - /// Returning joint promise is currently prohibited - CannotReturnJointPromise, - /// Accessed invalid promise result index - InvalidPromiseResultIndex { result_idx: u64 }, - /// Accessed invalid register id - InvalidRegisterId { register_id: u64 }, - /// Iterator `iterator_index` was invalidated after its creation by performing a mutable operation on trie - IteratorWasInvalidated { iterator_index: u64 }, - /// Accessed memory outside the bounds - MemoryAccessViolation, - /// VM Logic returned an invalid receipt index - InvalidReceiptIndex { receipt_index: u64 }, - /// Iterator index `iterator_index` does not exist - InvalidIteratorIndex { iterator_index: u64 }, - /// VM Logic returned an invalid account id - InvalidAccountId, - /// VM Logic returned an invalid method name - InvalidMethodName, - /// VM Logic provided an invalid public key - InvalidPublicKey, - /// `method_name` is not allowed in view calls - ProhibitedInView { method_name: String }, - /// The total number of logs will exceed the limit. - NumberOfLogsExceeded { limit: u64 }, - /// The storage key length exceeded the limit. - KeyLengthExceeded { length: u64, limit: u64 }, - /// The storage value length exceeded the limit. - ValueLengthExceeded { length: u64, limit: u64 }, - /// The total log length exceeded the limit. - TotalLogLengthExceeded { length: u64, limit: u64 }, - /// The maximum number of promises within a FunctionCall exceeded the limit. - NumberPromisesExceeded { number_of_promises: u64, limit: u64 }, - /// The maximum number of input data dependencies exceeded the limit. - NumberInputDataDependenciesExceeded { number_of_input_data_dependencies: u64, limit: u64 }, - /// The returned value length exceeded the limit. - ReturnedValueLengthExceeded { length: u64, limit: u64 }, - /// The contract size for DeployContract action exceeded the limit. - ContractSizeExceeded { size: u64, limit: u64 }, - /// The host function was deprecated. - Deprecated { method_name: String }, -} -``` + + ```rust + pub enum HostError { + /// String encoding is bad UTF-16 sequence + BadUTF16, + /// String encoding is bad UTF-8 sequence + BadUTF8, + /// Exceeded the prepaid gas + GasExceeded, + /// Exceeded the maximum amount of gas allowed to burn per contract + GasLimitExceeded, + /// Exceeded the account balance + BalanceExceeded, + /// Tried to call an empty method name + EmptyMethodName, + /// Smart contract panicked + GuestPanic { panic_msg: String }, + /// IntegerOverflow happened during a contract execution + IntegerOverflow, + /// `promise_idx` does not correspond to existing promises + InvalidPromiseIndex { promise_idx: u64 }, + /// Actions can only be appended to non-joint promise. + CannotAppendActionToJointPromise, + /// Returning joint promise is currently prohibited + CannotReturnJointPromise, + /// Accessed invalid promise result index + InvalidPromiseResultIndex { result_idx: u64 }, + /// Accessed invalid register id + InvalidRegisterId { register_id: u64 }, + /// Iterator `iterator_index` was invalidated after its creation by performing a mutable operation on trie + IteratorWasInvalidated { iterator_index: u64 }, + /// Accessed memory outside the bounds + MemoryAccessViolation, + /// VM Logic returned an invalid receipt index + InvalidReceiptIndex { receipt_index: u64 }, + /// Iterator index `iterator_index` does not exist + InvalidIteratorIndex { iterator_index: u64 }, + /// VM Logic returned an invalid account id + InvalidAccountId, + /// VM Logic returned an invalid method name + InvalidMethodName, + /// VM Logic provided an invalid public key + InvalidPublicKey, + /// `method_name` is not allowed in view calls + ProhibitedInView { method_name: String }, + /// The total number of logs will exceed the limit. + NumberOfLogsExceeded { limit: u64 }, + /// The storage key length exceeded the limit. + KeyLengthExceeded { length: u64, limit: u64 }, + /// The storage value length exceeded the limit. + ValueLengthExceeded { length: u64, limit: u64 }, + /// The total log length exceeded the limit. + TotalLogLengthExceeded { length: u64, limit: u64 }, + /// The maximum number of promises within a FunctionCall exceeded the limit. + NumberPromisesExceeded { number_of_promises: u64, limit: u64 }, + /// The maximum number of input data dependencies exceeded the limit. + NumberInputDataDependenciesExceeded { number_of_input_data_dependencies: u64, limit: u64 }, + /// The returned value length exceeded the limit. + ReturnedValueLengthExceeded { length: u64, limit: u64 }, + /// The contract size for DeployContract action exceeded the limit. + ContractSizeExceeded { size: u64, limit: u64 }, + /// The host function was deprecated. + Deprecated { method_name: String }, + } + ``` * `ExternalError` includes errors that occur during the execution inside `External`, which is an interface between runtime and the rest of the system. The possible errors are: -```rust -pub enum ExternalError { - /// Unexpected error which is typically related to the node storage corruption. - /// It's possible the input state is invalid or malicious. - StorageError(StorageError), - /// Error when accessing validator information. Happens inside epoch manager. - ValidatorError(EpochError), -} -``` + + ```rust + pub enum ExternalError { + /// Unexpected error which is typically related to the node storage corruption. + /// It's possible the input state is invalid or malicious. + StorageError(StorageError), + /// Error when accessing validator information. Happens inside epoch manager. + ValidatorError(EpochError), + } + ``` * `StorageError` occurs when state or storage is corrupted. diff --git a/specs/RuntimeSpec/Preparation.md b/specs/RuntimeSpec/Preparation.md new file mode 100644 index 000000000..4b0b230cb --- /dev/null +++ b/specs/RuntimeSpec/Preparation.md @@ -0,0 +1,273 @@ +# Contract preparation + +This document describes the contract preparation and instrumentation process as well as the +limitations this process imposes on the contract authors. + +In order to provide high performance execution of the [function calls], the near validator utilizes +ahead-of-time preparation of the contract WASM code. Today the contract code is prepared during the +execution of the [`DeployContractAction`]. The results are then saved and later reported to the +user when a [`FunctionCall`] is invoked. + +Note that only some parts of this document are normative. This document delves into implementation +details, which may change in the future as long as the behavior documented by the normative +portions of this book is maintained. The non-normative portions of this document will be called out +as such. + +[function calls]: ./FunctionCall.md +[`DeployContractAction`]: ./Actions.md#DeployContractAction +[`FunctionCallAction`]: ./Actions.md#FunctionCallAction + +## High level overview + +**This section is not normative.** + +Upon initiation of a contract deployment, broadly the following operations will be executed: +validation, instrumentation, conversion to machine code (compilation) and storage of the compiled +artifacts in the account’s storage. + +Functions exported from the contract module may then be invoked through the mechanisms provided +by the protocol. Two common ways to call a function is by submitting a function call action onto +the chain or via a cross-contract call. + +Most of the errors that have occurred as part of validation, instrumentation, compilation, etc. are +saved and reported when a `FunctionCallAction` is submitted. Deployment itself may only report +errors relevant to itself, as described in the specification for [`DeployContractAction`]. + +## Validation + +A number of limits are imposed on the WebAssembly module that is being parsed: + +* The length of the wasm code must not exceed `max_contract_size` genesis configuration parameter; +* The wasm module must be a valid module according to the WebAssembly core 1.0 specification (this + means no extensions such as multi value returns or SIMD; this limitation may be relaxed in the + future). +* The wasm module may contain no more than: + * `1_000_000` distinct signatures; + * `1_000_000` function imports and local function definitions; + * `100_000` imports; + * `100_000` exports; + * `1_000_000` global definitions and imports; + * `100_000` data segments; + * `1` table; + * `1` memory; +* UTF-8 strings comprising the wasm module definition (e.g. export name) may not exceed `100_000` + bytes each; +* Function definitions may not specify more than `50_000` locals; +* Signatures may not specify more than `1_000` parameters; +* Signatures may not specify more than `1_000` results; +* Tables may not specify more than `10_000_000` entries; + +If the contract code is invalid, the first violation in the binary encoding of the WebAssembly +module shall be reported. These additional requirements are imposed after the module is parsed: + +* The wasm module may contain no more function imports and local definitions than specified in the + `max_functions_number_per_contract` genesis configuration parameter; and + +These additional requirements are imposed after the instrumentation, as documented in the later +sections: + +* All imports may only import from the `env` module. + +## Memory normalization + +All near contracts have the same amount of memory made available for execution. The exact amount is +specified specified by the `initial_memory_pages` and `max_memory_pages` genesis configuration +parameters. In order to ensure a level playing field, any module-local memory definitions are +transparently replaced with an import of a standard memory instance from `env.memory`. + +If the original memory instance definition specified limits different from those specified by the +genesis configuration parameters, the limits are reset to the configured parameters. + +## Gas instrumentation + +In order to implement precise and efficient gas accounting, the contract code is analyzed and +instrumented with additional operations before the compilation occurs. One such instrumentation +implements accounting of the gas fees. + +Gas fees are accounted for at a granularity of sequences of instructions forming a metered block +and are consumed before execution of any instruction part of such a sequence. The accounting +mechanism verifies the remaining gas is sufficient, and subtracts the gas fee from the remaining +gas budget before continuing execution. In the case where the remaining gas balance is insufficient +to continue execution, the `GasExceeded` error is raised and execution of the contract is +terminated. + +The gas instrumentation analysis will segment a wasm function into metered blocks. In the end, +every instruction will belong to exactly one metered block. The algorithm uses a stack of metered +blocks and instructions are assigned to the metered block on top of the stack. The following +terminology will be used throughout this section to refer to metered block operations: + +* active metered block – the metered block at the top of the stack; +* pop – the active metered block is removed from the top of the stack; +* push – a new metered block is added to the stack, becoming the new active metered block. + +A metered block is pushed onto the stack upon a function entry and after every `if` and `loop` +instruction. After the `br`, `br_if`, `br_table`, `else` & `return` (pseudo-)instructions the +active metered block is popped and a new metered block is pushed onto the stack. + +The `end` pseudo-instruction associated with the `if` & `loop` instructions, or when it terminates +the function body, will cause the top-most metered block to be popped off the stack. As a +consequence, the instructions within a metered block need not be consecutive in the original +function. If the `if..end`, `loop..end` or `block..end` control block terminated by this `end` +pseudo-instruction contained any branching instructions targeting control blocks other than the +control block terminated by this `end` pseudo instruction, the currently active metered block is +popped and a new metered block is pushed. + +Note that some of the instructions considered to affect the control flow in the WebAssembly +specification such as `call`, `call_indirect` or `unreachable` do not affect metered block +construction and are accounted for much like other instructions not mentioned in this section. This +also means that calling the `used_gas` host function at different points of the same metered block +would return the same value if the `base` cost was `0`. + +All the instructions covered by a metered block are assigned a fee based on the `regular_op_cost` +genesis parameter. Pseudo-instructions do not cause any fee to be charged. A sum of these fees is +then charged by instrumentation inserted at the beginning of each metered block. + +### Examples + +**This section is not normative.** + +In this section some examples of the instrumentation are presented as an understanding aid to the +specification above. The examples are annotated with comments describing how much gas is charged at +a specific point of the program. The programs presented here are not intended to be executable or +to produce meaningful behavior. + +#### `block` instruction does not terminate a metered block + +```wat +(func + (; charge_gas(6 regular_op_cost) ;) + nop + block + nop + unreachable + nop + end + nop) +``` + +This function has just 1 metered block, covering both the `block..end` block as well as the 2 `nop` +instructions outside of it. As a result the gas fee for all 6 instructions will be charged at the +beginning of the function (even if we can see `unreachable` would be executed after 4 instructions, +terminating the execution). + +#### Branching instructions pop a metered block + +Introducing a conditional branch to the example from the previous section would split the metered +block and the gas accounting would be introduced in two locations: + +```wat +(func + (; charge_gas([nop block br.0 nop]) ;) + nop + block + br 0 + (; charge_gas([nop nop]) ;) + nop + nop + end + nop) +``` + +Note that the first metered block is disjoint and covers the `[nop, block, br 0]` instruction +sequence as well as the final `nop`. The analysis is able to deduce that the `br 0` will not be +able to jump past the final `nop` instruction, and therefore is able to account for the gas fees +incurred by this instruction earlier. + +Replacing `br 0` with a `return` would enable jumping past this final `nop` instruction, splitting +the code into three distinct metered blocks instead: + +```wat +(func + (; charge_gas([nop block return]) ;) + nop + block + return + (; charge_gas([nop nop]) ;) + nop + nop + end + (; charge_gas([nop]) ;) + nop) +``` + +#### `if` and `loop` push a new metered block + +```wat +(func + (; charge_gas([loop unreachable]) ;) + loop + (; charge_gas([br 0]) ;) + br 0 + end + unreachable +) +``` + +In this example the `loop` instruction will always introduce a new nested metered block for its +body, for the `end` pseudo-instruction as well as `br 0` cause a backward jump back to the +beginning of the loop body. A similar reasoning works for `if .. else .. end` sequence since the +body is only executed conditionally: + +```wat +(func + (; charge_gas([i32.const.42 if nop]) ;) + i32.const 42 + if + (; charge_gas([nop nop]) ;) + nop + nop + else + (; charge_gas([unreachable]) ;) + unreachable + end + nop) +``` + +## Operand stack depth instrumentation + +The `max_stack_height` genesis parameter imposes a limit on the number of entries the wasm +operand stack may contain during the contract execution. + +The maximum operand stack height required for a function to execute successfully is computed +statically by simulating the operand stack operations executed by each instruction. For example, +`i32.const 1` pushes 1 entry on the operand stack, whereas `i32.add` pops two entries and pushes 1 +entry containing the result value. The maximum operand stack height of the `if..else..end` control +block is the larger of the heights for two bodies of the conditional. Stack operations for each +instruction are otherwise specified in the section 4 of the WebAssembly core 1.0 specification. + +Before the `call` or `call_indirect` instructions are executed, the callee's required stack is +added to the current stack height counter and is compared with the `max_stack_height` parameter. A +trap is raised if the counter exceeds the limit. The instruction is executed, otherwise. + +Note that the stack depth instrumentation runs after the gas instrumentation. At each point where +gas is charged one entry worth of operand stack space is considered to be used. + +### Examples + +**This section is not normative.** + +Picking the example from the gas instrumentation section, we can tell that this function will use +just 1 operand slot. Lets annotate the operand stack operations at each of the instructions: + +```wat +(func + (; charge_gas(...) ;) (; [] => [gas] => [] ;) + i32.const 42 (; [] => [i32] ;) + if (; [i32] => [] ;) + (; charge_gas(...) ;) (; [] => [gas] => [] ;) + nop (; [] ;) + nop (; [] ;) + else + (; charge_gas(...) ;) (; [] => [gas] => [] ;) + unreachable (; [] ;) + end + nop (; [] ;) +) +``` + +We can see that at no point in time the operand stack contained more than 1 entry. As a result, +the runtime will check that 1 entry is available in the operand stack before the function is +invoked. + + From 956deff113cee553b56dc21aee9fb932d2243b33 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dami=C3=A1n=20Parrino?= Date: Tue, 15 Mar 2022 13:53:08 -0300 Subject: [PATCH 005/150] Add Lunr local search (#336) add a local search bar (while we try to get Algolia) --- website/docusaurus.config.js | 1 + website/package.json | 1 + website/src/theme/SearchBar/algolia.css | 533 ++++++++++++++++++ website/src/theme/SearchBar/index.js | 118 ++++ website/src/theme/SearchBar/lib/DocSearch.js | 306 ++++++++++ .../src/theme/SearchBar/lib/lunar-search.js | 146 +++++ website/src/theme/SearchBar/lib/templates.js | 114 ++++ website/src/theme/SearchBar/lib/utils.js | 270 +++++++++ website/src/theme/SearchBar/styles.css | 40 ++ website/yarn.lock | 190 ++++++- 10 files changed, 1715 insertions(+), 4 deletions(-) create mode 100644 website/src/theme/SearchBar/algolia.css create mode 100644 website/src/theme/SearchBar/index.js create mode 100644 website/src/theme/SearchBar/lib/DocSearch.js create mode 100644 website/src/theme/SearchBar/lib/lunar-search.js create mode 100644 website/src/theme/SearchBar/lib/templates.js create mode 100644 website/src/theme/SearchBar/lib/utils.js create mode 100644 website/src/theme/SearchBar/styles.css diff --git a/website/docusaurus.config.js b/website/docusaurus.config.js index c402b3220..e71b38970 100644 --- a/website/docusaurus.config.js +++ b/website/docusaurus.config.js @@ -21,6 +21,7 @@ const config = { scripts: [ "/js/hotjar.js", ], + plugins: [require.resolve('docusaurus-lunr-search')], stylesheets: [ { href: 'https://cdn.jsdelivr.net/npm/katex@0.13.24/dist/katex.min.css', diff --git a/website/package.json b/website/package.json index 178bfef21..3f8d68fd6 100644 --- a/website/package.json +++ b/website/package.json @@ -19,6 +19,7 @@ "@docusaurus/preset-classic": "^2.0.0-beta.15", "@mdx-js/react": "^1.6.21", "clsx": "^1.1.1", + "docusaurus-lunr-search": "^2.1.15", "hast-util-is-element": "1.1.0", "prism-react-renderer": "^1.2.1", "react": "^17.0.1", diff --git a/website/src/theme/SearchBar/algolia.css b/website/src/theme/SearchBar/algolia.css new file mode 100644 index 000000000..8f3038edc --- /dev/null +++ b/website/src/theme/SearchBar/algolia.css @@ -0,0 +1,533 @@ +/** + * Copyright (c) 2017-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +/* Bottom border of each suggestion */ +.algolia-docsearch-suggestion { + border-bottom-color: #3a3dd1; +} +/* Main category headers */ +.algolia-docsearch-suggestion--category-header { + background-color: #4b54de; +} +/* Highlighted search terms */ +.algolia-docsearch-suggestion--highlight { + color: #3a33d1; +} +/* Highligted search terms in the main category headers */ +.algolia-docsearch-suggestion--category-header + .algolia-docsearch-suggestion--highlight { + background-color: #4d47d5; +} +/* Currently selected suggestion */ +.aa-cursor .algolia-docsearch-suggestion--content { + color: #272296; +} +.aa-cursor .algolia-docsearch-suggestion { + background: #ebebfb; +} + +/* For bigger screens, when displaying results in two columns */ +@media (min-width: 768px) { + /* Bottom border of each suggestion */ + .algolia-docsearch-suggestion { + border-bottom-color: #7671df; + } + /* Left column, with secondary category header */ + .algolia-docsearch-suggestion--subcategory-column { + border-right-color: #7671df; + color: #4e4726; + } +} + +.searchbox { + display: inline-block; + position: relative; + width: 200px; + height: 32px !important; + white-space: nowrap; + box-sizing: border-box; + visibility: visible !important; +} + +.searchbox .algolia-autocomplete { + display: block; + width: 100%; + height: 100%; +} + +.searchbox__wrapper { + width: 100%; + height: 100%; + z-index: 999; + position: relative; +} + +.searchbox__input { + display: inline-block; + box-sizing: border-box; + -webkit-transition: box-shadow 0.4s ease, background 0.4s ease; + transition: box-shadow 0.4s ease, background 0.4s ease; + border: 0; + border-radius: 16px; + box-shadow: inset 0 0 0 1px #cccccc; + background: #ffffff !important; + padding: 0; + padding-right: 26px; + padding-left: 32px; + width: 100%; + height: 100%; + vertical-align: middle; + white-space: normal; + font-size: 12px; + -webkit-appearance: none; + -moz-appearance: none; + appearance: none; +} + +.searchbox__input::-webkit-search-decoration, +.searchbox__input::-webkit-search-cancel-button, +.searchbox__input::-webkit-search-results-button, +.searchbox__input::-webkit-search-results-decoration { + display: none; +} + +.searchbox__input:hover { + box-shadow: inset 0 0 0 1px #b3b3b3; +} + +.searchbox__input:focus, +.searchbox__input:active { + outline: 0; + box-shadow: inset 0 0 0 1px #aaaaaa; + background: #ffffff; +} + +.searchbox__input::-webkit-input-placeholder { + color: #aaaaaa; +} + +.searchbox__input::-moz-placeholder { + color: #aaaaaa; +} + +.searchbox__input:-ms-input-placeholder { + color: #aaaaaa; +} + +.searchbox__input::placeholder { + color: #aaaaaa; +} + +.searchbox__submit { + position: absolute; + top: 0; + margin: 0; + border: 0; + border-radius: 16px 0 0 16px; + background-color: rgba(69, 142, 225, 0); + padding: 0; + width: 32px; + height: 100%; + vertical-align: middle; + text-align: center; + font-size: inherit; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + right: inherit; + left: 0; +} + +.searchbox__submit::before { + display: inline-block; + margin-right: -4px; + height: 100%; + vertical-align: middle; + content: ''; +} + +.searchbox__submit:hover, +.searchbox__submit:active { + cursor: pointer; +} + +.searchbox__submit:focus { + outline: 0; +} + +.searchbox__submit svg { + width: 14px; + height: 14px; + vertical-align: middle; + fill: #6d7e96; +} + +.searchbox__reset { + display: block; + position: absolute; + top: 8px; + right: 8px; + margin: 0; + border: 0; + background: none; + cursor: pointer; + padding: 0; + font-size: inherit; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + fill: rgba(0, 0, 0, 0.5); +} + +.searchbox__reset.hide { + display: none; +} + +.searchbox__reset:focus { + outline: 0; +} + +.searchbox__reset svg { + display: block; + margin: 4px; + width: 8px; + height: 8px; +} + +.searchbox__input:valid ~ .searchbox__reset { + display: block; + -webkit-animation-name: sbx-reset-in; + animation-name: sbx-reset-in; + -webkit-animation-duration: 0.15s; + animation-duration: 0.15s; +} + +@-webkit-keyframes sbx-reset-in { + 0% { + -webkit-transform: translate3d(-20%, 0, 0); + transform: translate3d(-20%, 0, 0); + opacity: 0; + } + 100% { + -webkit-transform: none; + transform: none; + opacity: 1; + } +} + +@keyframes sbx-reset-in { + 0% { + -webkit-transform: translate3d(-20%, 0, 0); + transform: translate3d(-20%, 0, 0); + opacity: 0; + } + 100% { + -webkit-transform: none; + transform: none; + opacity: 1; + } +} + +.algolia-autocomplete .ds-dropdown-menu:before { + display: block; + position: absolute; + content: ''; + width: 14px; + height: 14px; + background: #373940; + z-index: 1000; + top: -7px; + border-top: 1px solid #373940; + border-right: 1px solid #373940; + -webkit-transform: rotate(-45deg); + transform: rotate(-45deg); + border-radius: 2px; +} + +.algolia-autocomplete .ds-dropdown-menu { + box-shadow: 0 1px 0 0 rgba(0, 0, 0, 0.2), 0 2px 3px 0 rgba(0, 0, 0, 0.1); +} + +@media (min-width: 601px) { + .algolia-autocomplete.algolia-autocomplete-right .ds-dropdown-menu { + right: 0 !important; + left: inherit !important; + } + + .algolia-autocomplete.algolia-autocomplete-right .ds-dropdown-menu:before { + right: 48px; + } + + .algolia-autocomplete .ds-dropdown-menu { + position: relative; + top: -6px; + border-radius: 4px; + margin: 6px 0 0; + padding: 0; + text-align: left; + height: auto; + position: relative; + background: transparent; + border: none; + z-index: 999; + max-width: 600px; + min-width: 500px; + } +} + +@media (max-width: 600px) { + .algolia-autocomplete .ds-dropdown-menu { + z-index: 100; + position: fixed !important; + top: 50px !important; + left: auto !important; + right: 1rem !important; + width: 600px; + max-width: calc(100% - 2rem); + max-height: calc(100% - 5rem); + display: block; + } + + .algolia-autocomplete .ds-dropdown-menu:before { + right: 6rem; + } +} + +.algolia-autocomplete .ds-dropdown-menu .ds-suggestions { + position: relative; + z-index: 1000; +} + +.algolia-autocomplete .ds-dropdown-menu .ds-suggestion { + cursor: pointer; +} + +.algolia-autocomplete .ds-dropdown-menu [class^='ds-dataset-'] { + position: relative; + border-radius: 4px; + overflow: auto; + padding: 0; + background: #ffffff; +} + +.algolia-autocomplete .ds-dropdown-menu * { + box-sizing: border-box; +} + +.algolia-autocomplete .algolia-docsearch-suggestion { + display: block; + position: relative; + padding: 0; + overflow: hidden; + text-decoration: none; +} + +.algolia-autocomplete .ds-cursor .algolia-docsearch-suggestion--wrapper { + background: #f1f1f1; + box-shadow: inset -2px 0 0 #61dafb; +} + +.algolia-autocomplete .algolia-docsearch-suggestion--highlight { + background: #ffe564; + padding: 0.1em 0.05em; +} + +.algolia-autocomplete + .algolia-docsearch-suggestion--category-header + .algolia-docsearch-suggestion--category-header-lvl0 + .algolia-docsearch-suggestion--highlight, +.algolia-autocomplete + .algolia-docsearch-suggestion--category-header + .algolia-docsearch-suggestion--category-header-lvl1 + .algolia-docsearch-suggestion--highlight { + color: inherit; + background: inherit; +} + +.algolia-autocomplete + .algolia-docsearch-suggestion--text + .algolia-docsearch-suggestion--highlight { + padding: 0 0 1px; + background: inherit; + box-shadow: inset 0 -2px 0 0 rgba(69, 142, 225, 0.8); + color: inherit; +} + +.algolia-autocomplete .algolia-docsearch-suggestion--content { + display: block; + float: right; + width: 70%; + position: relative; + padding: 5.33333px 0 5.33333px 10.66667px; + cursor: pointer; +} + +.algolia-autocomplete .algolia-docsearch-suggestion--content:before { + content: ''; + position: absolute; + display: block; + top: 0; + height: 100%; + width: 1px; + background: #ececec; + left: -1px; +} + +.algolia-autocomplete .algolia-docsearch-suggestion--category-header { + position: relative; + display: none; + font-size: 14px; + letter-spacing: 0.08em; + font-weight: 700; + background-color: #373940; + text-transform: uppercase; + color: #fff; + margin: 0; + padding: 5px 8px; +} + +.algolia-autocomplete .algolia-docsearch-suggestion--wrapper { + background-color: #fff; + width: 100%; + float: left; + padding: 8px 0 0 0; +} + +.algolia-autocomplete .algolia-docsearch-suggestion--subcategory-column { + float: left; + width: 30%; + display: none; + padding-left: 0; + text-align: right; + position: relative; + padding: 5.33333px 10.66667px; + color: #777; + font-size: 0.9em; + word-wrap: break-word; +} + +.algolia-autocomplete .algolia-docsearch-suggestion--subcategory-column:before { + content: ''; + position: absolute; + display: block; + top: 0; + height: 100%; + width: 1px; + background: #ececec; + right: 0; +} + +.algolia-autocomplete + .algolia-docsearch-suggestion.algolia-docsearch-suggestion__main + .algolia-docsearch-suggestion--category-header, +.algolia-autocomplete + .algolia-docsearch-suggestion.algolia-docsearch-suggestion__secondary { + display: block; +} + +.algolia-autocomplete + .algolia-docsearch-suggestion--subcategory-column + .algolia-docsearch-suggestion--highlight { + background-color: inherit; + color: inherit; +} + +.algolia-autocomplete .algolia-docsearch-suggestion--subcategory-inline { + display: none; +} + +.algolia-autocomplete .algolia-docsearch-suggestion--title { + margin-bottom: 4px; + color: #02060c; + font-size: 0.9em; + font-weight: bold; +} + +.algolia-autocomplete .algolia-docsearch-suggestion--text { + display: block; + line-height: 1.2em; + font-size: 0.85em; + color: #63676d; + padding-right: 2px; +} + +.algolia-autocomplete .algolia-docsearch-suggestion--no-results { + width: 100%; + padding: 8px 0; + text-align: center; + font-size: 1.2em; + background-color: #373940; + margin-top: -8px; +} + +.algolia-autocomplete + .algolia-docsearch-suggestion--no-results + .algolia-docsearch-suggestion--text { + color: #ffffff; + margin-top: 4px; +} + +.algolia-autocomplete .algolia-docsearch-suggestion--no-results::before { + display: none; +} + +.algolia-autocomplete .algolia-docsearch-suggestion code { + padding: 1px 5px; + font-size: 90%; + border: none; + color: #222222; + background-color: #ebebeb; + border-radius: 3px; + font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', + monospace; +} + +.algolia-autocomplete + .algolia-docsearch-suggestion + code + .algolia-docsearch-suggestion--highlight { + background: none; +} + +.algolia-autocomplete + .algolia-docsearch-suggestion.algolia-docsearch-suggestion__main + .algolia-docsearch-suggestion--category-header { + color: white; + display: block; +} + +.algolia-autocomplete + .algolia-docsearch-suggestion.algolia-docsearch-suggestion__secondary + .algolia-docsearch-suggestion--subcategory-column { + display: block; +} + +.algolia-autocomplete .algolia-docsearch-footer { + background-color: #fff; + width: 100%; + height: 30px; + z-index: 2000; + float: right; + font-size: 0; + line-height: 0; +} + +.algolia-autocomplete .algolia-docsearch-footer--logo { + background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 130 18'%3E%3Cdefs%3E%3ClinearGradient id='a' x1='-36.87%25' x2='129.43%25' y1='134.94%25' y2='-27.7%25'%3E%3Cstop stop-color='%252300AEFF' offset='0%25'/%3E%3Cstop stop-color='%25233369E7' offset='100%25'/%3E%3C/linearGradient%3E%3C/defs%3E%3Cg fill='none' fill-rule='evenodd'%3E%3Cpath fill='url(%2523a)' d='M59.4.02h13.3a2.37 2.37 0 0 1 2.38 2.37V15.6a2.37 2.37 0 0 1-2.38 2.36H59.4a2.37 2.37 0 0 1-2.38-2.36V2.38A2.37 2.37 0 0 1 59.4.02z'/%3E%3Cpath fill='%2523FFF' d='M66.26 4.56c-2.82 0-5.1 2.27-5.1 5.08 0 2.8 2.28 5.07 5.1 5.07 2.8 0 5.1-2.26 5.1-5.07 0-2.8-2.28-5.07-5.1-5.07zm0 8.65c-2 0-3.6-1.6-3.6-3.56 0-1.97 1.6-3.58 3.6-3.58 1.98 0 3.6 1.6 3.6 3.58a3.58 3.58 0 0 1-3.6 3.57zm0-6.4v2.66c0 .07.08.13.15.1l2.4-1.24c.04-.02.06-.1.03-.14a2.96 2.96 0 0 0-2.46-1.5c-.06 0-.1.05-.1.1zm-3.33-1.96l-.3-.3a.78.78 0 0 0-1.12 0l-.36.36a.77.77 0 0 0 0 1.1l.3.3c.05.05.13.04.17 0 .2-.25.4-.5.6-.7.23-.23.46-.43.7-.6.07-.04.07-.1.03-.16zm5-.8V3.4a.78.78 0 0 0-.78-.78h-1.83a.78.78 0 0 0-.78.78v.63c0 .07.06.12.14.1a5.74 5.74 0 0 1 1.58-.22c.52 0 1.04.07 1.54.2a.1.1 0 0 0 .13-.1z'/%3E%3Cpath fill='%2523182359' d='M102.16 13.76c0 1.46-.37 2.52-1.12 3.2-.75.67-1.9 1-3.44 1-.56 0-1.74-.1-2.67-.3l.34-1.7c.78.17 1.82.2 2.36.2.86 0 1.48-.16 1.84-.5.37-.36.55-.88.55-1.57v-.35a6.37 6.37 0 0 1-.84.3 4.15 4.15 0 0 1-1.2.17 4.5 4.5 0 0 1-1.6-.28 3.38 3.38 0 0 1-1.26-.82 3.74 3.74 0 0 1-.8-1.35c-.2-.54-.3-1.5-.3-2.2 0-.67.1-1.5.3-2.06a3.92 3.92 0 0 1 .9-1.43 4.12 4.12 0 0 1 1.45-.92 5.3 5.3 0 0 1 1.94-.37c.7 0 1.35.1 1.97.2a15.86 15.86 0 0 1 1.6.33v8.46zm-5.95-4.2c0 .9.2 1.88.6 2.3.4.4.9.62 1.53.62.34 0 .66-.05.96-.15a2.75 2.75 0 0 0 .73-.33V6.7a8.53 8.53 0 0 0-1.42-.17c-.76-.02-1.36.3-1.77.8-.4.5-.62 1.4-.62 2.23zm16.13 0c0 .72-.1 1.26-.32 1.85a4.4 4.4 0 0 1-.9 1.53c-.38.42-.85.75-1.4.98-.54.24-1.4.37-1.8.37-.43 0-1.27-.13-1.8-.36a4.1 4.1 0 0 1-1.4-.97 4.5 4.5 0 0 1-.92-1.52 5.04 5.04 0 0 1-.33-1.84c0-.72.1-1.4.32-2 .22-.6.53-1.1.92-1.5.4-.43.86-.75 1.4-.98a4.55 4.55 0 0 1 1.78-.34 4.7 4.7 0 0 1 1.8.34c.54.23 1 .55 1.4.97.38.42.68.92.9 1.5.23.6.35 1.3.35 2zm-2.2 0c0-.92-.2-1.7-.6-2.22-.38-.54-.94-.8-1.64-.8-.72 0-1.27.26-1.67.8-.4.54-.58 1.3-.58 2.22 0 .93.2 1.56.6 2.1.38.54.94.8 1.64.8s1.25-.26 1.65-.8c.4-.55.6-1.17.6-2.1zm6.97 4.7c-3.5.02-3.5-2.8-3.5-3.27L113.57.92l2.15-.34v10c0 .25 0 1.87 1.37 1.88v1.8zm3.77 0h-2.15v-9.2l2.15-.33v9.54zM119.8 3.74c.7 0 1.3-.58 1.3-1.3 0-.7-.58-1.3-1.3-1.3-.73 0-1.3.6-1.3 1.3 0 .72.58 1.3 1.3 1.3zm6.43 1c.7 0 1.3.1 1.78.27.5.18.88.42 1.17.73.28.3.5.74.6 1.18.13.46.2.95.2 1.5v5.47a25.24 25.24 0 0 1-1.5.25c-.67.1-1.42.15-2.25.15a6.83 6.83 0 0 1-1.52-.16 3.2 3.2 0 0 1-1.18-.5 2.46 2.46 0 0 1-.76-.9c-.18-.37-.27-.9-.27-1.44 0-.52.1-.85.3-1.2.2-.37.48-.67.83-.9a3.6 3.6 0 0 1 1.23-.5 7.07 7.07 0 0 1 2.2-.1l.83.16v-.35c0-.25-.03-.48-.1-.7a1.5 1.5 0 0 0-.3-.58c-.15-.18-.34-.3-.58-.4a2.54 2.54 0 0 0-.92-.17c-.5 0-.94.06-1.35.13-.4.08-.75.16-1 .25l-.27-1.74c.27-.1.67-.18 1.2-.28a9.34 9.34 0 0 1 1.65-.14zm.18 7.74c.66 0 1.15-.04 1.5-.1V10.2a5.1 5.1 0 0 0-2-.1c-.23.03-.45.1-.64.2a1.17 1.17 0 0 0-.47.38c-.13.17-.18.26-.18.52 0 .5.17.8.5.98.32.2.74.3 1.3.3zM84.1 4.8c.72 0 1.3.08 1.8.26.48.17.87.42 1.15.73.3.3.5.72.6 1.17.14.45.2.94.2 1.47v5.48a25.24 25.24 0 0 1-1.5.26c-.67.1-1.42.14-2.25.14a6.83 6.83 0 0 1-1.52-.16 3.2 3.2 0 0 1-1.18-.5 2.46 2.46 0 0 1-.76-.9c-.18-.38-.27-.9-.27-1.44 0-.53.1-.86.3-1.22.2-.36.5-.65.84-.88a3.6 3.6 0 0 1 1.24-.5 7.07 7.07 0 0 1 2.2-.1c.26.03.54.08.84.15v-.35c0-.24-.03-.48-.1-.7a1.5 1.5 0 0 0-.3-.58c-.15-.17-.34-.3-.58-.4a2.54 2.54 0 0 0-.9-.15c-.5 0-.96.05-1.37.12-.4.07-.75.15-1 .24l-.26-1.75c.27-.08.67-.17 1.18-.26a8.9 8.9 0 0 1 1.66-.15zm.2 7.73c.65 0 1.14-.04 1.48-.1v-2.17a5.1 5.1 0 0 0-1.98-.1c-.24.03-.46.1-.65.18a1.17 1.17 0 0 0-.47.4c-.12.17-.17.26-.17.52 0 .5.18.8.5.98.32.2.75.3 1.3.3zm8.68 1.74c-3.5 0-3.5-2.82-3.5-3.28L89.45.92 91.6.6v10c0 .25 0 1.87 1.38 1.88v1.8z'/%3E%3Cpath fill='%25231D3657' d='M5.03 11.03c0 .7-.26 1.24-.76 1.64-.5.4-1.2.6-2.1.6-.88 0-1.6-.14-2.17-.42v-1.2c.36.16.74.3 1.14.38.4.1.78.15 1.13.15.5 0 .88-.1 1.12-.3a.94.94 0 0 0 .35-.77.98.98 0 0 0-.33-.74c-.22-.2-.68-.44-1.37-.72-.72-.3-1.22-.62-1.52-1C.23 8.27.1 7.82.1 7.3c0-.65.22-1.17.7-1.55.46-.37 1.08-.56 1.86-.56.76 0 1.5.16 2.25.48l-.4 1.05c-.7-.3-1.32-.44-1.87-.44-.4 0-.73.08-.94.26a.9.9 0 0 0-.33.72c0 .2.04.38.12.52.08.15.22.3.42.4.2.14.55.3 1.06.52.58.24 1 .47 1.27.67.27.2.47.44.6.7.12.26.18.57.18.92zM9 13.27c-.92 0-1.64-.27-2.16-.8-.52-.55-.78-1.3-.78-2.24 0-.97.24-1.73.72-2.3.5-.54 1.15-.82 2-.82.78 0 1.4.25 1.85.72.46.48.7 1.14.7 1.97v.67H7.35c0 .58.17 1.02.46 1.33.3.3.7.47 1.24.47.36 0 .68-.04.98-.1a5.1 5.1 0 0 0 .98-.33v1.02a3.87 3.87 0 0 1-.94.32 5.72 5.72 0 0 1-1.08.1zm-.22-5.2c-.4 0-.73.12-.97.38s-.37.62-.42 1.1h2.7c0-.48-.13-.85-.36-1.1-.23-.26-.54-.38-.94-.38zm7.7 5.1l-.26-.84h-.05c-.28.36-.57.6-.86.74-.28.13-.65.2-1.1.2-.6 0-1.05-.16-1.38-.48-.32-.32-.5-.77-.5-1.34 0-.62.24-1.08.7-1.4.45-.3 1.14-.47 2.07-.5l1.02-.03V9.2c0-.37-.1-.65-.27-.84-.17-.2-.45-.28-.82-.28-.3 0-.6.04-.88.13a6.68 6.68 0 0 0-.8.33l-.4-.9a4.4 4.4 0 0 1 1.05-.4 4.86 4.86 0 0 1 1.08-.12c.76 0 1.33.18 1.7.5.4.33.6.85.6 1.56v4h-.9zm-1.9-.87c.47 0 .83-.13 1.1-.38.3-.26.43-.62.43-1.08v-.52l-.76.03c-.6.03-1.02.13-1.3.3s-.4.45-.4.82c0 .26.08.47.24.6.16.16.4.23.7.23zm7.57-5.2c.25 0 .46.03.62.06l-.12 1.18a2.38 2.38 0 0 0-.56-.06c-.5 0-.92.16-1.24.5-.3.32-.47.75-.47 1.27v3.1h-1.27V7.23h1l.16 1.05h.05c.2-.36.45-.64.77-.85a1.83 1.83 0 0 1 1.02-.3zm4.12 6.17c-.9 0-1.58-.27-2.05-.8-.47-.52-.7-1.27-.7-2.25 0-1 .24-1.77.73-2.3.5-.54 1.2-.8 2.12-.8.63 0 1.2.1 1.7.34l-.4 1c-.52-.2-.96-.3-1.3-.3-1.04 0-1.55.68-1.55 2.05 0 .67.13 1.17.38 1.5.26.34.64.5 1.13.5a3.23 3.23 0 0 0 1.6-.4v1.1a2.53 2.53 0 0 1-.73.28 4.36 4.36 0 0 1-.93.08zm8.28-.1h-1.27V9.5c0-.45-.1-.8-.28-1.02-.18-.23-.47-.34-.88-.34-.53 0-.9.16-1.16.48-.25.3-.38.85-.38 1.6v2.94h-1.26V4.8h1.26v2.12c0 .34-.02.7-.06 1.1h.08a1.76 1.76 0 0 1 .72-.67c.3-.16.66-.24 1.07-.24 1.43 0 2.15.74 2.15 2.2v3.86zM42.2 7.1c.74 0 1.32.28 1.73.82.4.53.62 1.3.62 2.26 0 .97-.2 1.73-.63 2.27-.42.54-1 .82-1.75.82s-1.33-.27-1.75-.8h-.08l-.23.7h-.94V4.8h1.26v2l-.02.64-.03.56h.05c.4-.6 1-.9 1.78-.9zm-.33 1.04c-.5 0-.88.15-1.1.45-.22.3-.34.8-.35 1.5v.08c0 .72.12 1.24.35 1.57.23.32.6.48 1.12.48.44 0 .78-.17 1-.53.24-.35.36-.87.36-1.53 0-1.35-.47-2.03-1.4-2.03zm3.24-.92h1.4l1.2 3.37c.18.47.3.92.36 1.34h.04l.18-.72 1.37-4H51l-2.53 6.73c-.46 1.23-1.23 1.85-2.3 1.85-.3 0-.56-.03-.83-.1v-1c.2.05.4.08.65.08.6 0 1.03-.36 1.28-1.06l.22-.56-2.4-5.94z'/%3E%3C/g%3E%3C/svg%3E"); + background-repeat: no-repeat; + background-position: center; + background-size: 100%; + overflow: hidden; + text-indent: -9000px; + width: 110px; + height: 100%; + display: block; + margin-left: auto; + margin-right: 5px; +} diff --git a/website/src/theme/SearchBar/index.js b/website/src/theme/SearchBar/index.js new file mode 100644 index 000000000..2f189d11e --- /dev/null +++ b/website/src/theme/SearchBar/index.js @@ -0,0 +1,118 @@ +/** + * Copyright (c) 2017-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +import React, { useRef, useCallback, useState } from "react"; +import classnames from "classnames"; +import { useHistory } from "@docusaurus/router"; +import useDocusaurusContext from "@docusaurus/useDocusaurusContext"; +import { usePluginData } from '@docusaurus/useGlobalData'; +const Search = props => { + const initialized = useRef(false); + const searchBarRef = useRef(null); + const [indexReady, setIndexReady] = useState(false); + const history = useHistory(); + const { siteConfig = {}, isClient = false} = useDocusaurusContext(); + const { baseUrl } = siteConfig; + const initAlgolia = (searchDocs, searchIndex, DocSearch) => { + new DocSearch({ + searchDocs, + searchIndex, + inputSelector: "#search_input_react", + // Override algolia's default selection event, allowing us to do client-side + // navigation and avoiding a full page refresh. + handleSelected: (_input, _event, suggestion) => { + const url = baseUrl + suggestion.url; + // Use an anchor tag to parse the absolute url into a relative url + // Alternatively, we can use new URL(suggestion.url) but its not supported in IE + const a = document.createElement("a"); + a.href = url; + // Algolia use closest parent element id #__docusaurus when a h1 page title does not have an id + // So, we can safely remove it. See https://github.com/facebook/docusaurus/issues/1828 for more details. + + history.push(url); + } + }); + }; + + const pluginData = usePluginData('docusaurus-lunr-search'); + const getSearchDoc = () => + process.env.NODE_ENV === "production" + ? fetch(`${baseUrl}${pluginData.fileNames.searchDoc}`).then((content) => content.json()) + : Promise.resolve([]); + + const getLunrIndex = () => + process.env.NODE_ENV === "production" + ? fetch(`${baseUrl}${pluginData.fileNames.lunrIndex}`).then((content) => content.json()) + : Promise.resolve([]); + + const loadAlgolia = () => { + if (!initialized.current) { + Promise.all([ + getSearchDoc(), + getLunrIndex(), + import("./lib/DocSearch"), + import("./algolia.css") + ]).then(([searchDocs, searchIndex, { default: DocSearch }]) => { + if( searchDocs.length === 0) { + return; + } + initAlgolia(searchDocs, searchIndex, DocSearch); + setIndexReady(true); + }); + initialized.current = true; + } + }; + + const toggleSearchIconClick = useCallback( + e => { + if (!searchBarRef.current.contains(e.target)) { + searchBarRef.current.focus(); + } + + props.handleSearchBarToggle && props.handleSearchBarToggle(!props.isSearchBarExpanded); + }, + [props.isSearchBarExpanded] + ); + + if (isClient) { + loadAlgolia(); + } + + return ( +
+ + +
+ ); +}; + +export default Search; diff --git a/website/src/theme/SearchBar/lib/DocSearch.js b/website/src/theme/SearchBar/lib/DocSearch.js new file mode 100644 index 000000000..ffdca6a59 --- /dev/null +++ b/website/src/theme/SearchBar/lib/DocSearch.js @@ -0,0 +1,306 @@ +import Hogan from "hogan.js"; +import LunrSearchAdapter from "./lunar-search"; +import autocomplete from "autocomplete.js"; +import templates from "./templates"; +import utils from "./utils"; +import $ from "autocomplete.js/zepto"; + +/** + * Adds an autocomplete dropdown to an input field + * @function DocSearch + * @param {Object} options.searchDocs Search Documents + * @param {Object} options.searchIndex Lune searchIndexes + * @param {string} options.inputSelector CSS selector that targets the input + * value. + * @param {Object} [options.autocompleteOptions] Options to pass to the underlying autocomplete instance + * @return {Object} + */ +class DocSearch { + constructor({ + searchDocs, + searchIndex, + inputSelector, + debug = false, + queryDataCallback = null, + autocompleteOptions = { + debug: false, + hint: false, + autoselect: true + }, + transformData = false, + queryHook = false, + handleSelected = false, + enhancedSearchInput = false, + layout = "collumns" + }) { + this.input = DocSearch.getInputFromSelector(inputSelector); + this.queryDataCallback = queryDataCallback || null; + const autocompleteOptionsDebug = + autocompleteOptions && autocompleteOptions.debug + ? autocompleteOptions.debug + : false; + // eslint-disable-next-line no-param-reassign + autocompleteOptions.debug = debug || autocompleteOptionsDebug; + this.autocompleteOptions = autocompleteOptions; + this.autocompleteOptions.cssClasses = + this.autocompleteOptions.cssClasses || {}; + this.autocompleteOptions.cssClasses.prefix = + this.autocompleteOptions.cssClasses.prefix || "ds"; + const inputAriaLabel = + this.input && + typeof this.input.attr === "function" && + this.input.attr("aria-label"); + this.autocompleteOptions.ariaLabel = + this.autocompleteOptions.ariaLabel || inputAriaLabel || "search input"; + + this.isSimpleLayout = layout === "simple"; + + this.client = new LunrSearchAdapter(searchDocs, searchIndex); + + if (enhancedSearchInput) { + this.input = DocSearch.injectSearchBox(this.input); + } + this.autocomplete = autocomplete(this.input, autocompleteOptions, [ + { + source: this.getAutocompleteSource(transformData, queryHook), + templates: { + suggestion: DocSearch.getSuggestionTemplate(this.isSimpleLayout), + footer: templates.footer, + empty: DocSearch.getEmptyTemplate() + } + } + ]); + + const customHandleSelected = handleSelected; + this.handleSelected = customHandleSelected || this.handleSelected; + + // We prevent default link clicking if a custom handleSelected is defined + if (customHandleSelected) { + $(".algolia-autocomplete").on("click", ".ds-suggestions a", event => { + event.preventDefault(); + }); + } + + this.autocomplete.on( + "autocomplete:selected", + this.handleSelected.bind(null, this.autocomplete.autocomplete) + ); + + this.autocomplete.on( + "autocomplete:shown", + this.handleShown.bind(null, this.input) + ); + + if (enhancedSearchInput) { + DocSearch.bindSearchBoxEvent(); + } + } + + static injectSearchBox(input) { + input.before(templates.searchBox); + const newInput = input + .prev() + .prev() + .find("input"); + input.remove(); + return newInput; + } + + static bindSearchBoxEvent() { + $('.searchbox [type="reset"]').on("click", function () { + $("input#docsearch").focus(); + $(this).addClass("hide"); + autocomplete.autocomplete.setVal(""); + }); + + $("input#docsearch").on("keyup", () => { + const searchbox = document.querySelector("input#docsearch"); + const reset = document.querySelector('.searchbox [type="reset"]'); + reset.className = "searchbox__reset"; + if (searchbox.value.length === 0) { + reset.className += " hide"; + } + }); + } + + /** + * Returns the matching input from a CSS selector, null if none matches + * @function getInputFromSelector + * @param {string} selector CSS selector that matches the search + * input of the page + * @returns {void} + */ + static getInputFromSelector(selector) { + const input = $(selector).filter("input"); + return input.length ? $(input[0]) : null; + } + + /** + * Returns the `source` method to be passed to autocomplete.js. It will query + * the Algolia index and call the callbacks with the formatted hits. + * @function getAutocompleteSource + * @param {function} transformData An optional function to transform the hits + * @param {function} queryHook An optional function to transform the query + * @returns {function} Method to be passed as the `source` option of + * autocomplete + */ + getAutocompleteSource(transformData, queryHook) { + return (query, callback) => { + if (queryHook) { + // eslint-disable-next-line no-param-reassign + query = queryHook(query) || query; + } + this.client.search(query).then(hits => { + if ( + this.queryDataCallback && + typeof this.queryDataCallback == "function" + ) { + this.queryDataCallback(hits); + } + if (transformData) { + hits = transformData(hits) || hits; + } + callback(DocSearch.formatHits(hits)); + }); + }; + } + + // Given a list of hits returned by the API, will reformat them to be used in + // a Hogan template + static formatHits(receivedHits) { + const clonedHits = utils.deepClone(receivedHits); + const hits = clonedHits.map(hit => { + if (hit._highlightResult) { + // eslint-disable-next-line no-param-reassign + hit._highlightResult = utils.mergeKeyWithParent( + hit._highlightResult, + "hierarchy" + ); + } + return utils.mergeKeyWithParent(hit, "hierarchy"); + }); + + // Group hits by category / subcategory + let groupedHits = utils.groupBy(hits, "lvl0"); + $.each(groupedHits, (level, collection) => { + const groupedHitsByLvl1 = utils.groupBy(collection, "lvl1"); + const flattenedHits = utils.flattenAndFlagFirst( + groupedHitsByLvl1, + "isSubCategoryHeader" + ); + groupedHits[level] = flattenedHits; + }); + groupedHits = utils.flattenAndFlagFirst(groupedHits, "isCategoryHeader"); + + // Translate hits into smaller objects to be send to the template + return groupedHits.map(hit => { + const url = DocSearch.formatURL(hit); + const category = utils.getHighlightedValue(hit, "lvl0"); + const subcategory = utils.getHighlightedValue(hit, "lvl1") || category; + const displayTitle = utils + .compact([ + utils.getHighlightedValue(hit, "lvl2") || subcategory, + utils.getHighlightedValue(hit, "lvl3"), + utils.getHighlightedValue(hit, "lvl4"), + utils.getHighlightedValue(hit, "lvl5"), + utils.getHighlightedValue(hit, "lvl6") + ]) + .join( + '' + ); + const text = utils.getSnippetedValue(hit, "content"); + const isTextOrSubcategoryNonEmpty = + (subcategory && subcategory !== "") || + (displayTitle && displayTitle !== ""); + const isLvl1EmptyOrDuplicate = + !subcategory || subcategory === "" || subcategory === category; + const isLvl2 = + displayTitle && displayTitle !== "" && displayTitle !== subcategory; + const isLvl1 = + !isLvl2 && + (subcategory && subcategory !== "" && subcategory !== category); + const isLvl0 = !isLvl1 && !isLvl2; + + return { + isLvl0, + isLvl1, + isLvl2, + isLvl1EmptyOrDuplicate, + isCategoryHeader: hit.isCategoryHeader, + isSubCategoryHeader: hit.isSubCategoryHeader, + isTextOrSubcategoryNonEmpty, + category, + subcategory, + title: displayTitle, + text, + url + }; + }); + } + + static formatURL(hit) { + const { url, anchor } = hit; + if (url) { + const containsAnchor = url.indexOf("#") !== -1; + if (containsAnchor) return url; + else if (anchor) return `${hit.url}#${hit.anchor}`; + return url; + } else if (anchor) return `#${hit.anchor}`; + /* eslint-disable */ + console.warn("no anchor nor url for : ", JSON.stringify(hit)); + /* eslint-enable */ + return null; + } + + static getEmptyTemplate() { + return args => Hogan.compile(templates.empty).render(args); + } + + static getSuggestionTemplate(isSimpleLayout) { + const stringTemplate = isSimpleLayout + ? templates.suggestionSimple + : templates.suggestion; + const template = Hogan.compile(stringTemplate); + return suggestion => template.render(suggestion); + } + + handleSelected(input, event, suggestion, datasetNumber, context = {}) { + // Do nothing if click on the suggestion, as it's already a , the + // browser will take care of it. This allow Ctrl-Clicking on results and not + // having the main window being redirected as well + if (context.selectionMethod === "click") { + return; + } + + input.setVal(""); + window.location.assign(suggestion.url); + } + + handleShown(input) { + const middleOfInput = input.offset().left + input.width() / 2; + let middleOfWindow = $(document).width() / 2; + + if (isNaN(middleOfWindow)) { + middleOfWindow = 900; + } + + const alignClass = + middleOfInput - middleOfWindow >= 0 + ? "algolia-autocomplete-right" + : "algolia-autocomplete-left"; + const otherAlignClass = + middleOfInput - middleOfWindow < 0 + ? "algolia-autocomplete-right" + : "algolia-autocomplete-left"; + const autocompleteWrapper = $(".algolia-autocomplete"); + if (!autocompleteWrapper.hasClass(alignClass)) { + autocompleteWrapper.addClass(alignClass); + } + + if (autocompleteWrapper.hasClass(otherAlignClass)) { + autocompleteWrapper.removeClass(otherAlignClass); + } + } +} + +export default DocSearch; \ No newline at end of file diff --git a/website/src/theme/SearchBar/lib/lunar-search.js b/website/src/theme/SearchBar/lib/lunar-search.js new file mode 100644 index 000000000..159b79504 --- /dev/null +++ b/website/src/theme/SearchBar/lib/lunar-search.js @@ -0,0 +1,146 @@ +import lunr from "@generated/lunr.client"; +lunr.tokenizer.separator = /[\s\-/]+/; + +class LunrSearchAdapter { + constructor(searchDocs, searchIndex) { + this.searchDocs = searchDocs; + this.lunrIndex = lunr.Index.load(searchIndex); + } + + getLunrResult(input) { + return this.lunrIndex.query(function (query) { + const tokens = lunr.tokenizer(input); + query.term(tokens, { + boost: 10 + }); + query.term(tokens, { + wildcard: lunr.Query.wildcard.TRAILING + }); + }); + } + + getHit(doc, formattedTitle, formattedContent) { + return { + hierarchy: { + lvl0: doc.pageTitle || doc.title, + lvl1: doc.type === 0 ? null : doc.title + }, + url: doc.url, + _snippetResult: formattedContent ? { + content: { + value: formattedContent, + matchLevel: "full" + } + } : null, + _highlightResult: { + hierarchy: { + lvl0: { + value: doc.type === 0 ? formattedTitle || doc.title : doc.pageTitle, + }, + lvl1: + doc.type === 0 + ? null + : { + value: formattedTitle || doc.title + } + } + } + }; + } + getTitleHit(doc, position, length) { + const start = position[0]; + const end = position[0] + length; + let formattedTitle = doc.title.substring(0, start) + '' + doc.title.substring(start, end) + '' + doc.title.substring(end, doc.title.length); + return this.getHit(doc, formattedTitle) + } + + getKeywordHit(doc, position, length) { + const start = position[0]; + const end = position[0] + length; + let formattedTitle = doc.title + '
Keywords: ' + doc.keywords.substring(0, start) + '' + doc.keywords.substring(start, end) + '' + doc.keywords.substring(end, doc.keywords.length) + '' + return this.getHit(doc, formattedTitle) + } + + getContentHit(doc, position) { + const start = position[0]; + const end = position[0] + position[1]; + let previewStart = start; + let previewEnd = end; + let ellipsesBefore = true; + let ellipsesAfter = true; + for (let k = 0; k < 3; k++) { + const nextSpace = doc.content.lastIndexOf(' ', previewStart - 2); + const nextDot = doc.content.lastIndexOf('.', previewStart - 2); + if ((nextDot > 0) && (nextDot > nextSpace)) { + previewStart = nextDot + 1; + ellipsesBefore = false; + break; + } + if (nextSpace < 0) { + previewStart = 0; + ellipsesBefore = false; + break; + } + previewStart = nextSpace + 1; + } + for (let k = 0; k < 10; k++) { + const nextSpace = doc.content.indexOf(' ', previewEnd + 1); + const nextDot = doc.content.indexOf('.', previewEnd + 1); + if ((nextDot > 0) && (nextDot < nextSpace)) { + previewEnd = nextDot; + ellipsesAfter = false; + break; + } + if (nextSpace < 0) { + previewEnd = doc.content.length; + ellipsesAfter = false; + break; + } + previewEnd = nextSpace; + } + let preview = doc.content.substring(previewStart, start); + if (ellipsesBefore) { + preview = '... ' + preview; + } + preview += '' + doc.content.substring(start, end) + ''; + preview += doc.content.substring(end, previewEnd); + if (ellipsesAfter) { + preview += ' ...'; + } + return this.getHit(doc, null, preview); + + } + search(input) { + return new Promise((resolve, rej) => { + const results = this.getLunrResult(input); + const hits = []; + results.length > 5 && (results.length = 5); + this.titleHitsRes = [] + this.contentHitsRes = [] + results.forEach(result => { + const doc = this.searchDocs[result.ref]; + const { metadata } = result.matchData; + for (let i in metadata) { + if (metadata[i].title) { + if (!this.titleHitsRes.includes(result.ref)) { + const position = metadata[i].title.position[0] + hits.push(this.getTitleHit(doc, position, input.length)); + this.titleHitsRes.push(result.ref); + } + } else if (metadata[i].content) { + const position = metadata[i].content.position[0] + hits.push(this.getContentHit(doc, position)) + } else if (metadata[i].keywords) { + const position = metadata[i].keywords.position[0] + hits.push(this.getKeywordHit(doc, position, input.length)); + this.titleHitsRes.push(result.ref); + } + } + }); + hits.length > 5 && (hits.length = 5); + resolve(hits); + }); + } +} + +export default LunrSearchAdapter; diff --git a/website/src/theme/SearchBar/lib/templates.js b/website/src/theme/SearchBar/lib/templates.js new file mode 100644 index 000000000..c7ea998fd --- /dev/null +++ b/website/src/theme/SearchBar/lib/templates.js @@ -0,0 +1,114 @@ +const prefix = 'algolia-docsearch'; +const suggestionPrefix = `${prefix}-suggestion`; +const footerPrefix = `${prefix}-footer`; + +/* eslint-disable max-len */ + +const templates = { + suggestion: ` +
+
+ {{{category}}} +
+
+
+ {{{subcategory}}} +
+ {{#isTextOrSubcategoryNonEmpty}} +
+
{{{subcategory}}}
+
{{{title}}}
+ {{#text}}
{{{text}}}
{{/text}} +
+ {{/isTextOrSubcategoryNonEmpty}} +
+
+ `, + suggestionSimple: ` +
+
+ {{^isLvl0}} + {{{category}}} + {{^isLvl1}} + {{^isLvl1EmptyOrDuplicate}} + + {{{subcategory}}} + + {{/isLvl1EmptyOrDuplicate}} + {{/isLvl1}} + {{/isLvl0}} +
+ {{#isLvl2}} + {{{title}}} + {{/isLvl2}} + {{#isLvl1}} + {{{subcategory}}} + {{/isLvl1}} + {{#isLvl0}} + {{{category}}} + {{/isLvl0}} +
+
+
+ {{#text}} +
+
{{{text}}}
+
+ {{/text}} +
+
+ `, + footer: ` +
+
+ `, + empty: ` +
+
+
+
+
+ No results found for query "{{query}}" +
+
+
+
+
+ `, + searchBox: ` + + + + `, +}; + +export default templates; diff --git a/website/src/theme/SearchBar/lib/utils.js b/website/src/theme/SearchBar/lib/utils.js new file mode 100644 index 000000000..0807500d7 --- /dev/null +++ b/website/src/theme/SearchBar/lib/utils.js @@ -0,0 +1,270 @@ +import $ from "autocomplete.js/zepto"; + +const utils = { + /* + * Move the content of an object key one level higher. + * eg. + * { + * name: 'My name', + * hierarchy: { + * lvl0: 'Foo', + * lvl1: 'Bar' + * } + * } + * Will be converted to + * { + * name: 'My name', + * lvl0: 'Foo', + * lvl1: 'Bar' + * } + * @param {Object} object Main object + * @param {String} property Main object key to move up + * @return {Object} + * @throws Error when key is not an attribute of Object or is not an object itself + */ + mergeKeyWithParent(object, property) { + if (object[property] === undefined) { + return object; + } + if (typeof object[property] !== 'object') { + return object; + } + const newObject = $.extend({}, object, object[property]); + delete newObject[property]; + return newObject; + }, + /* + * Group all objects of a collection by the value of the specified attribute + * If the attribute is a string, use the lowercase form. + * + * eg. + * groupBy([ + * {name: 'Tim', category: 'dev'}, + * {name: 'Vincent', category: 'dev'}, + * {name: 'Ben', category: 'sales'}, + * {name: 'Jeremy', category: 'sales'}, + * {name: 'AlexS', category: 'dev'}, + * {name: 'AlexK', category: 'sales'} + * ], 'category'); + * => + * { + * 'devs': [ + * {name: 'Tim', category: 'dev'}, + * {name: 'Vincent', category: 'dev'}, + * {name: 'AlexS', category: 'dev'} + * ], + * 'sales': [ + * {name: 'Ben', category: 'sales'}, + * {name: 'Jeremy', category: 'sales'}, + * {name: 'AlexK', category: 'sales'} + * ] + * } + * @param {array} collection Array of objects to group + * @param {String} property The attribute on which apply the grouping + * @return {array} + * @throws Error when one of the element does not have the specified property + */ + groupBy(collection, property) { + const newCollection = {}; + $.each(collection, (index, item) => { + if (item[property] === undefined) { + throw new Error(`[groupBy]: Object has no key ${property}`); + } + let key = item[property]; + if (typeof key === 'string') { + key = key.toLowerCase(); + } + // fix #171 the given data type of docsearch hits might be conflict with the properties of the native Object, + // such as the constructor, so we need to do this check. + if (!Object.prototype.hasOwnProperty.call(newCollection, key)) { + newCollection[key] = []; + } + newCollection[key].push(item); + }); + return newCollection; + }, + /* + * Return an array of all the values of the specified object + * eg. + * values({ + * foo: 42, + * bar: true, + * baz: 'yep' + * }) + * => + * [42, true, yep] + * @param {object} object Object to extract values from + * @return {array} + */ + values(object) { + return Object.keys(object).map(key => object[key]); + }, + /* + * Flattens an array + * eg. + * flatten([1, 2, [3, 4], [5, 6]]) + * => + * [1, 2, 3, 4, 5, 6] + * @param {array} array Array to flatten + * @return {array} + */ + flatten(array) { + const results = []; + array.forEach(value => { + if (!Array.isArray(value)) { + results.push(value); + return; + } + value.forEach(subvalue => { + results.push(subvalue); + }); + }); + return results; + }, + /* + * Flatten all values of an object into an array, marking each first element of + * each group with a specific flag + * eg. + * flattenAndFlagFirst({ + * 'devs': [ + * {name: 'Tim', category: 'dev'}, + * {name: 'Vincent', category: 'dev'}, + * {name: 'AlexS', category: 'dev'} + * ], + * 'sales': [ + * {name: 'Ben', category: 'sales'}, + * {name: 'Jeremy', category: 'sales'}, + * {name: 'AlexK', category: 'sales'} + * ] + * , 'isTop'); + * => + * [ + * {name: 'Tim', category: 'dev', isTop: true}, + * {name: 'Vincent', category: 'dev', isTop: false}, + * {name: 'AlexS', category: 'dev', isTop: false}, + * {name: 'Ben', category: 'sales', isTop: true}, + * {name: 'Jeremy', category: 'sales', isTop: false}, + * {name: 'AlexK', category: 'sales', isTop: false} + * ] + * @param {object} object Object to flatten + * @param {string} flag Flag to set to true on first element of each group + * @return {array} + */ + flattenAndFlagFirst(object, flag) { + const values = this.values(object).map(collection => + collection.map((item, index) => { + // eslint-disable-next-line no-param-reassign + item[flag] = index === 0; + return item; + }) + ); + return this.flatten(values); + }, + /* + * Removes all empty strings, null, false and undefined elements array + * eg. + * compact([42, false, null, undefined, '', [], 'foo']); + * => + * [42, [], 'foo'] + * @param {array} array Array to compact + * @return {array} + */ + compact(array) { + const results = []; + array.forEach(value => { + if (!value) { + return; + } + results.push(value); + }); + return results; + }, + /* + * Returns the highlighted value of the specified key in the specified object. + * If no highlighted value is available, will return the key value directly + * eg. + * getHighlightedValue({ + * _highlightResult: { + * text: { + * value: 'foo' + * } + * }, + * text: 'foo' + * }, 'text'); + * => + * 'foo' + * @param {object} object Hit object returned by the Algolia API + * @param {string} property Object key to look for + * @return {string} + **/ + getHighlightedValue(object, property) { + if ( + object._highlightResult && + object._highlightResult.hierarchy_camel && + object._highlightResult.hierarchy_camel[property] && + object._highlightResult.hierarchy_camel[property].matchLevel && + object._highlightResult.hierarchy_camel[property].matchLevel !== 'none' && + object._highlightResult.hierarchy_camel[property].value + ) { + return object._highlightResult.hierarchy_camel[property].value; + } + if ( + object._highlightResult && + object._highlightResult && + object._highlightResult[property] && + object._highlightResult[property].value + ) { + return object._highlightResult[property].value; + } + return object[property]; + }, + /* + * Returns the snippeted value of the specified key in the specified object. + * If no highlighted value is available, will return the key value directly. + * Will add starting and ending ellipsis (…) if we detect that a sentence is + * incomplete + * eg. + * getSnippetedValue({ + * _snippetResult: { + * text: { + * value: 'This is an unfinished sentence' + * } + * }, + * text: 'This is an unfinished sentence' + * }, 'text'); + * => + * 'This is an unfinished sentence…' + * @param {object} object Hit object returned by the Algolia API + * @param {string} property Object key to look for + * @return {string} + **/ + getSnippetedValue(object, property) { + if ( + !object._snippetResult || + !object._snippetResult[property] || + !object._snippetResult[property].value + ) { + return object[property]; + } + let snippet = object._snippetResult[property].value; + + if (snippet[0] !== snippet[0].toUpperCase()) { + snippet = `…${snippet}`; + } + if (['.', '!', '?'].indexOf(snippet[snippet.length - 1]) === -1) { + snippet = `${snippet}…`; + } + return snippet; + }, + /* + * Deep clone an object. + * Note: This will not clone functions and dates + * @param {object} object Object to clone + * @return {object} + */ + deepClone(object) { + return JSON.parse(JSON.stringify(object)); + }, +}; + +export default utils; diff --git a/website/src/theme/SearchBar/styles.css b/website/src/theme/SearchBar/styles.css new file mode 100644 index 000000000..047517ec0 --- /dev/null +++ b/website/src/theme/SearchBar/styles.css @@ -0,0 +1,40 @@ +/** + * Copyright (c) 2017-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +.search-icon { + background-image: var(--ifm-navbar-search-input-icon); + height: auto; + width: 24px; + cursor: pointer; + padding: 8px; + line-height: 32px; + background-repeat: no-repeat; + background-position: center; + display: none; +} + +.search-icon-hidden { + visibility: hidden; +} + +@media (max-width: 360px) { + .search-bar { + width: 0 !important; + background: none !important; + padding: 0 !important; + transition: none !important; + } + + .search-bar-expanded { + width: 9rem !important; + } + + .search-icon { + display: inline; + vertical-align: sub; + } +} diff --git a/website/yarn.lock b/website/yarn.lock index 90695f89a..abb23c452 100644 --- a/website/yarn.lock +++ b/website/yarn.lock @@ -2107,6 +2107,11 @@ abab@^2.0.3, abab@^2.0.5: resolved "https://registry.yarnpkg.com/abab/-/abab-2.0.5.tgz#c0b678fb32d60fc1219c784d6a826fe385aeb79a" integrity sha512-9IK9EadsbHo6jLWIpxpR6pL0sazTXV6+SQv25ZB+F7Bj9mJNaOc4nCRabwd5M/JwmUa8idz6Eci6eKfJryPs6Q== +abbrev@1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" + integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q== + accepts@~1.3.4, accepts@~1.3.5, accepts@~1.3.7: version "1.3.7" resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.7.tgz#531bc726517a3b2b41f850021c6cc15eaab507cd" @@ -2298,6 +2303,11 @@ anymatch@~3.1.2: normalize-path "^3.0.0" picomatch "^2.0.4" +"aproba@^1.0.3 || ^2.0.0": + version "2.0.0" + resolved "https://registry.yarnpkg.com/aproba/-/aproba-2.0.0.tgz#52520b8ae5b569215b354efc0caa3fe1e45a8adc" + integrity sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ== + arg@^5.0.0: version "5.0.1" resolved "https://registry.yarnpkg.com/arg/-/arg-5.0.1.tgz#eb0c9a8f77786cad2af8ff2b862899842d7b6adb" @@ -2357,6 +2367,13 @@ at-least-node@^1.0.0: resolved "https://registry.yarnpkg.com/at-least-node/-/at-least-node-1.0.0.tgz#602cd4b46e844ad4effc92a8011a3c46e0238dc2" integrity sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg== +autocomplete.js@^0.37.0: + version "0.37.1" + resolved "https://registry.yarnpkg.com/autocomplete.js/-/autocomplete.js-0.37.1.tgz#a29a048d827e7d2bf8f7df8b831766e5cc97df01" + integrity sha512-PgSe9fHYhZEsm/9jggbjtVsGXJkPLvd+9mC7gZJ662vVL5CRWEtm/mIrrzCx0MrNxHVwxD5d00UOn6NsmL2LUQ== + dependencies: + immediate "^3.2.3" + autoprefixer@^10.3.5, autoprefixer@^10.3.7: version "10.4.2" resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-10.4.2.tgz#25e1df09a31a9fba5c40b578936b90d35c9d4d3b" @@ -2464,6 +2481,11 @@ batch@0.6.1: resolved "https://registry.yarnpkg.com/batch/-/batch-0.6.1.tgz#dc34314f4e679318093fc760272525f94bf25c16" integrity sha1-3DQxT05nkxgJP8dgJyUl+UvyXBY= +bcp-47-match@^1.0.0: + version "1.0.3" + resolved "https://registry.yarnpkg.com/bcp-47-match/-/bcp-47-match-1.0.3.tgz#cb8d03071389a10aff2062b862d6575ffd7cd7ef" + integrity sha512-LggQ4YTdjWQSKELZF5JwchnBa1u0pIQSZf5lSdOHEdbVP55h0qICA/FUp3+W99q0xqxYa1ZQizTUH87gecII5w== + big.js@^5.2.2: version "5.2.2" resolved "https://registry.yarnpkg.com/big.js/-/big.js-5.2.2.tgz#65f0af382f578bcdc742bd9c281e9cb2d7768328" @@ -2757,6 +2779,11 @@ ci-info@^2.0.0: resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-2.0.0.tgz#67a9e964be31a51e15e5010d58e6f12834002f46" integrity sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ== +classnames@^2.2.6: + version "2.3.1" + resolved "https://registry.yarnpkg.com/classnames/-/classnames-2.3.1.tgz#dfcfa3891e306ec1dad105d0e88f4417b8535e8e" + integrity sha512-OlQdbZ7gLfGarSqxesMesDa5uz7KFbID8Kpq/SxIoNGDqY8lSYs0D+hhtBXhcdB3rcbXArFr7vlHheLk1voeNA== + clean-css@^5.1.5, clean-css@^5.2.2: version "5.2.2" resolved "https://registry.yarnpkg.com/clean-css/-/clean-css-5.2.2.tgz#d3a7c6ee2511011e051719838bdcf8314dc4548d" @@ -2824,6 +2851,11 @@ color-name@~1.1.4: resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== +color-support@^1.1.2: + version "1.1.3" + resolved "https://registry.yarnpkg.com/color-support/-/color-support-1.1.3.tgz#93834379a1cc9a0c61f82f52f0d04322251bd5a2" + integrity sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg== + colord@^2.9.1: version "2.9.2" resolved "https://registry.yarnpkg.com/colord/-/colord-2.9.2.tgz#25e2bacbbaa65991422c07ea209e2089428effb1" @@ -2928,6 +2960,11 @@ consola@^2.15.3: resolved "https://registry.yarnpkg.com/consola/-/consola-2.15.3.tgz#2e11f98d6a4be71ff72e0bdf07bd23e12cb61550" integrity sha512-9vAdYbHj6x2fLKC4+oPH0kFzY/orMZyG2Aj+kNylHxKGJ/Ed4dpNyAQYwJOdqO4zdM7XpVHmyejQDcQHrnuXbw== +console-control-strings@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e" + integrity sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4= + content-disposition@0.5.2: version "0.5.2" resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.2.tgz#0cf68bb9ddf5f2be7961c3a85178cb85dba78cb4" @@ -3099,6 +3136,11 @@ css-select@~1.2.0: domutils "1.5.1" nth-check "~1.0.1" +css-selector-parser@^1.0.0: + version "1.4.1" + resolved "https://registry.yarnpkg.com/css-selector-parser/-/css-selector-parser-1.4.1.tgz#03f9cb8a81c3e5ab2c51684557d5aaf6d2569759" + integrity sha512-HYPSb7y/Z7BNDCOrakL4raGO2zltZkbeXyAd6Tg9obzix6QhzxCotdBl6VT0Dv4vZfJGVz3WL/xaEI9Ly3ul0g== + css-tree@^1.1.2, css-tree@^1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/css-tree/-/css-tree-1.1.3.tgz#eb4870fb6fd7707327ec95c2ff2ab09b5e8db91d" @@ -3369,6 +3411,11 @@ dir-glob@^3.0.1: dependencies: path-type "^4.0.0" +direction@^1.0.0: + version "1.0.4" + resolved "https://registry.yarnpkg.com/direction/-/direction-1.0.4.tgz#2b86fb686967e987088caf8b89059370d4837442" + integrity sha512-GYqKi1aH7PJXxdhTeZBFrg8vUBeKXi+cNprXsC1kpJcbcVnV9wBsrOu1cQEdG0WeQwlfHiy3XvnKfIrJ2R0NzQ== + dns-equal@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/dns-equal/-/dns-equal-1.0.0.tgz#b39e7f1da6eb0a75ba9c17324b34753c47e0654d" @@ -3389,6 +3436,26 @@ dns-txt@^2.0.2: dependencies: buffer-indexof "^1.0.0" +docusaurus-lunr-search@^2.1.15: + version "2.1.15" + resolved "https://registry.yarnpkg.com/docusaurus-lunr-search/-/docusaurus-lunr-search-2.1.15.tgz#e0b141ebf6226e3fb2cd7ec0a07fccee809cfc94" + integrity sha512-W37af7ziwNFstM0VNjruJi3HChPWI5BWGAAxFYpRRbMZQAZqdQtz4aZHX5E/ORrfqHWsKTGMCRWode1rb3ncQw== + dependencies: + autocomplete.js "^0.37.0" + classnames "^2.2.6" + gauge "^3.0.0" + hast-util-select "^4.0.0" + hast-util-to-text "^2.0.0" + hogan.js "^3.0.2" + lunr "^2.3.8" + lunr-languages "^1.4.0" + minimatch "^3.0.4" + object-assign "^4.1.1" + rehype-parse "^7.0.1" + to-vfile "^6.1.0" + unified "^9.0.0" + unist-util-is "^4.0.2" + dom-converter@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/dom-converter/-/dom-converter-0.2.0.tgz#6721a9daee2e293682955b6afe416771627bb768" @@ -3980,6 +4047,21 @@ function-bind@^1.1.1: resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== +gauge@^3.0.0: + version "3.0.2" + resolved "https://registry.yarnpkg.com/gauge/-/gauge-3.0.2.tgz#03bf4441c044383908bcfa0656ad91803259b395" + integrity sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q== + dependencies: + aproba "^1.0.3 || ^2.0.0" + color-support "^1.1.2" + console-control-strings "^1.0.0" + has-unicode "^2.0.1" + object-assign "^4.1.1" + signal-exit "^3.0.0" + string-width "^4.2.3" + strip-ansi "^6.0.1" + wide-align "^1.1.2" + gensync@^1.0.0-beta.1, gensync@^1.0.0-beta.2: version "1.0.0-beta.2" resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.2.tgz#32a6ee76c3d7f52d46b2b1ae5d93fea8580a25e0" @@ -4172,6 +4254,11 @@ has-tostringtag@^1.0.0: dependencies: has-symbols "^1.0.2" +has-unicode@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9" + integrity sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk= + has-yarn@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/has-yarn/-/has-yarn-2.1.0.tgz#137e11354a7b5bf11aa5cb649cf0c6f3ff2b2e77" @@ -4228,6 +4315,11 @@ hast-util-from-parse5@^6.0.0: vfile-location "^3.2.0" web-namespaces "^1.0.0" +hast-util-has-property@^1.0.0: + version "1.0.4" + resolved "https://registry.yarnpkg.com/hast-util-has-property/-/hast-util-has-property-1.0.4.tgz#9f137565fad6082524b382c1e7d7d33ca5059f36" + integrity sha512-ghHup2voGfgFoHMGnaLHOjbYFACKrRh9KFttdCzMCbFoBMJXiNi2+XTrPP8+q6cDJM/RSqlCfVWrjp1H201rZg== + hast-util-is-element@1.1.0, hast-util-is-element@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/hast-util-is-element/-/hast-util-is-element-1.1.0.tgz#3b3ed5159a2707c6137b48637fbfe068e175a425" @@ -4269,6 +4361,26 @@ hast-util-raw@6.0.1: xtend "^4.0.0" zwitch "^1.0.0" +hast-util-select@^4.0.0: + version "4.0.2" + resolved "https://registry.yarnpkg.com/hast-util-select/-/hast-util-select-4.0.2.tgz#ae3ef2860e02cda2ad3a2e72b47c1f5e8f44e9e7" + integrity sha512-8EEG2//bN5rrzboPWD2HdS3ugLijNioS1pqOTIolXNf67xxShYw4SQEmVXd3imiBG+U2bC2nVTySr/iRAA7Cjg== + dependencies: + bcp-47-match "^1.0.0" + comma-separated-tokens "^1.0.0" + css-selector-parser "^1.0.0" + direction "^1.0.0" + hast-util-has-property "^1.0.0" + hast-util-is-element "^1.0.0" + hast-util-to-string "^1.0.0" + hast-util-whitespace "^1.0.0" + not "^0.1.0" + nth-check "^2.0.0" + property-information "^5.0.0" + space-separated-tokens "^1.0.0" + unist-util-visit "^2.0.0" + zwitch "^1.0.0" + hast-util-to-parse5@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/hast-util-to-parse5/-/hast-util-to-parse5-6.0.0.tgz#1ec44650b631d72952066cea9b1445df699f8479" @@ -4280,6 +4392,11 @@ hast-util-to-parse5@^6.0.0: xtend "^4.0.0" zwitch "^1.0.0" +hast-util-to-string@^1.0.0: + version "1.0.4" + resolved "https://registry.yarnpkg.com/hast-util-to-string/-/hast-util-to-string-1.0.4.tgz#9b24c114866bdb9478927d7e9c36a485ac728378" + integrity sha512-eK0MxRX47AV2eZ+Lyr18DCpQgodvaS3fAQO2+b9Two9F5HEoRPhiUMNzoXArMJfZi2yieFzUBMRl3HNJ3Jus3w== + hast-util-to-text@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/hast-util-to-text/-/hast-util-to-text-2.0.1.tgz#04f2e065642a0edb08341976084aa217624a0f8b" @@ -4298,6 +4415,11 @@ hast-util-to-text@^3.1.0: hast-util-is-element "^2.0.0" unist-util-find-after "^4.0.0" +hast-util-whitespace@^1.0.0: + version "1.0.4" + resolved "https://registry.yarnpkg.com/hast-util-whitespace/-/hast-util-whitespace-1.0.4.tgz#e4fe77c4a9ae1cb2e6c25e02df0043d0164f6e41" + integrity sha512-I5GTdSfhYfAPNztx2xJRQpG8cuDSNt599/7YUn7Gx/WxNMsG+a835k97TDkFgk123cwjfwINaZknkKkphx/f2A== + hastscript@^5.0.0: version "5.1.2" resolved "https://registry.yarnpkg.com/hastscript/-/hastscript-5.1.2.tgz#bde2c2e56d04c62dd24e8c5df288d050a355fb8a" @@ -4347,6 +4469,14 @@ history@^4.9.0: tiny-warning "^1.0.0" value-equal "^1.0.1" +hogan.js@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/hogan.js/-/hogan.js-3.0.2.tgz#4cd9e1abd4294146e7679e41d7898732b02c7bfd" + integrity sha1-TNnhq9QpQUbnZ55B14mHMrAse/0= + dependencies: + mkdirp "0.3.0" + nopt "1.0.10" + hoist-non-react-statics@^3.1.0: version "3.3.2" resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz#ece0acaf71d62c2969c2ec59feff42a4b1a85b45" @@ -4541,6 +4671,11 @@ image-size@^1.0.1: dependencies: queue "6.0.2" +immediate@^3.2.3: + version "3.3.0" + resolved "https://registry.yarnpkg.com/immediate/-/immediate-3.3.0.tgz#1aef225517836bcdf7f2a2de2600c79ff0269266" + integrity sha512-HR7EVodfFUdQCTIeySw+WDRFJlPcLOJbXfwwZ7Oom6tjsvZ3bOkCDJHehQC3nxJrv7+f9XecwazynjU8e4Vw3Q== + immer@^9.0.7: version "9.0.12" resolved "https://registry.yarnpkg.com/immer/-/immer-9.0.12.tgz#2d33ddf3ee1d247deab9d707ca472c8c942a0f20" @@ -5219,6 +5354,16 @@ lru-cache@^6.0.0: dependencies: yallist "^4.0.0" +lunr-languages@^1.4.0: + version "1.9.0" + resolved "https://registry.yarnpkg.com/lunr-languages/-/lunr-languages-1.9.0.tgz#7105230807788a112a69910561b7bbd055a0e588" + integrity sha512-Be5vFuc8NAheOIjviCRms3ZqFFBlzns3u9DXpPSZvALetgnydAN0poV71pVLFn0keYy/s4VblMMkqewTLe+KPg== + +lunr@^2.3.8: + version "2.3.9" + resolved "https://registry.yarnpkg.com/lunr/-/lunr-2.3.9.tgz#18b123142832337dd6e964df1a5a7707b25d35e1" + integrity sha512-zTU3DaZaF3Rt9rhN3uBMGQD3dD2/vFQqnvZCDv4dl5iOzq2IZQqTxu90r4E5J+nP70J3ilqVCrbho2eWaeW8Ow== + magic-string@^0.25.3: version "0.25.7" resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.25.7.tgz#3f497d6fd34c669c6798dcb821f2ef31f5445051" @@ -5414,6 +5559,11 @@ mj-context-menu@^0.6.1: resolved "https://registry.yarnpkg.com/mj-context-menu/-/mj-context-menu-0.6.1.tgz#a043c5282bf7e1cf3821de07b13525ca6f85aa69" integrity sha512-7NO5s6n10TIV96d4g2uDpG7ZDpIhMh0QNfGdJw/W47JswFcosz457wqz/b5sAKvl12sxINGFCn80NZHKwxQEXA== +mkdirp@0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.3.0.tgz#1bbf5ab1ba827af23575143490426455f481fe1e" + integrity sha1-G79asbqCevI1dRQ0kEJkVfSB/h4= + mkdirp@^0.5.5: version "0.5.5" resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.5.tgz#d91cefd62d1436ca0f41620e251288d420099def" @@ -5499,6 +5649,13 @@ node-releases@^2.0.1: resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.1.tgz#3d1d395f204f1f2f29a54358b9fb678765ad2fc5" integrity sha512-CqyzN6z7Q6aMeF/ktcMVTzhAHCEpf8SOarwpzpf8pNBY2k5/oM34UHldUwp8VKI7uxct2HxSRdJjBaZeESzcxA== +nopt@1.0.10: + version "1.0.10" + resolved "https://registry.yarnpkg.com/nopt/-/nopt-1.0.10.tgz#6ddd21bd2a31417b92727dd585f8a6f37608ebee" + integrity sha1-bd0hvSoxQXuScn3Vhfim83YI6+4= + dependencies: + abbrev "1" + normalize-path@^3.0.0, normalize-path@~3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" @@ -5519,6 +5676,11 @@ normalize-url@^6.0.1: resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-6.1.0.tgz#40d0885b535deffe3f3147bec877d05fe4c5668a" integrity sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A== +not@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/not/-/not-0.1.0.tgz#c9691c1746c55dcfbe54cbd8bd4ff041bc2b519d" + integrity sha1-yWkcF0bFXc++VMvYvU/wQbwrUZ0= + npm-run-path@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-4.0.1.tgz#b7ecd1e5ed53da8e37a55e1c2269e0b97ed748ea" @@ -5531,7 +5693,7 @@ nprogress@^0.2.0: resolved "https://registry.yarnpkg.com/nprogress/-/nprogress-0.2.0.tgz#cb8f34c53213d895723fcbab907e9422adbcafb1" integrity sha1-y480xTIT2JVyP8urkH6UIq28r7E= -nth-check@^2.0.1: +nth-check@^2.0.0, nth-check@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/nth-check/-/nth-check-2.0.1.tgz#2efe162f5c3da06a28959fbd3db75dbeea9f0fc2" integrity sha512-it1vE95zF6dTT9lBsYbxvqh0Soy4SPowchj0UBGj/V6cTPnXXtQOPUbhZ6CmGzAD/rW22LQK6E96pcdJXk4A4w== @@ -6643,7 +6805,7 @@ rehype-parse@^6.0.2: parse5 "^5.0.0" xtend "^4.0.0" -rehype-parse@^7.0.0: +rehype-parse@^7.0.0, rehype-parse@^7.0.1: version "7.0.1" resolved "https://registry.yarnpkg.com/rehype-parse/-/rehype-parse-7.0.1.tgz#58900f6702b56767814afc2a9efa2d42b1c90c57" integrity sha512-fOiR9a9xH+Le19i4fGzIEowAbwG7idy2Jzs4mOrFWBSJ0sNUgy0ev871dwWnbOo371SjgjG4pwzrbgSVrKxecw== @@ -7076,6 +7238,11 @@ shelljs@^0.8.4: interpret "^1.0.0" rechoir "^0.6.2" +signal-exit@^3.0.0: + version "3.0.7" + resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9" + integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== + signal-exit@^3.0.2, signal-exit@^3.0.3: version "3.0.6" resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.6.tgz#24e630c4b0f03fea446a2bd299e62b4a6ca8d0af" @@ -7234,7 +7401,7 @@ std-env@^3.0.1: resolved "https://registry.yarnpkg.com/std-env/-/std-env-3.0.1.tgz#bc4cbc0e438610197e34c2d79c3df30b491f5182" integrity sha512-mC1Ps9l77/97qeOZc+HrOL7TIaOboHqMZ24dGVQrlxFcpPpfCHpH+qfUT7Dz+6mlG8+JPA1KfBQo19iC/+Ngcw== -string-width@^4.0.0, string-width@^4.1.0, string-width@^4.2.2: +"string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.0.0, string-width@^4.1.0, string-width@^4.2.2, string-width@^4.2.3: version "4.2.3" resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== @@ -7436,6 +7603,14 @@ to-regex-range@^5.0.1: dependencies: is-number "^7.0.0" +to-vfile@^6.1.0: + version "6.1.0" + resolved "https://registry.yarnpkg.com/to-vfile/-/to-vfile-6.1.0.tgz#5f7a3f65813c2c4e34ee1f7643a5646344627699" + integrity sha512-BxX8EkCxOAZe+D/ToHdDsJcVI4HqQfmw0tCkp31zf3dNP/XWIAjU4CmeuSwsSoOzOTqHPOL0KUzyZqJplkD0Qw== + dependencies: + is-buffer "^2.0.0" + vfile "^4.0.0" + toidentifier@1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.1.tgz#3be34321a88a820ed1bd80dfaa33e479fbb8dd35" @@ -7630,7 +7805,7 @@ unist-util-generated@^1.0.0: resolved "https://registry.yarnpkg.com/unist-util-generated/-/unist-util-generated-1.1.6.tgz#5ab51f689e2992a472beb1b35f2ce7ff2f324d4b" integrity sha512-cln2Mm1/CZzN5ttGK7vkoGw+RZ8VcUH6BtGbq98DDtRGquAAOXig1mrBQYelOwMXYS8rK+vZDyyojSjp7JX+Lg== -unist-util-is@^4.0.0: +unist-util-is@^4.0.0, unist-util-is@^4.0.2: version "4.1.0" resolved "https://registry.yarnpkg.com/unist-util-is/-/unist-util-is-4.1.0.tgz#976e5f462a7a5de73d94b706bac1b90671b57797" integrity sha512-ZOQSsnce92GrxSqlnEEseX0gi7GH9zTJZ0p9dtu87WRb/37mMPO2Ilx1s/t9vBHrFhbgweUwb+t7cIn5dxPhZg== @@ -8103,6 +8278,13 @@ wicked-good-xpath@^1.3.0: resolved "https://registry.yarnpkg.com/wicked-good-xpath/-/wicked-good-xpath-1.3.0.tgz#81b0e95e8650e49c94b22298fff8686b5553cf6c" integrity sha1-gbDpXoZQ5JyUsiKY//hoa1VTz2w= +wide-align@^1.1.2: + version "1.1.5" + resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.5.tgz#df1d4c206854369ecf3c9a4898f1b23fbd9d15d3" + integrity sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg== + dependencies: + string-width "^1.0.2 || 2 || 3 || 4" + widest-line@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/widest-line/-/widest-line-3.1.0.tgz#8292333bbf66cb45ff0de1603b136b7ae1496eca" From e574d07bb66a8a52ae6e13916b6bb11945ba8cd8 Mon Sep 17 00:00:00 2001 From: Jay Logelin Date: Mon, 21 Mar 2022 13:17:34 -0300 Subject: [PATCH 006/150] Initial shot at NEP-1: (#333) * Initial shot at NEP-1: NEP Purpose and Guidelines with restructured directory and restructured sample implementation NEP-141 * added NEP process state to NEP-1 * updated DiscussionsTo header value to point to PR * formatting * Update nep-0001.md (#334) * backported existing standards to new format Co-authored-by: Benjamin Kurrek <57506486+BenKurrek@users.noreply.github.com> --- README.md | 17 + 0000-template.md => nep-0000-template.md | 58 +-- neps/assets/nep-0001/NEP-states.png | Bin 0 -> 11042 bytes neps/nep-0001.md | 399 +++++++++++++++++++ neps/nep-0021.md | 230 +++++++++++ neps/nep-0141.md | 470 ++++++++++++++++++++++ neps/nep-0145.md | 454 ++++++++++++++++++++++ neps/nep-0148.md | 121 ++++++ neps/nep-0171.md | 376 ++++++++++++++++++ neps/nep-0177.md | 154 ++++++++ neps/nep-0178.md | 471 +++++++++++++++++++++++ neps/nep-0181.md | 96 +++++ neps/nep-0199.md | 117 ++++++ neps/nep-0297.md | 139 +++++++ 14 files changed, 3077 insertions(+), 25 deletions(-) rename 0000-template.md => nep-0000-template.md (70%) create mode 100644 neps/assets/nep-0001/NEP-states.png create mode 100644 neps/nep-0001.md create mode 100644 neps/nep-0021.md create mode 100644 neps/nep-0141.md create mode 100644 neps/nep-0145.md create mode 100644 neps/nep-0148.md create mode 100644 neps/nep-0171.md create mode 100644 neps/nep-0177.md create mode 100644 neps/nep-0178.md create mode 100644 neps/nep-0181.md create mode 100644 neps/nep-0199.md create mode 100644 neps/nep-0297.md diff --git a/README.md b/README.md index c7df70e60..69e289b48 100644 --- a/README.md +++ b/README.md @@ -78,3 +78,20 @@ Tip: build consensus and integrate feedback. NEPs that have broad support are mu 3. Observe those changes reflected in the local docs 4. Submit a pull request with your changes + + +## NEPs + +|NEP # | Title | Author | Status | +|---|---|---|---| +|[0001](https://github.com/near/NEPs/blob/master/neps/nep-0001.md) | FIP Purpose and Guidelines | @jlogelin | Active | +|[0021](https://github.com/near/NEPs/blob/master/neps/nep-0021.md) | Fungible Token Standard (Deprecated) | @aevgenykuzyakov | Final | +|[0141](https://github.com/near/NEPs/blob/master/neps/nep-0141.md) | Fungible Token Standard | @aevgenykuzyakov @oysterpack | Final | +|[0145](https://github.com/near/NEPs/blob/master/neps/nep-0145.md) | Storage Management | @aevgenykuzyakov | Final | +|[0148](https://github.com/near/NEPs/blob/master/neps/nep-0148.md) | Fungible Token Metadata | @robert-zaremba @aevgenykuzyakov @oysterpack | Final | +|[0171](https://github.com/near/NEPs/blob/master/neps/nep-0171.md) | Non Fungible Token Standard | @mikedotexe @aevgenykuzyakov @oysterpack | Final | +|[0177](https://github.com/near/NEPs/blob/master/neps/nep-0177.md) | Non Fungible Token Metadata | @chadoh @mikedotexe | Final | +|[0178](https://github.com/near/NEPs/blob/master/neps/nep-0178.md) | Non Fungible Token Approval Management | @chadoh @thor314 | Final | +|[0181](https://github.com/near/NEPs/blob/master/neps/nep-0181.md) | Non Fungible Token Enumeration | @chadoh @thor314 | Final | +|[0199](https://github.com/near/NEPs/blob/master/neps/nep-0199.md) | Non Fungible Token Royalties and Payouts | @thor314 @mattlockyer | Final | +|[0297](https://github.com/near/NEPs/blob/master/neps/nep-0297.md) | Non Fungible Token Royalties and Payouts | @telezhnaya | Final | diff --git a/0000-template.md b/nep-0000-template.md similarity index 70% rename from 0000-template.md rename to nep-0000-template.md index c85193bbf..2d8c051a1 100644 --- a/0000-template.md +++ b/nep-0000-template.md @@ -1,20 +1,29 @@ -- Proposal Name: (fill me in with a unique ident, `my_awesome_feature`) -- Start Date: (fill me in with today's date, YYYY-MM-DD) -- NEP PR: [nearprotocol/neps#0000](https://github.com/nearprotocol/neps/pull/0000) -- Issue(s): link to relevant issues in relevant repos (not required). - -# Summary -[summary]: #summary +--- +NEP: 0 +Title: NEP Purpose and Guidelines +Author: Todd Codrington III +DiscussionsTo: https://github.com/nearprotocol/neps/pull/0000 +Status: Draft +Type: Standards Track +Category: Contract +Created: 03-Mar-2022 +--- + +## Summary One paragraph explanation of the proposal. -# Motivation -[motivation]: #motivation +## Motivation Why are we doing this? What use cases does it support? What is the expected outcome? -# Guide-level explanation -[guide-level-explanation]: #guide-level-explanation +## Rationale and alternatives + +- Why is this design the best in the space of possible designs? +- What other designs have been considered and what is the rationale for not choosing them? +- What is the impact of not doing this? + +## Specification Explain the proposal as if it was already implemented and you were teaching it to another developer. That generally means: @@ -25,38 +34,32 @@ Explain the proposal as if it was already implemented and you were teaching it t For user-facing NEPs this section should focus on user stories. -# Reference-level explanation -[reference-level-explanation]: #reference-level-explanation +## Reference Implementation This is the technical portion of the NEP. Explain the design in sufficient detail that: - Its interaction with other features is clear. +- Where possible, include a `Minimum Viable Interface` subsection expressing the required behavior and types in a target Near Contract language. (ie. traits and structs for rust, interfaces and classes for javascript, function signatures and structs for c, etc.) - It is reasonably clear how the feature would be implemented. - Corner cases are dissected by example. The section should return to the examples given in the previous section, and explain more fully how the detailed proposal makes those examples work. -# Drawbacks -[drawbacks]: #drawbacks +## Security Implications (Optional) -Why should we *not* do this? +If there are security concerns in relation to the NEP, those concerns should be explicitly written out to make sure reviewers of the NEP are aware of them. -# Rationale and alternatives -[rationale-and-alternatives]: #rationale-and-alternatives +## Drawbacks (Optional) -- Why is this design the best in the space of possible designs? -- What other designs have been considered and what is the rationale for not choosing them? -- What is the impact of not doing this? +Why should we *not* do this? -# Unresolved questions -[unresolved-questions]: #unresolved-questions +## Unresolved Issues (Optional) - What parts of the design do you expect to resolve through the NEP process before this gets merged? - What parts of the design do you expect to resolve through the implementation of this feature before stabilization? - What related issues do you consider out of scope for this NEP that could be addressed in the future independently of the solution that comes out of this NEP? -# Future possibilities -[future-possibilities]: #future-possibilities +## Future possibilities Think about what the natural extension and evolution of your proposal would be and how it would affect the project as a whole in a holistic @@ -75,3 +78,8 @@ Note that having something written down in the future-possibilities section is not a reason to accept the current or a future NEP. Such notes should be in the section on motivation or rationale in this or subsequent NEPs. The section merely provides additional information. + +## Copyright +[copyright]: #copyright + +Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). \ No newline at end of file diff --git a/neps/assets/nep-0001/NEP-states.png b/neps/assets/nep-0001/NEP-states.png new file mode 100644 index 0000000000000000000000000000000000000000..6ad781bbc4bd3e279234af4ebdd11fcebe2d8302 GIT binary patch literal 11042 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 +DiscussionsTo: https://github.com/near/NEPs/pull/333 +Status: Active +Type: Process +Created: 03-Mar-2022 +--- + +## What is an NEP? + +NEP stands for Near Enhancement Proposal. An NEP is a design +document providing information to the Near community, or describing +a new feature for the Near protocol, Smart Contract standards, or it's environment. +The NEP should provide a concise technical specification of the feature and a +rationale for the feature. + +NEPs are intented to be the primary mechanism for proposing new features, interfacing +with the community on an issue and documenting design decisions that have +been integrated into Near's runtime or Smart Contract ecosystem. + +As such, the NEP author is responsible for building consensus within the community and documenting dissenting opinions. + +## NEP Audience + +The typical primary audience for NEPs are the core developers of the Near +reference implementations, and Near Smart Contract developers. + +However, other parts of the Near community may also choose to use the process +(particularly for Informational NEPs) to document expected API conventions and +to manage complex design coordination problems that require collaboration across +multiple projects. + +## NEP Types + +There are three kinds of NEP: + +1. A **Standards Track** NEP describes a new feature or implementation + for the Near protocol or Near Smart Contract implementation standards. + +2. An **Informational** NEP describes a Near design issue, or + provides general guidelines or information to the Near community, + but does not propose a new feature. Informational NEPs do not + necessarily represent a Near community consensus or + recommendation, so users and implementers can ignore + Informational NEPs or follow their advice. + +3. A **Process** NEP describes a process surrounding Near, or + proposes a change to (or an event in) a process. Process NEPs are + like Standards Track NEPs but apply to areas other than the Near + platform itself. They may propose an implementation, but not to + Near's codebase; they often require community consensus; unlike + Informational NEPs, they are more than recommendations, and users + are typically not free to ignore them. Examples include + procedures, guidelines, changes to the decision-making process, and + changes to the tools or environment used in Near development. + Any meta-NEP is also considered a Process NEP. + +## NEP Workflow + +### Start with an idea for Near + +The NEP process begins with a new idea for the Near ecosystem. It is +recommended that a single NEP contain a single key proposal or new +idea. + +Each NEP must have a torch-bearer: someone who writes the NEP using the style +and format described below, shepherds the discussions in the appropriate +forums, and attempts to build community consensus around the idea. This NEP Author +should first attempt to ascertain whether the idea is +NEP-able. + +Vetting an idea publicly before going as far as writing an NEP is meant +to save the potential author time. Many ideas have been brought +forward for changing Near that have been rejected for various +reasons. Asking the Near community first if an idea is original +helps prevent too much time being spent on something that is +guaranteed to be rejected based on prior discussions. It also helps to make sure +the idea is applicable to the entire community and not just the author. +Just because an idea sounds good to the author does not +mean it will work for most people in most areas where Near is used. + +In general the process is: + +* Sign up for the [governance site](https://gov.near.org/) and make a post to the +appropriate section. For instance, during the ideation phase of a standard, one might +start a new conversation in the +[Development » Standards section](https://gov.near.org/c/dev/standards/29). +The other suggested category in the governance forum is the +[Development » Proposals section](https://gov.near.org/c/dev/proposals/68). + +* The forum has comment threading which allows the community and NEAR Collective +to ideate, ask questions, wrestle with approaches, etc. If more immediate responses +are desired, consider bringing the conversation [to Discord](https://near.chat). + +Once the torch-bearer has asked the Near community as to whether an +idea has any chance of acceptance, a draft NEP should be presented to +the appropriate venue mentioned above. This gives the author a chance to flesh out the draft +NEP to make properly formatted, of high quality, and to address +initial concerns about the proposal. + + +## Submitting an NEP + +Following the above initial discussions, the workflow, the proposal should be +submitted as a `draft` NEP via a GitHub pull request. The draft must be written +in NEP style as described below, else it will fail review immediately (although +minor errors may be corrected by the editors). + +The standard NEP workflow is: + +* You, the NEP author, fork the `NEPs repository`, and create a file named + ``neps/nep-9999.md`` that contains your new NEP. Use "9999" as your draft NEP + number. + +* Your first update will be to change the nep filename to match the Pull Request + number. For example, if the PR is `305`, the NEP should be `neps/nep-0305.md`. + +* In the "Type:" header field, enter "Standards Track", + "Informational", or "Process" as appropriate, and for the "Status:" + field enter "Draft". For full details, see `NEP Header Preamble`. + +* Push this to your GitHub fork and submit a pull request. + +* The NEP editors review your PR for structure, formatting, and other + errors. For a markdown-formatted NEP, `nep-template.md` is provided as a template. + Approval criteria are: + + * It is sound and complete. The ideas must make technical sense. The + editors do not consider whether they seem likely to be accepted. + * The title accurately describes the content. + * The NEP's language (spelling, grammar, sentence structure, etc.) + and code style should be correct and conformant. + + If the NEP isn't ready for approval, an editor will send it back to + the author for revision, with specific instructions in the pull request. + +Once the review process is complete, and the NEP editors approve it (note that +this is *not* the same as accepting your NEP!), they will squash commit your +pull request onto main. + +The NEP editors will not unreasonably deny publication of an NEP. Reasons for +denying NEP status include duplication of effort, being technically unsound, +not providing proper motivation or addressing backwards compatibility, or not +in keeping with the NEAR philosophy. + +As updates are necessary, the NEP author can check in new versions if they +(or a collaborating developer) have write access to the `NEP repository`. + +Standards Track NEPs consist of two parts, a design document and a +reference implementation. It is generally recommended that at least a +prototype implementation be co-developed with the NEP, as ideas that sound +good in principle sometimes turn out to be impractical when subjected to the +test of implementation. + +## NEP Maintenance + +Informational and Process NEPs may be updated over time to reflect changes to +development practices and other details. The precise process followed in these +cases will depend on the nature and purpose of the NEP being updated. In general, +Standards track NEP's are no longer modified after they have reached the Final state. + +## NEP Process State + +The following is the standardization process for all NEPs in all tracks: + +![NEP Status Diagram](assets/nep-0001/NEP-states.png) + +**Idea** - An idea that is pre-draft. This is not tracked within the NEP Repository. + +**Draft** - The first formally tracked stage of an NEP in development. An NEP is merged by an NEP Editor into the NEP repository when properly formatted. + +**Review** - An NEP Author marks an NEP as ready for and requesting Peer Review. + +**Last Call** - This is the final review window for an NEP before moving to `Final`. An NEP editor will assign `Last Call` status and set a review end date (`last-call-deadline`), typically 14 days later. + +If this period results in necessary normative changes it will revert the NEP to `Review`. + +**Final** - This NEP represents the final standard. A Final NEP exists in a state of finality and should only be updated to correct errata and add non-normative clarifications. + +**Living** - A special status for NEPs that are designed to be continually updated and not reach a state of finality. This includes most notably NEP-0001. + +## What does a successful NEP look like? + +Each NEP should have the following parts/sections: + +1. Preamble - [RFC 822](https://www.ietf.org/rfc/rfc822.txt) style headers + containing meta-data about the NEP, including the NEP number, a short descriptive + title, the names, and optionally the contact info for each author, etc. + +2. Summary - a short (~200 word) description of the technical issue being addressed. + +3. Motivation - The motivation section should + clearly explain why the existing contract ecosystem is + inadequate to address the problem that the NEP solves. This can + include collecting documented support for the NEP from important + projects in the Near ecosystem. NEP submissions without + sufficient motivation may be rejected. + +4. Rationale and alternatives - The rationale fleshes out the specification by + describing why particular design decisions were made. It should + describe alternate designs that were considered and related work, + e.g. how the feature is supported in other platforms. + +5. Specification - The technical specification should describe the + syntax and semantics of the contract or protocol feature. The + specification should be detailed enough to allow competing, + interoperable implementations for at least the current major Near + version. + +6. Reference Implementation - The reference implementation must be + completed before any Standards Track NEP is given status "Final", + but it need not be completed before the NEP is accepted. While + there is merit to the approach of reaching consensus on the + specification and rationale before writing code, the principle of + "rough consensus and running code" is still useful when it comes + to resolving many discussions of API details. + + The final implementation must include test code and documentation + appropriate in a Near-compatible contract language. + + Appropriate judgement should be used when defining the reference + implementation, which can be included inline or reference an + external github repository. + + Where possible, include a `Minimum Viable Interface` expressing the + required behavior and types in a target Near Contract language. + (ie. traits and structs for rust, interfaces and classes for javascript, + function signatures and structs for c, etc.) Expressions of such + interfaces helps define the link between contract standardization + and implementation. + +7. Security Implications - If there are security concerns in relation + to the NEP, those concerns should be explicitly written out to make + sure reviewers of the NEP are aware of them. + +8. Drawbacks - Throughout the discussion of an NEP, various ideas + will be proposed which are not accepted. Those rejected ideas should + be recorded along with the reasoning as to why they were rejected. + This both helps record the thought process behind the final version + of the NEP as well as preventing people from bringing up the same + rejected idea again in subsequent discussions. + + In a way this section can be thought of as a breakout section of the + Rationale section that is focused specifically on why certain ideas + were not ultimately pursued. + +9. Unresolved Issues - While an NEP is in draft, ideas can come up which + warrant further discussion. Those ideas should be recorded so people + know that they are being thought about but do not have a concrete + resolution. This helps make sure all issues required for the NEP to be + ready for consideration are complete and reduces people duplicating + prior discussion. + +10. Future possibilities - Future possibilities describes any natural extensions + and evolutions to the NEP proposal and how it would affect the project. + Try to use this section as a tool to more fully consider all possible + interactions with the project in your proposal. + Also consider how the this all fits into the roadmap for the project + and of the relevant sub-teams. + +11. Copyright Waiver - All NEPs must be in the public domain. See the bottom + of this NEP for an example copyright waiver. + + +## NEP Header Preamble + +Each NEP must begin with an [RFC 822](https://www.ietf.org/rfc/rfc822.txt) style +header preamble. The headers must appear in the following order. + +``` + NEP: + Title: + Author: + DiscussionsTo: + Status: + Type: + Category: if Type is "Standards Track" one of + Requires (Optional): + Replaces (Optional): + SupersededBy (Optional): + Created: +``` + +`Title`: The NEP title header should not be more than 4-5 words, describing + +`Author`: The Author header lists the names, and optionally the email addresses +of all the authors/owners of the NEP. The format of the Author header +value must be + + Random J. User + +if the email address is included, and just + + Random J. User + +If there are multiple authors, each should be on a separate line +following [RFC 822](https://www.ietf.org/rfc/rfc822.txt) continuation line conventions. + +`DiscussionsTo`: The DiscussionsTo header provides the URL to the current +canonical discussion thread for the NEP. + +`Type`: The Type header specifies the type of NEP: Standards Track, +Informational, or Process. + +`Category`: The Category header only exists iff the Type header is `Standards Track`, +one of Protocol or Contract. + +`Created`: The Created header records the date that the NEP was assigned a +number, should be in dd-mmm-yyyy format, e.g. 03-Mar-2022. + +`Requires`: NEPs may have a Requires header, indicating the NEP numbers that this +NEP depends on. + +`SupersededBy`: NEPs may also have a SupersededBy header indicating that an NEP has +been rendered obsolete by a later document; the value is the number of +the NEP that replaces the current document. + +`Replaces`: A newer NEP marked with a SupercededBy header must have a Replaces header +containing the number of the NEP that it rendered obsolete. + +## Auxiliary Files + +Images, diagrams and auxiliary files should be included in a subdirectory of the assets +folder for that NEP as follows: `assets/nep-N` (where N is to be replaced with the NEP number). +When linking to an image in the NEP, use relative links such as ../assets/nep-1/image.png + +## Transferring NEP Ownership + +It occasionally becomes necessary to transfer ownership of NEPs to a +new torch-bearer. In general, it is preferable to retain the original author as +a co-author of the transferred NEP, but that's really up to the +original author. A good reason to transfer ownership is because the +original author no longer has the time or interest in updating it or +following through with the NEP process. A bad +reason to transfer ownership is because the author doesn't agree with the +direction of the NEP. One aim of the NEP process is to try to build +consensus around an NEP, but if that's not possible, an author can +submit a competing NEP. + +If you are interested in assuming ownership of an NEP, you can also do this via +pull request. Fork the `NEP repository`, make your ownership modification, +and submit a pull request. You should mention both the original author and +``@Near/NEP-editors`` in a comment on the pull request. + +## NEP Editors + +The current NEP Editors are: + * TBD + +## NEP Editor Responsibilities & Workflow + +Note that developers with write access to the `NEP repository` may +handle the tasks that would normally be taken care of by the NEP editors. + +For each new NEP that comes in, an editor does the following: + +* Read the NEP to check if it is ready: sound and complete. The ideas must make +technical sense, even if they don't seem likely to get to final status. +* The title should accurately describe the content. +* Check the NEP for language (spelling, grammar, sentence structure, etc.), markup +(GitHub flavored Markdown), code style + +Several NEPs are written and maintained by developers with write access +to the Near codebase. The NEP editors monitor the NEP repository +for changes, and correct any structure, grammar, spelling, or +markup mistakes they see. + +NEP editors don't pass philosophical judgment on NEPs. They merely do the +administrative & editorial part. + +## Style Guide + +#### NEP numbers + +When referring to an NEP by number, it should be written in the hyphenated +form `NEP-X` where `X` is the NEP's assigned number. + +#### RFC 2119 + +NEPs are encouraged to follow [RFC 2119](https://www.ietf.org/rfc/rfc2119.txt) for +terminology and to insert the following at the beginning of the Specification section: + +> The key words “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “MAY”, and “OPTIONAL” in this document are to be interpreted as described in RFC 2119. + +## References + +The content of this document was derived heavily from the PEP, BIP, Rust RFC +and EIP standards boostrap documents: + +* Klock, F et al. Rust: RFC-0002: RFC Process. https://github.com/rust-lang/rfcs/blob/master/text/0002-rfc-process.md +* Taaki, A. et al. Bitcoin Improvement Proposal: BIP:1, BIP Purpose and Guidelines. https://github.com/bitcoin/bips/blob/master/bip-0001.mediawiki +* Warsaw, B. et al. Python Enhancement Proposal: PEP Purpose and Guidelines. https://github.com/python/peps/blob/main/pep-0001.txt +* Becze, M. et al. Ethereum Improvement Proposal EIP1: EIP Purpose and Guidelines. https://github.com/ethereum/EIPs/blob/master/EIPS/eip-1.md + +## Copyright + +Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). diff --git a/neps/nep-0021.md b/neps/nep-0021.md new file mode 100644 index 000000000..45dc7bc13 --- /dev/null +++ b/neps/nep-0021.md @@ -0,0 +1,230 @@ +--- +NEP: 21 +Title: Fungible Token Standard +Author: Evgeny Kuzyakov +DiscussionsTo: https://github.com/near/NEPs/pull/21 +Status: Final +Type: Standards Track +Category: Contract +Created: 29-Oct-2019 +SupersededBy: 141 +--- + +## Summary + +A standard interface for fungible tokens allowing for ownership, escrow and transfer, specifically targeting third-party marketplace integration. + +## Motivation + +NEAR Protocol uses an asynchronous sharded Runtime. This means the following: + +Storage for different contracts and accounts can be located on the different shards. +Two contracts can be executed at the same time in different shards. +While this increases the transaction throughput linearly with the number of shards, it also creates some challenges for cross-contract development. +For example, if one contract wants to query some information from the state of another contract (e.g. current balance), by the time the first contract receive the balance the real balance can change. +It means in the async system, a contract can't rely on the state of other contract and assume it's not going to change. + +Instead the contract can rely on temporary partial lock of the state with a callback to act or unlock, but it requires careful engineering to avoid dead locks. + +## Rationale and alternatives + +In this standard we're trying to avoid enforcing locks, since most actions can still be completed without locks by transferring ownership to an escrow account. + +Prior art: + +ERC-20 standard +NEP#4 NEAR NFT standard: nearprotocol/neps#4 +For latest lock proposals see Safes (#26) + +## Specification + +We should be able to do the following: +- Initialize contract once. The given total supply will be owned by the given account ID. +- Get the total supply. +- Transfer tokens to a new user. +- Set a given allowance for an escrow account ID. + - Escrow will be able to transfer up this allowance from your account. + - Get current balance for a given account ID. +- Transfer tokens from one user to another. +- Get the current allowance for an escrow account on behalf of the balance owner. This should only be used in the UI, since a contract shouldn't rely on this temporary information. + +There are a few concepts in the scenarios above: +- **Total supply**. It's the total number of tokens in circulation. +- **Balance owner**. An account ID that owns some amount of tokens. +- **Balance**. Some amount of tokens. +- **Transfer**. Action that moves some amount from one account to another account. +- **Escrow**. A different account from the balance owner who has permission to use some amount of tokens. +- **Allowance**. The amount of tokens an escrow account can use on behalf of the account owner. + +Note, that the precision is not part of the default standard, since it's not required to perform actions. The minimum +value is always 1 token. + +### Simple transfer + +Alice wants to send 5 wBTC tokens to Bob. + +**Assumptions** + +- The wBTC token contract is `wbtc`. +- Alice's account is `alice`. +- Bob's account is `bob`. +- The precision on wBTC contract is `10^8`. +- The 5 tokens is `5 * 10^8` or as a number is `500000000`. + +**High-level explanation** + +Alice needs to issue one transaction to wBTC contract to transfer 5 tokens (multiplied by precision) to Bob. + +**Technical calls** + +1. `alice` calls `wbtc::transfer({"new_owner_id": "bob", "amount": "500000000"})`. + +### Token deposit to a contract + +Alice wants to deposit 1000 DAI tokens to a compound interest contract to earn extra tokens. + +**Assumptions** + +- The DAI token contract is `dai`. +- Alice's account is `alice`. +- The compound interest contract is `compound`. +- The precision on DAI contract is `10^18`. +- The 1000 tokens is `1000 * 10^18` or as a number is `1000000000000000000000`. +- The compound contract can work with multiple token types. + +**High-level explanation** + +Alice needs to issue 2 transactions. The first one to `dai` to set an allowance for `compound` to be able to withdraw tokens from `alice`. +The second transaction is to the `compound` to start the deposit process. Compound will check that the DAI tokens are supported and will try to withdraw the desired amount of DAI from `alice`. +- If transfer succeeded, `compound` can increase local ownership for `alice` to 1000 DAI +- If transfer fails, `compound` doesn't need to do anything in current example, but maybe can notify `alice` of unsuccessful transfer. + +**Technical calls** + +1. `alice` calls `dai::set_allowance({"escrow_account_id": "compound", "allowance": "1000000000000000000000"})`. +1. `alice` calls `compound::deposit({"token_contract": "dai", "amount": "1000000000000000000000"})`. During the `deposit` call, `compound` does the following: + 1. makes async call `dai::transfer_from({"owner_id": "alice", "new_owner_id": "compound", "amount": "1000000000000000000000"})`. + 1. attaches a callback `compound::on_transfer({"owner_id": "alice", "token_contract": "dai", "amount": "1000000000000000000000"})`. + +### Multi-token swap on DEX + +Charlie wants to exchange his wLTC to wBTC on decentralized exchange contract. Alex wants to buy wLTC and has 80 wBTC. + +**Assumptions** + +- The wLTC token contract is `wltc`. +- The wBTC token contract is `wbtc`. +- The DEX contract is `dex`. +- Charlie's account is `charlie`. +- Alex's account is `alex`. +- The precision on both tokens contract is `10^8`. +- The amount of 9001 wLTC tokens is Alex wants is `9001 * 10^8` or as a number is `900100000000`. +- The 80 wBTC tokens is `80 * 10^8` or as a number is `8000000000`. +- Charlie has 1000000 wLTC tokens which is `1000000 * 10^8` or as a number is `100000000000000` +- Dex contract already has an open order to sell 80 wBTC tokens by `alex` towards 9001 wLTC. +- Without Safes implementation, DEX has to act as an escrow and hold funds of both users before it can do an exchange. + +**High-level explanation** + +Let's first setup open order by Alex on DEX. It's similar to `Token deposit to a contract` example above. +- Alex sets an allowance on wBTC to DEX +- Alex calls deposit on Dex for wBTC. +- Alex calls DEX to make an new sell order. + +Then Charlie comes and decides to fulfill the order by selling his wLTC to Alex on DEX. +Charlie calls the DEX +- Charlie sets the allowance on wLTC to DEX +- Alex calls deposit on Dex for wLTC. +- Then calls DEX to take the order from Alex. + +When called, DEX makes 2 async transfers calls to exchange corresponding tokens. +- DEX calls wLTC to transfer tokens DEX to Alex. +- DEX calls wBTC to transfer tokens DEX to Charlie. + +**Technical calls** + +1. `alex` calls `wbtc::set_allowance({"escrow_account_id": "dex", "allowance": "8000000000"})`. +1. `alex` calls `dex::deposit({"token": "wbtc", "amount": "8000000000"})`. + 1. `dex` calls `wbtc::transfer_from({"owner_id": "alex", "new_owner_id": "dex", "amount": "8000000000"})` +1. `alex` calls `dex::trade({"have": "wbtc", "have_amount": "8000000000", "want": "wltc", "want_amount": "900100000000"})`. +1. `charlie` calls `wltc::set_allowance({"escrow_account_id": "dex", "allowance": "100000000000000"})`. +1. `charlie` calls `dex::deposit({"token": "wltc", "amount": "100000000000000"})`. + 1. `dex` calls `wltc::transfer_from({"owner_id": "charlie", "new_owner_id": "dex", "amount": "100000000000000"})` +1. `charlie` calls `dex::trade({"have": "wltc", "have_amount": "900100000000", "want": "wbtc", "want_amount": "8000000000"})`. + - `dex` calls `wbtc::transfer({"new_owner_id": "charlie", "amount": "8000000000"})` + - `dex` calls `wltc::transfer({"new_owner_id": "alex", "amount": "900100000000"})` + +## Reference Implementation + +The full implementation in Rust can be found there: https://github.com/nearprotocol/near-sdk-rs/blob/master/examples/fungible-token/src/lib.rs + +**NOTES:** +- All amounts, balances and allowance are limited by U128 (max value `2**128 - 1`). +- Token standard uses JSON for serialization of arguments and results. +- Amounts in arguments and results have are serialized as Base-10 strings, e.g. `"100"`. This is done to avoid +JSON limitation of max integer value of `2**53`. + +Interface: + +```rust +/******************/ +/* CHANGE METHODS */ +/******************/ + +/// Sets the `allowance` for `escrow_account_id` on the account of the caller of this contract +/// (`predecessor_id`) who is the balance owner. +pub fn set_allowance(&mut self, escrow_account_id: AccountId, allowance: U128); + +/// Transfers the `amount` of tokens from `owner_id` to the `new_owner_id`. +/// Requirements: +/// * `amount` should be a positive integer. +/// * `owner_id` should have balance on the account greater or equal than the transfer `amount`. +/// * If this function is called by an escrow account (`owner_id != predecessor_account_id`), +/// then the allowance of the caller of the function (`predecessor_account_id`) on +/// the account of `owner_id` should be greater or equal than the transfer `amount`. +pub fn transfer_from(&mut self, owner_id: AccountId, new_owner_id: AccountId, amount: U128); + + +/// Transfer `amount` of tokens from the caller of the contract (`predecessor_id`) to +/// `new_owner_id`. +/// Act the same was as `transfer_from` with `owner_id` equal to the caller of the contract +/// (`predecessor_id`). +pub fn transfer(&mut self, new_owner_id: AccountId, amount: U128); + +/****************/ +/* VIEW METHODS */ +/****************/ + +/// Returns total supply of tokens. +pub fn get_total_supply(&self) -> U128; + +/// Returns balance of the `owner_id` account. +pub fn get_balance(&self, owner_id: AccountId) -> U128; + +/// Returns current allowance of `escrow_account_id` for the account of `owner_id`. +/// +/// NOTE: Other contracts should not rely on this information, because by the moment a contract +/// receives this information, the allowance may already be changed by the owner. +/// So this method should only be used on the front-end to see the current allowance. +pub fn get_allowance(&self, owner_id: AccountId, escrow_account_id: AccountId) -> U128; +``` +## Drawbacks +[drawbacks]: #drawbacks + +- Current interface doesn't have minting, precision (decimals), naming. But it should be done as extensions, e.g. a Precision extension. +- It's not possible to exchange tokens without transferring them to escrow first. +- It's not possible to transfer tokens to a contract with a single transaction without setting the allowance first. +It should be possible if we introduce `transfer_with` function that transfers tokens and calls escrow contract. It needs to handle result of the execution and contracts have to be aware of this API. + +## Future possibilities +[future-possibilities]: #future-possibilities + +- Support for multiple token types +- Minting and burning +- Precision, naming and short token name. + + +## Copyright +[copyright]: #copyright + +Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). \ No newline at end of file diff --git a/neps/nep-0141.md b/neps/nep-0141.md new file mode 100644 index 000000000..0aafb889d --- /dev/null +++ b/neps/nep-0141.md @@ -0,0 +1,470 @@ +--- +NEP: 141 +Title: Fungible Token Standard +Author: Evgeny Kuzyakov , @oysterpack +DiscussionsTo: https://github.com/near/NEPs/issues/141 +Status: Final +Type: Standards Track +Category: Contract +Created: 03-Mar-2022 +Replaces: 21 +Requires: 297 +--- + +## Summary + +A standard interface for fungible tokens that allows for a normal transfer as well as a transfer and method call in a single transaction. The [storage standard](../StorageManagement.md) addresses the needs (and security) of storage staking. +The [fungible token metadata standard](Metadata.md) provides the fields needed for ergonomics across dApps and marketplaces. + +## Motivation + +NEAR Protocol uses an asynchronous, sharded runtime. This means the following: + - Storage for different contracts and accounts can be located on the different shards. + - Two contracts can be executed at the same time in different shards. + +While this increases the transaction throughput linearly with the number of shards, it also creates some challenges for cross-contract development. For example, if one contract wants to query some information from the state of another contract (e.g. current balance), by the time the first contract receives the balance the real balance can change. In such an async system, a contract can't rely on the state of another contract and assume it's not going to change. + +Instead the contract can rely on temporary partial lock of the state with a callback to act or unlock, but it requires careful engineering to avoid deadlocks. In this standard we're trying to avoid enforcing locks. A typical approach to this problem is to include an escrow system with allowances. This approach was initially developed for [NEP-21](https://github.com/near/NEPs/pull/21) which is similar to the Ethereum ERC-20 standard. There are a few issues with using an escrow as the only avenue to pay for a service with a fungible token. This frequently requires more than one transaction for common scenarios where fungible tokens are given as payment with the expectation that a method will subsequently be called. + +For example, an oracle contract might be paid in fungible tokens. A client contract that wishes to use the oracle must either increase the escrow allowance before each request to the oracle contract, or allocate a large allowance that covers multiple calls. Both have drawbacks and ultimately it would be ideal to be able to send fungible tokens and call a method in a single transaction. This concern is addressed in the `ft_transfer_call` method. The power of this comes from the receiver contract working in concert with the fungible token contract in a secure way. That is, if the receiver contract abides by the standard, a single transaction may transfer and call a method. + +Note: there is no reason why an escrow system cannot be included in a fungible token's implementation, but it is simply not necessary in the core standard. Escrow logic should be moved to a separate contract to handle that functionality. One reason for this is because the [Rainbow Bridge](https://near.org/blog/eth-near-rainbow-bridge/) will be transferring fungible tokens from Ethereum to NEAR, where the token locker (a factory) will be using the fungible token core standard. + +Prior art: + +- [ERC-20 standard](https://eips.ethereum.org/EIPS/eip-20) +- NEP#4 NEAR NFT standard: [near/neps#4](https://github.com/near/neps/pull/4) + +Learn about NEP-141: + +- [Figment Learning Pathway](https://learn.figment.io/network-documentation/near/tutorials/1-project_overview/2-fungible-token) + +## Specification + +### Guide-level explanation + +We should be able to do the following: +- Initialize contract once. The given total supply will be owned by the given account ID. +- Get the total supply. +- Transfer tokens to a new user. +- Transfer tokens from one user to another. +- Transfer tokens to a contract, have the receiver contract call a method and "return" any fungible tokens not used. +- Remove state for the key/value pair corresponding with a user's account, withdrawing a nominal balance of Ⓝ that was used for storage. + +There are a few concepts in the scenarios above: +- **Total supply**: the total number of tokens in circulation. +- **Balance owner**: an account ID that owns some amount of tokens. +- **Balance**: an amount of tokens. +- **Transfer**: an action that moves some amount from one account to another account, either an externally owned account or a contract account. +- **Transfer and call**: an action that moves some amount from one account to a contract account where the receiver calls a method. +- **Storage amount**: the amount of storage used for an account to be "registered" in the fungible token. This amount is denominated in Ⓝ, not bytes, and represents the [storage staked](https://docs.near.org/docs/concepts/storage-staking). + +Note that precision (the number of decimal places supported by a given token) is not part of this core standard, since it's not required to perform actions. The minimum value is always 1 token. See the [Fungible Token Metadata Standard](Metadata.md) to learn how to support precision/decimals in a standardized way. + +Given that multiple users will use a Fungible Token contract, and their activity will result in an increased [storage staking](https://docs.near.org/docs/concepts/storage-staking) burden for the contract's account, this standard is designed to interoperate nicely with [the Account Storage standard](../StorageManagement.md) for storage deposits and refunds. + +#### Example scenarios + +##### Simple transfer + +Alice wants to send 5 wBTC tokens to Bob. + +**Assumptions** + +- The wBTC token contract is `wbtc`. +- Alice's account is `alice`. +- Bob's account is `bob`. +- The precision ("decimals" in the metadata standard) on wBTC contract is `10^8`. +- The 5 tokens is `5 * 10^8` or as a number is `500000000`. + +**High-level explanation** + +Alice needs to issue one transaction to wBTC contract to transfer 5 tokens (multiplied by precision) to Bob. + +**Technical calls** + +1. `alice` calls `wbtc::ft_transfer({"receiver_id": "bob", "amount": "500000000"})`. + +##### Token deposit to a contract + +Alice wants to deposit 1000 DAI tokens to a compound interest contract to earn extra tokens. + +**Assumptions** + +- The DAI token contract is `dai`. +- Alice's account is `alice`. +- The compound interest contract is `compound`. +- The precision ("decimals" in the metadata standard) on DAI contract is `10^18`. +- The 1000 tokens is `1000 * 10^18` or as a number is `1000000000000000000000`. +- The compound contract can work with multiple token types. + +
+For this example, you may expand this section to see how a previous fungible token standard using escrows would deal with the scenario. + +**High-level explanation** (NEP-21 standard) + +Alice needs to issue 2 transactions. The first one to `dai` to set an allowance for `compound` to be able to withdraw tokens from `alice`. +The second transaction is to the `compound` to start the deposit process. Compound will check that the DAI tokens are supported and will try to withdraw the desired amount of DAI from `alice`. +- If transfer succeeded, `compound` can increase local ownership for `alice` to 1000 DAI +- If transfer fails, `compound` doesn't need to do anything in current example, but maybe can notify `alice` of unsuccessful transfer. + +**Technical calls** (NEP-21 standard) + +1. `alice` calls `dai::set_allowance({"escrow_account_id": "compound", "allowance": "1000000000000000000000"})`. +2. `alice` calls `compound::deposit({"token_contract": "dai", "amount": "1000000000000000000000"})`. During the `deposit` call, `compound` does the following: + 1. makes async call `dai::transfer_from({"owner_id": "alice", "new_owner_id": "compound", "amount": "1000000000000000000000"})`. + 2. attaches a callback `compound::on_transfer({"owner_id": "alice", "token_contract": "dai", "amount": "1000000000000000000000"})`. + +
+ +**High-level explanation** + +Alice needs to issue 1 transaction, as opposed to 2 with a typical escrow workflow. + +**Technical calls** + +1. `alice` calls `dai::ft_transfer_call({"receiver_id": "compound", "amount": "1000000000000000000000", "msg": "invest"})`. During the `ft_transfer_call` call, `dai` does the following: + 1. makes async call `compound::ft_on_transfer({"sender_id": "alice", "amount": "1000000000000000000000", "msg": "invest"})`. + 2. attaches a callback `dai::ft_resolve_transfer({"sender_id": "alice", "receiver_id": "compound", "amount": "1000000000000000000000"})`. + 3. compound finishes investing, using all attached fungible tokens `compound::invest({…})` then returns the value of the tokens that weren't used or needed. In this case, Alice asked for the tokens to be invested, so it will return 0. (In some cases a method may not need to use all the fungible tokens, and would return the remainder.) + 4. the `dai::ft_resolve_transfer` function receives success/failure of the promise. If success, it will contain the unused tokens. Then the `dai` contract uses simple arithmetic (not needed in this case) and updates the balance for Alice. + +#### Swapping one token for another via an Automated Market Maker (AMM) like Uniswap + +Alice wants to swap 5 wrapped NEAR (wNEAR) for BNNA tokens at current market rate, with less than 2% slippage. + +**Assumptions** + +- The wNEAR token contract is `wnear`. +- Alice's account is `alice`. +- The AMM's contract is `amm`. +- BNNA's contract is `bnna`. +- The precision ("decimals" in the metadata standard) on wNEAR contract is `10^24`. +- The 5 tokens is `5 * 10^24` or as a number is `5000000000000000000000000`. + +**High-level explanation** + +Alice needs to issue one transaction to wNEAR contract to transfer 5 tokens (multiplied by precision) to `amm`, specifying her desired action (swap), her destination token (BNNA) & minimum slippage (<2%) in `msg`. + +Alice will probably make this call via a UI that knows how to construct `msg` in a way the `amm` contract will understand. However, it's possible that the `amm` contract itself may provide view functions which take desired action, destination token, & slippage as input and return data ready to pass to `msg` for `ft_transfer_call`. For the sake of this example, let's say `amm` implements a view function called `ft_data_to_msg`. + +Alice needs to attach one yoctoNEAR. This will result in her seeing a confirmation page in her preferred NEAR wallet. NEAR wallet implementations will (eventually) attempt to provide useful information in this confirmation page, so receiver contracts should follow a strong convention in how they format `msg`. We will update this documentation with a recommendation, as community consensus emerges. + +Altogether then, Alice may take two steps, though the first may be a background detail of the app she uses. + +**Technical calls** + +1. View `amm::ft_data_to_msg({ action: "swap", destination_token: "bnna", min_slip: 2 })`. Using [NEAR CLI](https://docs.near.org/docs/tools/near-cli): + + near view amm ft_data_to_msg '{ + "action": "swap", + "destination_token": "bnna", + "min_slip": 2 + }' + + Then Alice (or the app she uses) will hold onto the result and use it in the next step. Let's say this result is `"swap:bnna,2"`. + +2. Call `wnear::ft_on_transfer`. Using NEAR CLI: + near call wnear ft_transfer_call '{ + "receiver_id": "amm", + "amount": "5000000000000000000000000", + "msg": "swap:bnna,2" + }' --accountId alice --depositYocto 1 + + During the `ft_transfer_call` call, `wnear` does the following: + + 1. Decrease the balance of `alice` and increase the balance of `amm` by 5000000000000000000000000. + 2. Makes async call `amm::ft_on_transfer({"sender_id": "alice", "amount": "5000000000000000000000000", "msg": "swap:bnna,2"})`. + 3. Attaches a callback `wnear::ft_resolve_transfer({"sender_id": "alice", "receiver_id": "compound", "amount": "5000000000000000000000000"})`. + 4. `amm` finishes the swap, either successfully swapping all 5 wNEAR within the desired slippage, or failing. + 5. The `wnear::ft_resolve_transfer` function receives success/failure of the promise. Assuming `amm` implements all-or-nothing transfers (as in, it will not transfer less-than-the-specified amount in order to fulfill the slippage requirements), `wnear` will do nothing at this point if the swap succeeded, or it will decrease the balance of `amm` and increase the balance of `alice` by 5000000000000000000000000. + + +### Reference-level explanation + +**NOTES**: +- All amounts, balances and allowance are limited by `U128` (max value `2**128 - 1`). +- Token standard uses JSON for serialization of arguments and results. +- Amounts in arguments and results have are serialized as Base-10 strings, e.g. `"100"`. This is done to avoid JSON limitation of max integer value of `2**53`. +- The contract must track the change in storage when adding to and removing from collections. This is not included in this core fungible token standard but instead in the [Storage Standard](../StorageManagement.md). +- To prevent the deployed contract from being modified or deleted, it should not have any access keys on its account. + +#### Interface: + +##### ft_transfer + +Simple transfer to a receiver. + +Requirements: +* Caller of the method must attach a deposit of 1 yoctoⓃ for security purposes +* Caller must have greater than or equal to the `amount` being requested + +Arguments: +* `receiver_id`: the valid NEAR account receiving the fungible tokens. +* `amount`: the number of tokens to transfer, wrapped in quotes and treated + like a string, although the number will be stored as an unsigned integer + with 128 bits. +* `memo` (optional): for use cases that may benefit from indexing or +providing information for a transfer. + +```ts +function ft_transfer( + receiver_id: string, + amount: string, + memo: string|null +): void +``` + +##### ft_transfer_call + +Transfer tokens and call a method on a receiver contract. A successful +workflow will end in a success execution outcome to the callback on the same +contract at the method `ft_resolve_transfer`. +You can think of this as being similar to attaching native NEAR tokens to a +function call. It allows you to attach any Fungible Token in a call to a +receiver contract. + +Requirements: +* Caller of the method must attach a deposit of 1 yoctoⓃ for security + purposes +* Caller must have greater than or equal to the `amount` being requested +* The receiving contract must implement `ft_on_transfer` according to the + standard. If it does not, FT contract's `ft_resolve_transfer` MUST deal + with the resulting failed cross-contract call and roll back the transfer. +* Contract MUST implement the behavior described in `ft_resolve_transfer` + +Arguments: +* `receiver_id`: the valid NEAR account receiving the fungible tokens. +* `amount`: the number of tokens to transfer, wrapped in quotes and treated + like a string, although the number will be stored as an unsigned integer + with 128 bits. +* `memo` (optional): for use cases that may benefit from indexing or + providing information for a transfer. +* `msg`: specifies information needed by the receiving contract in + order to properly handle the transfer. Can indicate both a function to call and the parameters to pass to that function. + +```ts +function ft_transfer_call( + receiver_id: string, + amount: string, + memo: string|null, + msg: string +): Promise +``` + +##### ft_on_transfer + +This function is implemented on the receiving contract. +As mentioned, the `msg` argument contains information necessary for the receiving contract to know how to process the request. This may include method names and/or arguments. +Returns a value, or a promise which resolves with a value. The value is the +number of unused tokens in string form. For instance, if `amount` is 10 but only 9 are +needed, it will return "1". +```ts +function ft_on_transfer( + sender_id: string, + amount: string, + msg: string +): string +``` + +### View Methods + +##### ft_total_supply + +Returns the total supply of fungible tokens as a string representing the value as an unsigned 128-bit integer. +```js +function ft_total_supply(): string +``` + +##### ft_balance_of + +Returns the balance of an account in string form representing a value as an unsigned 128-bit integer. If the account doesn't exist must returns `"0"`. +```ts +function ft_balance_of( + account_id: string +): string +``` + +##### ft_resolve_transfer + +The following behavior is required, but contract authors may name this function something other than the conventional `ft_resolve_transfer` used here. + +Finalize an `ft_transfer_call` chain of cross-contract calls. + +The `ft_transfer_call` process: + + 1. Sender calls `ft_transfer_call` on FT contract + 2. FT contract transfers `amount` tokens from sender to receiver + 3. FT contract calls `ft_on_transfer` on receiver contract + 4+. [receiver contract may make other cross-contract calls] + N. FT contract resolves promise chain with `ft_resolve_transfer`, and may + refund sender some or all of original `amount` + +Requirements: + * Contract MUST forbid calls to this function by any account except self + * If promise chain failed, contract MUST revert token transfer + * If promise chain resolves with a non-zero amount given as a string, + contract MUST return this amount of tokens to `sender_id` + +Arguments: + * `sender_id`: the sender of `ft_transfer_call` + * `receiver_id`: the `receiver_id` argument given to `ft_transfer_call` + * `amount`: the `amount` argument given to `ft_transfer_call` + +Returns a string representing a string version of an unsigned 128-bit +integer of how many total tokens were spent by sender_id. Example: if sender +calls `ft_transfer_call({ "amount": "100" })`, but `receiver_id` only uses +80, `ft_on_transfer` will resolve with `"20"`, and `ft_resolve_transfer` +will return `"80"`. +```ts +function ft_resolve_transfer( + sender_id: string, + receiver_id: string, + amount: string +): string +``` + +### Events + +Standard interfaces for FT contract actions that extend [NEP-297](nep-0297.md) + +NEAR and third-party applications need to track `mint`, `transfer`, `burn` events for all FT-driven apps consistently. +This extension addresses that. + +Keep in mind that applications, including NEAR Wallet, could require implementing additional methods, such as [`ft_metadata`](Metadata.md), to display the FTs correctly. + +### Event Interface + +Fungible Token Events MUST have `standard` set to `"nep141"`, standard version set to `"1.0.0"`, `event` value is one of `ft_mint`, `ft_burn`, `ft_transfer`, and `data` must be of one of the following relevant types: `FtMintLog[] | FtTransferLog[] | FtBurnLog[]`: + +```ts +interface FtEventLogData { + standard: "nep141", + version: "1.0.0", + event: "ft_mint" | "ft_burn" | "ft_transfer", + data: FtMintLog[] | FtTransferLog[] | FtBurnLog[], +} +``` + +```ts +// An event log to capture tokens minting +// Arguments +// * `owner_id`: "account.near" +// * `amount`: the number of tokens to mint, wrapped in quotes and treated +// like a string, although the number will be stored as an unsigned integer +// with 128 bits. +// * `memo`: optional message +interface FtMintLog { + owner_id: string, + amount: string, + memo?: string +} + +// An event log to capture tokens burning +// Arguments +// * `owner_id`: owner of tokens to burn +// * `amount`: the number of tokens to burn, wrapped in quotes and treated +// like a string, although the number will be stored as an unsigned integer +// with 128 bits. +// * `memo`: optional message +interface FtBurnLog { + owner_id: string, + amount: string, + memo?: string +} + +// An event log to capture tokens transfer +// Arguments +// * `old_owner_id`: "owner.near" +// * `new_owner_id`: "receiver.near" +// * `amount`: the number of tokens to transfer, wrapped in quotes and treated +// like a string, although the number will be stored as an unsigned integer +// with 128 bits. +// * `memo`: optional message +interface FtTransferLog { + old_owner_id: string, + new_owner_id: string, + amount: string, + memo?: string +} +``` + +### Event Examples + +Batch mint: + +```js +EVENT_JSON:{ + "standard": "nep141", + "version": "1.0.0", + "event": "ft_mint", + "data": [ + {"owner_id": "foundation.near", "amount": "500"} + ] +} +``` + +Batch transfer: + +```js +EVENT_JSON:{ + "standard": "nep141", + "version": "1.0.0", + "event": "ft_transfer", + "data": [ + {"old_owner_id": "from.near", "new_owner_id": "to.near", "amount": "42", "memo": "hi hello bonjour"}, + {"old_owner_id": "user1.near", "new_owner_id": "user2.near", "amount": "7500"} + ] +} +``` + +Batch burn: + +```js +EVENT_JSON:{ + "standard": "nep141", + "version": "1.0.0", + "event": "ft_burn", + "data": [ + {"owner_id": "foundation.near", "amount": "100"}, + ] +} +``` + +### Further Event Methods + +Note that the example events covered above cover two different kinds of events: +1. Events that are not specified in the FT Standard (`ft_mint`, `ft_burn`) +2. An event that is covered in the [FT Core Standard](Core.md). (`ft_transfer`) + +Please feel free to open pull requests for extending the events standard detailed here as needs arise. + +## Reference Implementation + +The `near-contract-standards` cargo package of the [Near Rust SDK](https://github.com/near/near-sdk-rs) contain the following implementations of NEP-141: + +* [Minimum Viable Interface](https://github.com/near/near-sdk-rs/blob/master/near-contract-standards/src/fungible_token/core.rs) +* The [Core Fungible Token Implementation](https://github.com/near/near-sdk-rs/blob/master/near-contract-standards/src/fungible_token/core_impl.rs) +* [Optional Fungible Token Events](https://github.com/near/near-sdk-rs/blob/master/near-contract-standards/src/fungible_token/events.rs) +* [Core Fungible Token tests](https://github.com/near/near-sdk-rs/blob/master/examples/fungible-token/tests/workspaces.rs) + +## Drawbacks + +- The `msg` argument to `ft_transfer` and `ft_transfer_call` is freeform, which may necessitate conventions. +- The paradigm of an escrow system may be familiar to developers and end users, and education on properly handling this in another contract may be needed. + +## Future possibilities + +- Support for multiple token types +- Minting and burning + +## History + +See also the discussions: +- [Fungible token core](https://github.com/near/NEPs/discussions/146#discussioncomment-298943) +- [Fungible token metadata](https://github.com/near/NEPs/discussions/148) +- [Storage standard](https://github.com/near/NEPs/discussions/145) + +## Copyright + +Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). \ No newline at end of file diff --git a/neps/nep-0145.md b/neps/nep-0145.md new file mode 100644 index 000000000..781e06d6d --- /dev/null +++ b/neps/nep-0145.md @@ -0,0 +1,454 @@ +--- +NEP: 145 +Title: Storage Management +Author: Evgeny Kuzyakov , @oysterpack +DiscussionsTo: https://github.com/near/NEPs/discussions/145 +Status: Final +Type: Standards Track +Category: Contract +Created: 03-Mar-2022 +--- + +## Summary + +NEAR uses [storage staking] which means that a contract account must have sufficient balance to cover all storage added over time. This standard provides a uniform way to pass storage costs onto users. + +## Motivation + +It allows accounts and contracts to: + +1. Check an account's storage balance. +2. Determine the minimum storage needed to add account information such that the account can interact as expected with a contract. +3. Add storage balance for an account; either one's own or another. +4. Withdraw some storage deposit by removing associated account data from the contract and then making a call to remove unused deposit. +5. Unregister an account to recover full storage balance. + + [storage staking]: https://docs.near.org/docs/concepts/storage-staking + +## Rationale and alternatives + +Prior art: + +- A previous fungible token standard ([NEP-21](https://github.com/near/NEPs/pull/21)) highlighting how [storage was paid](https://github.com/near/near-sdk-rs/blob/1d3535bd131b68f97a216e643ad1cba19e16dddf/examples/fungible-token/src/lib.rs#L92-L113) for when increasing the allowance of an escrow system. + +### Example scenarios + +To show the flexibility and power of this standard, let's walk through two example contracts. + +1. A simple Fungible Token contract which uses Storage Management in "registration only" mode, where the contract only adds storage on a user's first interaction. + 1. Account registers self + 2. Account registers another + 3. Unnecessary attempt to re-register + 4. Force-closure of account + 5. Graceful closure of account +2. A social media contract, where users can add more data to the contract over time. + 1. Account registers self with more than minimum required + 2. Unnecessary attempt to re-register using `registration_only` param + 3. Attempting to take action which exceeds paid-for storage; increasing storage deposit + 4. Removing storage and reclaiming excess deposit + +### Example 1: Fungible Token Contract + +Imagine a [fungible token](FungibleToken/Core.md) contract deployed at `ft`. Let's say this contract saves all user balances to a Map data structure internally, and adding a key for a new user requires 0.00235Ⓝ. This contract therefore uses the Storage Management standard to pass this cost onto users, so that a new user must effectively pay a registration fee to interact with this contract of 0.00235Ⓝ, or 2350000000000000000000 yoctoⓃ ([yocto](https://www.metricconversion.us/prefixes.htm) = 10-24). + +For this contract, `storage_balance_bounds` will be: + +```json +{ + "min": "2350000000000000000000", + "max": "2350000000000000000000" +} +``` + +This means a user must deposit 0.00235Ⓝ to interact with this contract, and that attempts to deposit more than this will have no effect (attached deposits will be immediately refunded). + +Let's follow two users, Alice with account `alice` and Bob with account `bob`, as they interact with `ft` through the following scenarios: + +1. Alice registers herself +2. Alice registers Bob +3. Alice tries to register Bob again +4. Alice force-closes her account +5. Bob gracefully closes his account + +#### 1. Account pays own registration fee + +**High-level explanation** + +1. Alice checks if she is registered with the `ft` contract. +2. Alice determines the needed registration fee to register with the `ft` contract. +3. Alice issues a transaction to deposit Ⓝ for her account. + +**Technical calls** + +1. Alice queries a view-only method to determine if she already has storage on this contract with `ft::storage_balance_of({"account_id": "alice"})`. Using [NEAR CLI](https://docs.near.org/docs/tools/near-cli) to make this view call, the command would be: + + near view ft storage_balance_of '{"account_id": "alice"}' + + The response: + + null + +2. Alice uses [NEAR CLI](https://docs.near.org/docs/tools/near-cli) to make a view call. + + near view ft storage_balance_bounds + + As mentioned above, this will show that both `min` and `max` are both 2350000000000000000000 yoctoⓃ. + +3. Alice converts this yoctoⓃ amount to 0.00235 Ⓝ, then calls `ft::storage_deposit` with this attached deposit. Using NEAR CLI: + + near call ft storage_deposit '' \ + --accountId alice --amount 0.00235 + + The result: + + { + total: "2350000000000000000000", + available: "0" + } + + +#### 2. Account pays for another account's storage + +Alice wishes to eventually send `ft` tokens to Bob who is not registered. She decides to pay for Bob's storage. + +**High-level explanation** + +Alice issues a transaction to deposit Ⓝ for Bob's account. + +**Technical calls** + +Alice calls `ft::storage_deposit({"account_id": "bob"})` with the attached deposit of '0.00235'. Using NEAR CLI the command would be: + + near call ft storage_deposit '{"account_id": "bob"}' \ + --accountId alice --amount 0.00235 + +The result: + + { + total: "2350000000000000000000", + available: "0" + } + +#### 3. Unnecessary attempt to register already-registered account + +Alice accidentally makes the same call again, and even misses a leading zero in her deposit amount. + + near call ft storage_deposit '{"account_id": "bob"}' \ + --accountId alice --amount 0.0235 + +The result: + + { + total: "2350000000000000000000", + available: "0" + } + +Additionally, Alice will be refunded the 0.0235Ⓝ she attached, because the `storage_deposit_bounds.max` specifies that Bob's account cannot have a total balance larger than 0.00235Ⓝ. + +#### 4. Account force-closes registration + +Alice decides she doesn't care about her `ft` tokens and wants to forcibly recover her registration fee. If the contract permits this operation, her remaining `ft` tokens will either be burned or transferred to another account, which she may or may not have the ability to specify prior to force-closing. + +**High-level explanation** + +Alice issues a transaction to unregister her account and recover the Ⓝ from her registration fee. She must attach 1 yoctoⓃ, expressed in Ⓝ as `.000000000000000000000001`. + +**Technical calls** + +Alice calls `ft::storage_unregister({"force": true})` with a 1 yoctoⓃ deposit. Using NEAR CLI the command would be: + + near call ft storage_unregister '{ "force": true }' \ + --accountId alice --depositYocto 1 + +The result: + + true + +#### 5. Account gracefully closes registration + +Bob wants to close his account, but has a non-zero balance of `ft` tokens. + +**High-level explanation** + +1. Bob tries to gracefully close his account, calling `storage_unregister()` without specifying `force=true`. This results in an intelligible error that tells him why his account can't yet be unregistered gracefully. +2. Bob sends all of his `ft` tokens to a friend. +3. Bob retries to gracefully close his account. It works. + +**Technical calls** + +1. Bob calls `ft::storage_unregister()` with a 1 yoctoⓃ deposit. Using NEAR CLI the command would be: + + near call ft storage_unregister '' \ + --accountId bob --depositYocto 1 + + It fails with a message like "Cannot gracefully close account with positive remaining balance; bob has balance N" + +2. Bob transfers his tokens to a friend using `ft_transfer` from the [Fungible Token Core](FungibleToken/Core.md) standard. + +3. Bob tries the call from Step 1 again. It works. + +### Example 2: Social Media Contract + +Imagine a social media smart contract which passes storage costs onto users for posts and follower data. Let's say this this contract is deployed at account `social`. Like the Fungible Token contract example above, the `storage_balance_bounds.min` is 0.00235, because this contract will likewise add a newly-registered user to an internal Map. However, this contract sets no `storage_balance_bounds.max`, since users can add more data to the contract over time and must cover the cost for this storage. + +So for this contract, `storage_balance_bounds` will return: + +```json +{ + "min": "2350000000000000000000", + "max": null +} +``` + +Let's follow a user, Alice with account `alice`, as she interacts with `social` through the following scenarios: + +1. Registration +2. Unnecessary attempt to re-register using `registration_only` param +3. Attempting to take action which exceeds paid-for storage; increasing storage deposit +4. Removing storage and reclaiming excess deposit + +#### 1. Account registers with `social` + +**High-level explanation** + +Alice issues a transaction to deposit Ⓝ for her account. While the `storage_balance_bounds.min` for this contract is 0.00235Ⓝ, the frontend she uses suggests adding 0.1Ⓝ, so that she can immediately start adding data to the app, rather than *only* registering. + +**Technical calls** + +Using NEAR CLI: + + near call social storage_deposit '' \ + --accountId alice --amount 0.1 + +The result: + + { + total: '100000000000000000000000', + available: '97650000000000000000000' + } + +Here we see that she has deposited 0.1Ⓝ and that 0.00235 of it has been used to register her account, and is therefore locked by the contract. The rest is available to facilitate interaction with the contract, but could also be withdrawn by Alice by using `storage_withdraw`. + +#### 2. Unnecessary attempt to re-register using `registration_only` param + +**High-level explanation** + +Alice can't remember if she already registered and re-sends the call, using the `registration_only` param to ensure she doesn't attach another 0.1Ⓝ. + +**Technical calls** + +Using NEAR CLI: + + near call social storage_deposit '{"registration_only": true}' \ + --accountId alice --amount 0.1 + +The result: + + { + total: '100000000000000000000000', + available: '97650000000000000000000' + } + +Additionally, Alice will be refunded the extra 0.1Ⓝ that she just attached. This makes it easy for other contracts to always attempt to register users while performing batch transactions without worrying about errors or lost deposits. + +Note that if Alice had not included `registration_only`, she would have ended up with a `total` of 0.2Ⓝ. + +#### 3. Account increases storage deposit + +Assumption: `social` has a `post` function which allows creating a new post with free-form text. Alice has used almost all of her available storage balance. She attempts to call `post` with a large amount of text, and the transaction aborts because she needs to pay for more storage first. + +Note that applications will probably want to avoid this situation in the first place by prompting users to top up storage deposits sufficiently before available balance runs out. + +**High-level explanation** + +1. Alice issues a transaction, let's say `social.post`, and it fails with an intelligible error message to tell her that she has an insufficient storage balance to cover the cost of the operation +2. Alice issues a transaction to increase her storage balance +3. Alice retries the initial transaction and it succeeds + +**Technical calls** + +1. This is outside the scope of this spec, but let's say Alice calls `near call social post '{ "text": "very long message" }'`, and that this fails with a message saying something like "Insufficient storage deposit for transaction. Please call `storage_deposit` and attach at least 0.1 NEAR, then try again." + +2. Alice deposits the proper amount in a transaction by calling `social::storage_deposit` with the attached deposit of '0.1'. Using NEAR CLI: + + near call social storage_deposit '' \ + --accountId alice --amount 0.1 + + The result: + + { + total: '200000000000000000000000', + available: '100100000000000000000000' + } + +3. Alice tries the initial `near call social post` call again. It works. + +#### 4. Removing storage and reclaiming excess deposit + +Assumption: Alice has more deposited than she is using. + +**High-level explanation** + +1. Alice views her storage balance and sees that she has extra. +2. Alice withdraws her excess deposit. + +**Technical calls** + +1. Alice queries `social::storage_balance_of({ "account_id": "alice" })`. With NEAR CLI: + + near view social storage_balance_of '{"account_id": "alice"}' + + Response: + + { + total: '200000000000000000000000', + available: '100100000000000000000000' + } + +2. Alice calls `storage_withdraw` with a 1 yoctoⓃ deposit. NEAR CLI command: + + near call social storage_withdraw \ + '{"amount": "100100000000000000000000"}' \ + --accountId alice --depositYocto 1 + + Result: + + { + total: '200000000000000000000000', + available: '0' + } + +## Specification + +**NOTES**: + +- All amounts, balances and allowance are limited by `U128` (max value 2128 - 1). +- This storage standard uses JSON for serialization of arguments and results. +- Amounts in arguments and results are serialized as Base-10 strings, e.g. `"100"`. This is done to avoid JSON limitation of max integer value of 253. +- To prevent the deployed contract from being modified or deleted, it should not have any access keys on its account. + +**Interface**: + +```ts +// The structure that will be returned for the methods: +// * `storage_deposit` +// * `storage_withdraw` +// * `storage_balance_of` +// The `total` and `available` values are string representations of unsigned +// 128-bit integers showing the balance of a specific account in yoctoⓃ. +type StorageBalance = { + total: string; + available: string; +} + +// The below structure will be returned for the method `storage_balance_bounds`. +// Both `min` and `max` are string representations of unsigned 128-bit integers. +// +// `min` is the amount of tokens required to start using this contract at all +// (eg to register with the contract). If a new contract user attaches `min` +// NEAR to a `storage_deposit` call, subsequent calls to `storage_balance_of` +// for this user must show their `total` equal to `min` and `available=0` . +// +// A contract may implement `max` equal to `min` if it only charges for initial +// registration, and does not adjust per-user storage over time. A contract +// which implements `max` must refund deposits that would increase a user's +// storage balance beyond this amount. +type StorageBalanceBounds = { + min: string; + max: string|null; +} + +/************************************/ +/* CHANGE METHODS on fungible token */ +/************************************/ +// Payable method that receives an attached deposit of Ⓝ for a given account. +// +// If `account_id` is omitted, the deposit MUST go toward predecessor account. +// If provided, deposit MUST go toward this account. If invalid, contract MUST +// panic. +// +// If `registration_only=true`, contract MUST refund above the minimum balance +// if the account wasn't registered and refund full deposit if already +// registered. +// +// The `storage_balance_of.total` + `attached_deposit` in excess of +// `storage_balance_bounds.max` must be refunded to predecessor account. +// +// Returns the StorageBalance structure showing updated balances. +function storage_deposit( + account_id: string|null, + registration_only: boolean|null +): StorageBalance {} + +// Withdraw specified amount of available Ⓝ for predecessor account. +// +// This method is safe to call. It MUST NOT remove data. +// +// `amount` is sent as a string representing an unsigned 128-bit integer. If +// omitted, contract MUST refund full `available` balance. If `amount` exceeds +// predecessor account's available balance, contract MUST panic. +// +// If predecessor account not registered, contract MUST panic. +// +// MUST require exactly 1 yoctoNEAR attached balance to prevent restricted +// function-call access-key call (UX wallet security) +// +// Returns the StorageBalance structure showing updated balances. +function storage_withdraw(amount: string|null): StorageBalance {} + +// Unregisters the predecessor account and returns the storage NEAR deposit. +// +// If the predecessor account is not registered, the function MUST return +// `false` without panic. +// +// If `force=true` the function SHOULD ignore existing account data, such as +// non-zero balances on an FT contract (that is, it should burn such balances), +// and close the account. Contract MAY panic if it doesn't support forced +// unregistration, or if it can't force unregister for the particular situation +// (example: too much data to delete at once). +// +// If `force=false` or `force` is omitted, the contract MUST panic if caller +// has existing account data, such as a positive registered balance (eg token +// holdings). +// +// MUST require exactly 1 yoctoNEAR attached balance to prevent restricted +// function-call access-key call (UX wallet security) +// +// Returns `true` iff the account was successfully unregistered. +// Returns `false` iff account was not registered before. +function storage_unregister(force: boolean|null): boolean {} + +/****************/ +/* VIEW METHODS */ +/****************/ +// Returns minimum and maximum allowed balance amounts to interact with this +// contract. See StorageBalanceBounds. +function storage_balance_bounds(): StorageBalanceBounds {} + +// Returns the StorageBalance structure of the valid `account_id` +// provided. Must panic if `account_id` is invalid. +// +// If `account_id` is not registered, must return `null`. +function storage_balance_of(account_id: string): StorageBalance|null {} +``` + +## Reference Implementation + +The `near-contract-standards` cargo package of the [Near Rust SDK](https://github.com/near/near-sdk-rs) contain the following implementations of NEP-145: + +* [Minimum Viable Interface](https://github.com/near/near-sdk-rs/blob/master/near-contract-standards/src/storage_management/mod.rs#L20) +* [Implementation](https://github.com/near/near-sdk-rs/blob/master/near-contract-standards/src/storage_management/mod.rs) + +## Drawbacks + +- The idea may confuse contract developers at first until they understand how a system with storage staking works. +- Some folks in the community would rather see the storage deposit only done for the sender. That is, that no one else should be able to add storage for another user. This stance wasn't adopted in this standard, but others may have similar concerns in the future. + +## Future possibilities + +- Ideally, contracts will update available balance for all accounts every time the NEAR blockchain's configured storage-cost-per-byte is reduced. That they *must* do so is not enforced by this current standard. + +## Copyright +[copyright]: #copyright + +Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). \ No newline at end of file diff --git a/neps/nep-0148.md b/neps/nep-0148.md new file mode 100644 index 000000000..bd2254db3 --- /dev/null +++ b/neps/nep-0148.md @@ -0,0 +1,121 @@ +--- +NEP: 148 +Title: Fungible Token Metadata +Author: Robert Zaremba , Evgeny Kuzyakov , @oysterpack +DiscussionsTo: https://github.com/near/NEPs/discussions/148 +Status: Final +Type: Standards Track +Category: Contract +Created: 03-Mar-2022 +Requires: 141 +--- + +## Summary + +An interface for a fungible token's metadata. The goal is to keep the metadata future-proof as well as lightweight. This will be important to dApps needing additional information about an FT's properties, and broadly compatible with other tokens standards such that the [NEAR Rainbow Bridge](https://near.org/blog/eth-near-rainbow-bridge/) can move tokens between chains. + +## Motivation + +Custom fungible tokens play a major role in decentralized applications today. FTs can contain custom properties to differentiate themselves from other tokens or contracts in the ecosystem. In NEAR, many common properties can be stored right on-chain. Other properties are best stored off-chain or in a decentralized storage platform, in order to save on storage costs and allow rapid community experimentation. + +## Rationale and alternatives +As blockchain technology advances, it becomes increasingly important to provide backwards compatibility and a concept of a spec. This standard encompasses all of these concerns. + +Prior art: + +- [EIP-1046](https://eips.ethereum.org/EIPS/eip-1046) +- [OpenZeppelin's ERC-721 Metadata standard](https://docs.openzeppelin.com/contracts/2.x/api/token/erc721#ERC721Metadata) also helped, although it's for non-fungible tokens. + +## Specification + +A fungible token smart contract allows for discoverable properties. Some properties can be determined by other contracts on-chain, or return in view method calls. Others can only be determined by an oracle system to be used on-chain, or by a frontend with the ability to access a linked reference file. + +### Examples scenario + +#### Token provides metadata upon deploy and initialization + +Alice deploys a wBTC fungible token contract. + +**Assumptions** + +- The wBTC token contract is `wbtc`. +- Alice's account is `alice`. +- The precision ("decimals" in this metadata standard) on wBTC contract is `10^8`. + +**High-level explanation** + +Alice issues a transaction to deploy and initialize the fungible token contract, providing arguments to the initialization function that set metadata fields. + +**Technical calls** + +1. `alice` deploys a contract and calls `wbtc::new` with all metadata. If this deploy and initialization were done using [NEAR CLI](https://docs.near.org/docs/tools/near-cli) the command would be: + + near deploy wbtc --wasmFile res/ft.wasm --initFunction new --initArgs '{ + "owner_id": "wbtc", + "total_supply": "100000000000000", + "metadata": { + "spec": "ft-1.0.0", + "name": "Wrapped Bitcoin", + "symbol": "WBTC", + "icon": "data:image/svg+xml,%3C…", + "reference": "https://example.com/wbtc.json", + "reference_hash": "AK3YRHqKhCJNmKfV6SrutnlWW/icN5J8NUPtKsNXR1M=", + "decimals": 8 + } + }' --accountId alice + +## Reference-level explanation + +A fungible token contract implementing the metadata standard shall contain a function named `ft_metadata`. + +```ts +function ft_metadata(): FungibleTokenMetadata {} +``` + +**Interface**: + +```ts +type FungibleTokenMetadata = { + spec: string; + name: string; + symbol: string; + icon: string|null; + reference: string|null; + reference_hash: string|null; + decimals: number; +} +``` + +**An implementing contract MUST include the following fields on-chain** + +- `spec`: a string. Should be `ft-1.0.0` to indicate that a Fungible Token contract adheres to the current versions of this Metadata and the [Fungible Token Core](./Core.md) specs. This will allow consumers of the Fungible Token to know if they support the features of a given contract. +- `name`: the human-readable name of the token. +- `symbol`: the abbreviation, like wETH or AMPL. +- `decimals`: used in frontends to show the proper significant digits of a token. This concept is explained well in this [OpenZeppelin post](https://docs.openzeppelin.com/contracts/3.x/erc20#a-note-on-decimals). + +**An implementing contract MAY include the following fields on-chain** + +- `icon`: a small image associated with this token. Must be a [data URL](https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/Data_URIs), to help consumers display it quickly while protecting user data. Recommendation: use [optimized SVG](https://codepen.io/tigt/post/optimizing-svgs-in-data-uris), which can result in high-resolution images with only 100s of bytes of [storage cost](https://docs.near.org/docs/concepts/storage-staking). (Note that these storage costs are incurred to the token owner/deployer, but that querying these icons is a very cheap & cacheable read operation for all consumers of the contract and the RPC nodes that serve the data.) Recommendation: create icons that will work well with both light-mode and dark-mode websites by either using middle-tone color schemes, or by [embedding `media` queries in the SVG](https://timkadlec.com/2013/04/media-queries-within-svg/). +- `reference`: a link to a valid JSON file containing various keys offering supplementary details on the token. Example: "/ipfs/QmdmQXB2mzChmMeKY47C43LxUdg1NDJ5MWcKMKxDu7RgQm", "https://example.com/token.json", etc. If the information given in this document conflicts with the on-chain attributes, the values in `reference` shall be considered the source of truth. +- `reference_hash`: the base64-encoded sha256 hash of the JSON file contained in the `reference` field. This is to guard against off-chain tampering. + +## Reference Implementation + +The `near-contract-standards` cargo package of the [Near Rust SDK](https://github.com/near/near-sdk-rs) contain the following implementations of NEP-148: + +* [Implementation](https://github.com/near/near-sdk-rs/blob/master/near-contract-standards/src/fungible_token/metadata.rs) + +## Drawbacks + +- It could be argued that `symbol` and even `name` could belong as key/values in the `reference` JSON object. +- Enforcement of `icon` to be a data URL rather than a link to an HTTP endpoint that could contain privacy-violating code cannot be done on deploy or update of contract metadata, and must be done on the consumer/app side when displaying token data. +- If on-chain icon uses a data URL or is not set but the document given by `reference` contains a privacy-violating `icon` URL, consumers & apps of this data should not naïvely display the `reference` version, but should prefer the safe version. This is technically a violation of the "`reference` setting wins" policy described above. + +## Future possibilities +- Detailed conventions that may be enforced for versions. +- A fleshed out schema for what the `reference` object should contain. + +## Copyright +[copyright]: #copyright + +Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). \ No newline at end of file diff --git a/neps/nep-0171.md b/neps/nep-0171.md new file mode 100644 index 000000000..582cf6ab5 --- /dev/null +++ b/neps/nep-0171.md @@ -0,0 +1,376 @@ +--- +NEP: 171 +Title: Non Fungible Token Standard +Author: Mike Purvis , Evgeny Kuzyakov , @oysterpack +DiscussionsTo: https://github.com/near/NEPs/discussions/171 +Status: Final +Type: Standards Track +Category: Contract +Created: 03-Mar-2022 +Requires: 297 +--- + +## Summary + +A standard interface for non-fungible tokens (NFTs). That is, tokens which each have a unique ID. + +## Motivation + +In the three years since [ERC-721] was ratified by the Ethereum community, Non-Fungible Tokens have proven themselves as an incredible new opportunity across a wide array of disciplines: collectibles, art, gaming, finance, virtual reality, real estate, and more. + +This standard builds off the lessons learned in this early experimentation, and pushes the possibilities further by harnessing unique attributes of the NEAR blockchain: + +- an asynchronous, sharded runtime, meaning that two contracts can be executed at the same time in different shards +- a [storage staking] model that separates [gas] fees from the storage demands of the network, enabling greater on-chain storage (see [Metadata] extension) and ultra-low transaction fees + +Given these attributes, this NFT standard can accomplish with one user interaction things for which other blockchains need two or three. Most noteworthy is `nft_transfer_call`, by which a user can essentially attach a token to a call to a separate contract. An example scenario: + +* An [Exquisite Corpse](https://en.wikipedia.org/wiki/Exquisite_corpse) contract allows three drawings to be submitted, one for each section of a final composition, to be minted as its own NFT and sold on a marketplace, splitting royalties amongst the original artists. +* Alice draws the top third and submits it, Bob the middle third, and Carol follows up with the bottom third. Since they each use `nft_transfer_call` to both transfer their NFT to the Exquisite Corpse contract as well as call a `submit` method on it, the call from Carol can automatically kick off minting a composite NFT from the three submissions, as well as listing this composite NFT in a marketplace. +* When Dan attempts to also call `nft_transfer_call` to submit an unneeded top third of the drawing, the Exquisite Corpse contract can throw an error, and the transfer will be rolled back so that Bob maintains ownership of his NFT. + +While this is already flexible and powerful enough to handle all sorts of existing and new use-cases, apps such as marketplaces may still benefit from the [Approval Management] extension. + +Prior art: + +- [ERC-721] +- [EIP-1155 for multi-tokens](https://eips.ethereum.org/EIPS/eip-1155#non-fungible-tokens) +- [NEAR's Fungible Token Standard](../FungibleToken/Core.md), which first pioneered the "transfer and call" technique + + +## Rationale and alternatives +[rationale-and-alternatives]: #rationale-and-alternatives + +- Why is this design the best in the space of possible designs? +- What other designs have been considered and what is the rationale for not choosing them? +- What is the impact of not doing this? + +## Specification + +**NOTES**: +- All amounts, balances and allowance are limited by `U128` (max value `2**128 - 1`). +- Token standard uses JSON for serialization of arguments and results. +- Amounts in arguments and results are serialized as Base-10 strings, e.g. `"100"`. This is done to avoid JSON limitation of max integer value of `2**53`. +- The contract must track the change in storage when adding to and removing from collections. This is not included in this core fungible token standard but instead in the [Storage Standard](../StorageManagement.md). +- To prevent the deployed contract from being modified or deleted, it should not have any access keys on its account. + +### NFT Interface + +```ts +// The base structure that will be returned for a token. If contract is using +// extensions such as Approval Management, Metadata, or other +// attributes may be included in this structure. +type Token = { + token_id: string, + owner_id: string, + } + +/******************/ +/* CHANGE METHODS */ +/******************/ + +// Simple transfer. Transfer a given `token_id` from current owner to +// `receiver_id`. +// +// Requirements +// * Caller of the method must attach a deposit of 1 yoctoⓃ for security purposes +// * Contract MUST panic if called by someone other than token owner or, +// if using Approval Management, one of the approved accounts +// * `approval_id` is for use with Approval Management extension, see +// that document for full explanation. +// * If using Approval Management, contract MUST nullify approved accounts on +// successful transfer. +// +// Arguments: +// * `receiver_id`: the valid NEAR account receiving the token +// * `token_id`: the token to transfer +// * `approval_id`: expected approval ID. A number smaller than +// 2^53, and therefore representable as JSON. See Approval Management +// standard for full explanation. +// * `memo` (optional): for use cases that may benefit from indexing or +// providing information for a transfer +function nft_transfer( + receiver_id: string, + token_id: string, + approval_id: number|null, + memo: string|null, +) {} + +// Returns `true` if the token was transferred from the sender's account. + +// Transfer token and call a method on a receiver contract. A successful +// workflow will end in a success execution outcome to the callback on the NFT +// contract at the method `nft_resolve_transfer`. +// +// You can think of this as being similar to attaching native NEAR tokens to a +// function call. It allows you to attach any Non-Fungible Token in a call to a +// receiver contract. +// +// Requirements: +// * Caller of the method must attach a deposit of 1 yoctoⓃ for security +// purposes +// * Contract MUST panic if called by someone other than token owner or, +// if using Approval Management, one of the approved accounts +// * The receiving contract must implement `nft_on_transfer` according to the +// standard. If it does not, FT contract's `nft_resolve_transfer` MUST deal +// with the resulting failed cross-contract call and roll back the transfer. +// * Contract MUST implement the behavior described in `nft_resolve_transfer` +// * `approval_id` is for use with Approval Management extension, see +// that document for full explanation. +// * If using Approval Management, contract MUST nullify approved accounts on +// successful transfer. +// +// Arguments: +// * `receiver_id`: the valid NEAR account receiving the token. +// * `token_id`: the token to send. +// * `approval_id`: expected approval ID. A number smaller than +// 2^53, and therefore representable as JSON. See Approval Management +// standard for full explanation. +// * `memo` (optional): for use cases that may benefit from indexing or +// providing information for a transfer. +// * `msg`: specifies information needed by the receiving contract in +// order to properly handle the transfer. Can indicate both a function to +// call and the parameters to pass to that function. +function nft_transfer_call( + receiver_id: string, + token_id: string, + approval_id: number|null, + memo: string|null, + msg: string, +): Promise {} + + +/****************/ +/* VIEW METHODS */ +/****************/ + +// Returns the token with the given `token_id` or `null` if no such token. +function nft_token(token_id: string): Token|null {} +``` + +The following behavior is required, but contract authors may name this function something other than the conventional `nft_resolve_transfer` used here. + +```ts +// Finalize an `nft_transfer_call` chain of cross-contract calls. +// +// The `nft_transfer_call` process: +// +// 1. Sender calls `nft_transfer_call` on NFT contract +// 2. NFT contract transfers token from sender to receiver +// 3. NFT contract calls `nft_on_transfer` on receiver contract +// 4+. [receiver contract may make other cross-contract calls] +// N. NFT contract resolves promise chain with `nft_resolve_transfer`, and may +// transfer token back to sender +// +// Requirements: +// * Contract MUST forbid calls to this function by any account except self +// * If promise chain failed, contract MUST revert token transfer +// * If promise chain resolves with `true`, contract MUST return token to +// `owner_id` +// +// Arguments: +// * `owner_id`: the original owner of the NFT. +// * `receiver_id`: the `receiver_id` argument given to `nft_transfer_call` +// * `token_id`: the `token_id` argument given to `nft_transfer_call` +// * `approved_account_ids `: if using Approval Management, contract MUST provide +// record of original approved accounts in this argument, and restore these +// approved accounts and their approval IDs in case of revert. +// +// Returns true if token was successfully transferred to `receiver_id`. +function nft_resolve_transfer( + owner_id: string, + receiver_id: string, + token_id: string, + approved_account_ids: null|Record, +): boolean {} +``` + +### Receiver Interface + +Contracts which want to make use of `nft_transfer_call` must implement the following: + +```ts +// Take some action after receiving a non-fungible token +// +// Requirements: +// * Contract MUST restrict calls to this function to a set of whitelisted NFT +// contracts +// +// Arguments: +// * `sender_id`: the sender of `nft_transfer_call` +// * `previous_owner_id`: the account that owned the NFT prior to it being +// transferred to this contract, which can differ from `sender_id` if using +// Approval Management extension +// * `token_id`: the `token_id` argument given to `nft_transfer_call` +// * `msg`: information necessary for this contract to know how to process the +// request. This may include method names and/or arguments. +// +// Returns true if token should be returned to `sender_id` +function nft_on_transfer( + sender_id: string, + previous_owner_id: string, + token_id: string, + msg: string, +): Promise; +``` + +### Events + +NEAR and third-party applications need to track `mint`, `transfer`, `burn` events for all NFT-driven apps consistently. +This extension addresses that. + +Keep in mind that applications, including NEAR Wallet, could require implementing additional methods to display the NFTs correctly, such as [`nft_metadata`](Metadata.md) and [`nft_tokens_for_owner`](Enumeration.md). + +### Events Interface + +Non-Fungible Token Events MUST have `standard` set to `"nep171"`, standard version set to `"1.0.0"`, `event` value is one of `nft_mint`, `nft_burn`, `nft_transfer`, and `data` must be of one of the following relavant types: `NftMintLog[] | NftTransferLog[] | NftBurnLog[]`: + +```ts +interface NftEventLogData { + standard: "nep171", + version: "1.0.0", + event: "nft_mint" | "nft_burn" | "nft_transfer", + data: NftMintLog[] | NftTransferLog[] | NftBurnLog[], +} +``` + +```ts +// An event log to capture token minting +// Arguments +// * `owner_id`: "account.near" +// * `token_ids`: ["1", "abc"] +// * `memo`: optional message +interface NftMintLog { + owner_id: string, + token_ids: string[], + memo?: string +} + +// An event log to capture token burning +// Arguments +// * `owner_id`: owner of tokens to burn +// * `authorized_id`: approved account_id to burn, if applicable +// * `token_ids`: ["1","2"] +// * `memo`: optional message +interface NftBurnLog { + owner_id: string, + authorized_id?: string, + token_ids: string[], + memo?: string +} + +// An event log to capture token transfer +// Arguments +// * `authorized_id`: approved account_id to transfer, if applicable +// * `old_owner_id`: "owner.near" +// * `new_owner_id`: "receiver.near" +// * `token_ids`: ["1", "12345abc"] +// * `memo`: optional message +interface NftTransferLog { + authorized_id?: string, + old_owner_id: string, + new_owner_id: string, + token_ids: string[], + memo?: string +} +``` + +## Examples + +Single owner batch minting (pretty-formatted for readability purposes): + +```js +EVENT_JSON:{ + "standard": "nep171", + "version": "1.0.0", + "event": "nft_mint", + "data": [ + {"owner_id": "foundation.near", "token_ids": ["aurora", "proximitylabs"]} + ] +} +``` + +Different owners batch minting: + +```js +EVENT_JSON:{ + "standard": "nep171", + "version": "1.0.0", + "event": "nft_mint", + "data": [ + {"owner_id": "foundation.near", "token_ids": ["aurora", "proximitylabs"]}, + {"owner_id": "user1.near", "token_ids": ["meme"]} + ] +} +``` + +Different events (separate log entries): + +```js +EVENT_JSON:{ + "standard": "nep171", + "version": "1.0.0", + "event": "nft_burn", + "data": [ + {"owner_id": "foundation.near", "token_ids": ["aurora", "proximitylabs"]}, + ] +} +``` + +```js +EVENT_JSON:{ + "standard": "nep171", + "version": "1.0.0", + "event": "nft_transfer", + "data": [ + {"old_owner_id": "user1.near", "new_owner_id": "user2.near", "token_ids": ["meme"], "memo": "have fun!"} + ] +} +``` + +Authorized id: + +```js +EVENT_JSON:{ + "standard": "nep171", + "version": "1.0.0", + "event": "nft_burn", + "data": [ + {"owner_id": "owner.near", "token_ids": ["goodbye", "aurevoir"], "authorized_id": "thirdparty.near"} + ] +} +``` + +## Further Event Methods + +Note that the example events covered above cover two different kinds of events: +1. Events that are not specified in the NFT Standard (`nft_mint`, `nft_burn`) +2. An event that is covered in the [NFT Core Standard](https://nomicon.io/Standards/NonFungibleToken/Core.html#nft-interface). (`nft_transfer`) + +This event standard also applies beyond the three events highlighted here, where future events follow the same convention of as the second type. For instance, if an NFT contract uses the [approval management standard](https://nomicon.io/Standards/NonFungibleToken/ApprovalManagement.html), it may emit an event for `nft_approve` if that's deemed as important by the developer community. + +Please feel free to open pull requests for extending the events standard detailed here as needs arise. + +## Reference Implementation + +[Minimum Viable Interface](https://github.com/near/near-sdk-rs/blob/master/near-contract-standards/src/non_fungible_token/core/mod.rs) + +[NFT Implementation](https://github.com/near/near-sdk-rs/blob/master/near-contract-standards/src/non_fungible_token/core/core_impl.rs) + +## Errata + +* **2022-02-03**: updated `Token` struct field names. `id` was changed to `token_id`. This is to be consistent with current implementations of the standard and the rust SDK docs. + +* **2021-12-20**: updated `nft_resolve_transfer` argument `approved_account_ids` to be type `null|Record` instead of `null|string[]`. This gives contracts a way to restore the original approved accounts and their approval IDs. More information can be found in [this](https://github.com/near/NEPs/issues/301) discussion. +* **2021-07-16**: updated `nft_transfer_call` argument `approval_id` to be type `number|null` instead of `string|null`. As stated, approval IDs are not expected to exceed the JSON limit of 2^53. + + [ERC-721]: https://eips.ethereum.org/EIPS/eip-721 + [storage staking]: https://docs.near.org/docs/concepts/storage-staking + [gas]: https://docs.near.org/docs/concepts/gas + [Metadata]: Metadata.md + [Approval Management]: ApprovalManagement.md + +## Copyright +[copyright]: #copyright + +Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). \ No newline at end of file diff --git a/neps/nep-0177.md b/neps/nep-0177.md new file mode 100644 index 000000000..0e06091df --- /dev/null +++ b/neps/nep-0177.md @@ -0,0 +1,154 @@ +--- +NEP: 177 +Title: Non Fungible Token Metadata +Author: Chad Ostrowski <@chadoh>, Mike Purvis +DiscussionsTo: https://github.com/near/NEPs/discussions/177 +Status: Final +Type: Standards Track +Category: Contract +Created: 03-Mar-2022 +Requires: 171 +--- + +## Summary + +An interface for a non-fungible token's metadata. The goal is to keep the metadata future-proof as well as lightweight. This will be important to dApps needing additional information about an NFT's properties, and broadly compatible with other token standards such that the [NEAR Rainbow Bridge](https://near.org/blog/eth-near-rainbow-bridge/) can move tokens between chains. + +## Motivation + +The primary value of non-fungible tokens comes from their metadata. While the [core standard](Core.md) provides the minimum interface that can be considered a non-fungible token, most artists, developers, and dApps will want to associate more data with each NFT, and will want a predictable way to interact with any NFT's metadata. + +## Rationale and alternatives + +NEAR's unique [storage staking](https://docs.near.org/docs/concepts/storage-staking) approach makes it feasible to store more data on-chain than other blockchains. This standard leverages this strength for common metadata attributes, and provides a standard way to link to additional offchain data to support rapid community experimentation. + +This standard also provides a `spec` version. This makes it easy for consumers of NFTs, such as marketplaces, to know if they support all the features of a given token. + +Prior art: + +- NEAR's [Fungible Token Metadata Standard](../FungibleToken/Metadata.md) +- Discussion about NEAR's complete NFT standard: #171 + +## Specification + +## Interface + +Metadata applies at both the contract level (`NFTContractMetadata`) and the token level (`TokenMetadata`). The relevant metadata for each: + +```ts +type NFTContractMetadata = { + spec: string, // required, essentially a version like "nft-1.0.0" + name: string, // required, ex. "Mochi Rising — Digital Edition" or "Metaverse 3" + symbol: string, // required, ex. "MOCHI" + icon: string|null, // Data URL + base_uri: string|null, // Centralized gateway known to have reliable access to decentralized storage assets referenced by `reference` or `media` URLs + reference: string|null, // URL to a JSON file with more info + reference_hash: string|null, // Base64-encoded sha256 hash of JSON from reference field. Required if `reference` is included. +} + +type TokenMetadata = { + title: string|null, // ex. "Arch Nemesis: Mail Carrier" or "Parcel #5055" + description: string|null, // free-form description + media: string|null, // URL to associated media, preferably to decentralized, content-addressed storage + media_hash: string|null, // Base64-encoded sha256 hash of content referenced by the `media` field. Required if `media` is included. + copies: number|null, // number of copies of this set of metadata in existence when token was minted. + issued_at: number|null, // When token was issued or minted, Unix epoch in milliseconds + expires_at: number|null, // When token expires, Unix epoch in milliseconds + starts_at: number|null, // When token starts being valid, Unix epoch in milliseconds + updated_at: number|null, // When token was last updated, Unix epoch in milliseconds + extra: string|null, // anything extra the NFT wants to store on-chain. Can be stringified JSON. + reference: string|null, // URL to an off-chain JSON file with more info. + reference_hash: string|null // Base64-encoded sha256 hash of JSON from reference field. Required if `reference` is included. +} +``` + +A new function MUST be supported on the NFT contract: + +```ts +function nft_metadata(): NFTContractMetadata {} +``` + +A new attribute MUST be added to each `Token` struct: + +```diff + type Token = { + token_id: string, + owner_id: string, ++ metadata: TokenMetadata, + } +``` + +### An implementing contract MUST include the following fields on-chain + +- `spec`: a string that MUST be formatted `nft-1.0.0` to indicate that a Non-Fungible Token contract adheres to the current versions of this Metadata spec. This will allow consumers of the Non-Fungible Token to know if they support the features of a given contract. +- `name`: the human-readable name of the contract. +- `symbol`: the abbreviated symbol of the contract, like MOCHI or MV3 +- `base_uri`: Centralized gateway known to have reliable access to decentralized storage assets referenced by `reference` or `media` URLs. Can be used by other frontends for initial retrieval of assets, even if these frontends then replicate the data to their own decentralized nodes, which they are encouraged to do. + +### An implementing contract MAY include the following fields on-chain + +For `NFTContractMetadata`: + +- `icon`: a small image associated with this contract. Encouraged to be a [data URL](https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/Data_URIs), to help consumers display it quickly while protecting user data. Recommendation: use [optimized SVG](https://codepen.io/tigt/post/optimizing-svgs-in-data-uris), which can result in high-resolution images with only 100s of bytes of [storage cost](https://docs.near.org/docs/concepts/storage-staking). (Note that these storage costs are incurred to the contract deployer, but that querying these icons is a very cheap & cacheable read operation for all consumers of the contract and the RPC nodes that serve the data.) Recommendation: create icons that will work well with both light-mode and dark-mode websites by either using middle-tone color schemes, or by [embedding `media` queries in the SVG](https://timkadlec.com/2013/04/media-queries-within-svg/). +- `reference`: a link to a valid JSON file containing various keys offering supplementary details on the token. Example: "/ipfs/QmdmQXB2mzChmMeKY47C43LxUdg1NDJ5MWcKMKxDu7RgQm", "https://example.com/token.json", etc. If the information given in this document conflicts with the on-chain attributes, the values in `reference` shall be considered the source of truth. +- `reference_hash`: the base64-encoded sha256 hash of the JSON file contained in the `reference` field. This is to guard against off-chain tampering. + +For `TokenMetadata`: + +- `name`: The name of this specific token. +- `description`: A longer description of the token. +- `media`: URL to associated media. Preferably to decentralized, content-addressed storage. +- `media_hash`: the base64-encoded sha256 hash of content referenced by the `media` field. This is to guard against off-chain tampering. +- `copies`: The number of tokens with this set of metadata or `media` known to exist at time of minting. +- `issued_at`: Unix epoch in milliseconds when token was issued or minted (an unsigned 32-bit integer would suffice until the year 2106) +- `expires_at`: Unix epoch in milliseconds when token expires +- `starts_at`: Unix epoch in milliseconds when token starts being valid +- `updated_at`: Unix epoch in milliseconds when token was last updated +- `extra`: anything extra the NFT wants to store on-chain. Can be stringified JSON. +- `reference`: URL to an off-chain JSON file with more info. +- `reference_hash`: Base64-encoded sha256 hash of JSON from reference field. Required if `reference` is included. + +### No incurred cost for core NFT behavior + +Contracts should be implemented in a way to avoid extra gas fees for serialization & deserialization of metadata for calls to `nft_*` methods other than `nft_metadata` or `nft_token`. See `near-contract-standards` [implementation using `LazyOption`](https://github.com/near/near-sdk-rs/blob/c2771af7fdfe01a4e8414046752ee16fb0d29d39/examples/fungible-token/ft/src/lib.rs#L71) as a reference example. + + +## Reference Implementation +[reference-implementation]: #reference-implementation + +This is the technical portion of the NEP. Explain the design in sufficient detail that: + +- Its interaction with other features is clear. +- Where possible, include a `Minimum Viable Interface` subsection expressing the required behavior and types in a target Near Contract language. (ie. traits and structs for rust, interfaces and classes for javascript, function signatures and structs for c, etc.) +- It is reasonably clear how the feature would be implemented. +- Corner cases are dissected by example. + +The section should return to the examples given in the previous section, and explain more fully how the detailed proposal makes those examples work. + +## Drawbacks + +* When this NFT contract is created and initialized, the storage use per-token will be higher than an NFT Core version. Frontends can account for this by adding extra deposit when minting. This could be done by padding with a reasonable amount, or by the frontend using the [RPC call detailed here](https://docs.near.org/docs/develop/front-end/rpc#genesis-config) that gets genesis configuration and actually determine precisely how much deposit is needed. +* Convention of `icon` being a data URL rather than a link to an HTTP endpoint that could contain privacy-violating code cannot be done on deploy or update of contract metadata, and must be done on the consumer/app side when displaying token data. +* If on-chain icon uses a data URL or is not set but the document given by `reference` contains a privacy-violating `icon` URL, consumers & apps of this data should not naïvely display the `reference` version, but should prefer the safe version. This is technically a violation of the "`reference` setting wins" policy described above. + +## Future possibilities + +- Detailed conventions that may be enforced for versions. +- A fleshed out schema for what the `reference` object should contain. + +## Errata + +* **2022-02-03**: updated `Token` struct field names. `id` was changed to `token_id`. This is to be consistent with current implementations of the standard and the rust SDK docs. + +The first version (`1.0.0`) had confusing language regarding the fields: +- `issued_at` +- `expires_at` +- `starts_at` +- `updated_at` + +It gave those fields the type `string|null` but it was unclear whether it should be a Unix epoch in milliseconds or [ISO 8601](https://www.iso.org/iso-8601-date-and-time-format.html). Upon having to revisit this, it was determined to be the most efficient to use epoch milliseconds as it would reduce the computation on the smart contract and can be derived trivially from the block timestamp. + +## Copyright +[copyright]: #copyright + +Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). \ No newline at end of file diff --git a/neps/nep-0178.md b/neps/nep-0178.md new file mode 100644 index 000000000..cde0ea2c6 --- /dev/null +++ b/neps/nep-0178.md @@ -0,0 +1,471 @@ +--- +NEP: 178 +Title: Non Fungible Token Approval Management +Author: Chad Ostrowski <@chadoh>, Thor <@thor314> +DiscussionsTo: https://github.com/near/NEPs/discussions/178 +Status: Final +Type: Standards Track +Category: Contract +Created: 03-Mar-2022 +Requires: 171 +--- + +## Summary + +A system for allowing a set of users or contracts to transfer specific Non-Fungible Tokens on behalf of an owner. Similar to approval management systems in standards like [ERC-721]. + + [ERC-721]: https://eips.ethereum.org/EIPS/eip-721 + +## Motivation + +People familiar with [ERC-721] may expect to need an approval management system for basic transfers, where a simple transfer from Alice to Bob requires that Alice first _approve_ Bob to spend one of her tokens, after which Bob can call `transfer_from` to actually transfer the token to himself. + +## Rationale and alternatives + +NEAR's [core Non-Fungible Token standard](Core.md) includes good support for safe atomic transfers without such complexity. It even provides "transfer and call" functionality (`nft_transfer_call`) which allows a specific token to be "attached" to a call to a separate contract. For many Non-Fungible Token workflows, these options may circumvent the need for a full-blown Approval Managament system. + +However, some Non-Fungible Token developers, marketplaces, dApps, or artists may require greater control. This standard provides a uniform interface allowing token owners to approve other NEAR accounts, whether individuals or contracts, to transfer specific tokens on the owner's behalf. + +Prior art: + +- Ethereum's [ERC-721] +- [NEP-4](https://github.com/near/NEPs/pull/4), NEAR's old NFT standard that does not include approved_account_ids per token ID + +## Specification + +## Example Scenarios + +Let's consider some examples. Our cast of characters & apps: + +* Alice: has account `alice` with no contract deployed to it +* Bob: has account `bob` with no contract deployed to it +* NFT: a contract with account `nft`, implementing only the [Core NFT standard](Core.md) with this Approval Management extension +* Market: a contract with account `market` which sells tokens from `nft` as well as other NFT contracts +* Bazaar: similar to Market, but implemented differently (spoiler alert: has no `nft_on_approve` function!), has account `bazaar` + +Alice and Bob are already [registered](../StorageManagement.md) with NFT, Market, and Bazaar, and Alice owns a token on the NFT contract with ID=`"1"`. + +Let's examine the technical calls through the following scenarios: + +1. [Simple approval](#1-simple-approval): Alice approves Bob to transfer her token. +2. [Approval with cross-contract call (XCC)](#2-approval-with-cross-contract-call): Alice approves Market to transfer one of her tokens and passes `msg` so that NFT will call `nft_on_approve` on Market's contract. +3. [Approval with XCC, edge case](#3-approval-with-cross-contract-call-edge-case): Alice approves Bazaar and passes `msg` again, but what's this? Bazaar doesn't implement `nft_on_approve`, so Alice sees an error in the transaction result. Not to worry, though, she checks `nft_is_approved` and sees that she did successfully approve Bazaar, despite the error. +4. [Approval IDs](#4-approval-ids): Bob buys Alice's token via Market. +5. [Approval IDs, edge case](#5-approval-ids-edge-case): Bob transfers same token back to Alice, Alice re-approves Market & Bazaar. Bazaar has an outdated cache. Bob tries to buy from Bazaar at the old price. +6. [Revoke one](#6-revoke-one): Alice revokes Market's approval for this token. +7. [Revoke all](#7-revoke-all): Alice revokes all approval for this token. + +### 1. Simple Approval + +Alice approves Bob to transfer her token. + +**High-level explanation** + +1. Alice approves Bob +2. Alice queries the token to verify +3. Alice verifies a different way + +**Technical calls** + +1. Alice calls `nft::nft_approve({ "token_id": "1", "account_id": "bob" })`. She attaches 1 yoctoⓃ, (.000000000000000000000001Ⓝ). Using [NEAR CLI](https://docs.near.org/docs/tools/near-cli) to make this call, the command would be: + + near call nft nft_approve \ + '{ "token_id": "1", "account_id": "bob" }' \ + --accountId alice --depositYocto 1 + + The response: + + '' + +2. Alice calls view method `nft_token`: + + near view nft nft_token \ + '{ "token_id": "1" }' + + The response: + + { + "token_id": "1", + "owner_id": "alice.near", + "approved_account_ids": { + "bob": 1, + } + } + +3. Alice calls view method `nft_is_approved`: + + near view nft nft_is_approved \ + '{ "token_id": "1", "approved_account_id": "bob" }' + + The response: + + true + +### 2. Approval with cross-contract call + +Alice approves Market to transfer one of her tokens and passes `msg` so that NFT will call `nft_on_approve` on Market's contract. She probably does this via Market's frontend app which would know how to construct `msg` in a useful way. + +**High-level explanation** + +1. Alice calls `nft_approve` to approve `market` to transfer her token, and passes a `msg` +2. Since `msg` is included, `nft` will schedule a cross-contract call to `market` +3. Market can do whatever it wants with this info, such as listing the token for sale at a given price. The result of this operation is returned as the promise outcome to the original `nft_approve` call. + +**Technical calls** + +1. Using near-cli: + + near call nft nft_approve '{ + "token_id": "1", + "account_id": "market", + "msg": "{\"action\": \"list\", \"price\": \"100\", \"token\": \"nDAI\" }" + }' --accountId alice --depositYocto 1 + + At this point, near-cli will hang until the cross-contract call chain fully resolves, which would also be true if Alice used a Market frontend using [near-api-js](https://docs.near.org/docs/develop/front-end/near-api-js). Alice's part is done, though. The rest happens behind the scenes. + +2. `nft` schedules a call to `nft_on_approve` on `market`. Using near-cli notation for easy cross-reference with the above, this would look like: + + near call market nft_on_approve '{ + "token_id": "1", + "owner_id": "alice", + "approval_id": 2, + "msg": "{\"action\": \"list\", \"price\": \"100\", \"token\": \"nDAI\" }" + }' --accountId nft + +3. `market` now knows that it can sell Alice's token for 100 [nDAI](https://explorer.mainnet.near.org/accounts/6b175474e89094c44da98b954eedeac495271d0f.factory.bridge.near), and that when it transfers it to a buyer using `nft_transfer`, it can pass along the given `approval_id` to ensure that Alice hasn't changed her mind. It can schedule any further cross-contract calls it wants, and if it returns these promises correctly, Alice's initial near-cli call will resolve with the outcome from the final step in the chain. If Alice actually made this call from a Market frontend, the frontend can use this return value for something useful. + +### 3. Approval with cross-contract call, edge case + +Alice approves Bazaar and passes `msg` again. Maybe she actually does this via near-cli, rather than using Bazaar's frontend, because what's this? Bazaar doesn't implement `nft_on_approve`, so Alice sees an error in the transaction result. + +Not to worry, though, she checks `nft_is_approved` and sees that she did successfully approve Bazaar, despite the error. She will have to find a new way to list her token for sale in Bazaar, rather than using the same `msg` shortcut that worked for Market. + +**High-level explanation** + +1. Alice calls `nft_approve` to approve `bazaar` to transfer her token, and passes a `msg`. +2. Since `msg` is included, `nft` will schedule a cross-contract call to `bazaar`. +3. Bazaar doesn't implement `nft_on_approve`, so this call results in an error. The approval still worked, but Alice sees an error in her near-cli output. +4. Alice checks if `bazaar` is approved, and sees that it is, despite the error. + +**Technical calls** + +1. Using near-cli: + + near call nft nft_approve '{ + "token_id": "1", + "account_id": "bazaar", + "msg": "{\"action\": \"list\", \"price\": \"100\", \"token\": \"nDAI\" }" + }' --accountId alice --depositYocto 1 + +2. `nft` schedules a call to `nft_on_approve` on `market`. Using near-cli notation for easy cross-reference with the above, this would look like: + + near call bazaar nft_on_approve '{ + "token_id": "1", + "owner_id": "alice", + "approval_id": 3, + "msg": "{\"action\": \"list\", \"price\": \"100\", \"token\": \"nDAI\" }" + }' --accountId nft + +3. 💥 `bazaar` doesn't implement this method, so the call results in an error. Alice sees this error in the output from near-cli. + +4. Alice checks if the approval itself worked, despite the error on the cross-contract call: + + near view nft nft_is_approved \ + '{ "token_id": "1", "approved_account_id": "bazaar" }' + + The response: + + true + +### 4. Approval IDs + +Bob buys Alice's token via Market. Bob probably does this via Market's frontend, which will probably initiate the transfer via a call to `ft_transfer_call` on the nDAI contract to transfer 100 nDAI to `market`. Like the NFT standard's "transfer and call" function, [Fungible Token](../FungibleToken/Core.md)'s `ft_transfer_call` takes a `msg` which `market` can use to pass along information it will need to pay Alice and actually transfer the NFT. The actual transfer of the NFT is the only part we care about here. + +**High-level explanation** + +1. Bob signs some transaction which results in the `market` contract calling `nft_transfer` on the `nft` contract, as described above. To be trustworthy and pass security audits, `market` needs to pass along `approval_id` so that it knows it has up-to-date information. + +**Technical calls** + +Using near-cli notation for consistency: + + near call nft nft_transfer '{ + "receiver_id": "bob", + "token_id": "1", + "approval_id": 2, + }' --accountId market --depositYocto 1 + +### 5. Approval IDs, edge case + +Bob transfers same token back to Alice, Alice re-approves Market & Bazaar, listing her token at a higher price than before. Bazaar is somehow unaware of these changes, and still stores `approval_id: 3` internally along with Alice's old price. Bob tries to buy from Bazaar at the old price. Like the previous example, this probably starts with a call to a different contract, which eventually results in a call to `nft_transfer` on `bazaar`. Let's consider a possible scenario from that point. + +**High-level explanation** + +Bob signs some transaction which results in the `bazaar` contract calling `nft_transfer` on the `nft` contract, as described above. To be trustworthy and pass security audits, `bazaar` needs to pass along `approval_id` so that it knows it has up-to-date information. It does not have up-to-date information, so the call fails. If the initial `nft_transfer` call is part of a call chain originating from a call to `ft_transfer_call` on a fungible token, Bob's payment will be refunded and no assets will change hands. + +**Technical calls** + +Using near-cli notation for consistency: + + near call nft nft_transfer '{ + "receiver_id": "bob", + "token_id": "1", + "approval_id": 3, + }' --accountId bazaar --depositYocto 1 + +### 6. Revoke one + +Alice revokes Market's approval for this token. + +**Technical calls** + +Using near-cli: + + near call nft nft_revoke '{ + "account_id": "market", + "token_id": "1", + }' --accountId alice --depositYocto 1 + +Note that `market` will not get a cross-contract call in this case. The implementors of the Market app should implement [cron](https://en.wikipedia.org/wiki/Cron)-type functionality to intermittently check that Market still has the access they expect. + +### 7. Revoke all + +Alice revokes all approval for this token. + +**Technical calls** + +Using near-cli: + + near call nft nft_revoke_all '{ + "token_id": "1", + }' --accountId alice --depositYocto 1 + +Again, note that no previous approvers will get cross-contract calls in this case. + +## Reference-level explanation + +The `Token` structure returned by `nft_token` must include an `approved_account_ids` field, which is a map of account IDs to approval IDs. Using TypeScript's [Record type](https://www.typescriptlang.org/docs/handbook/utility-types.html#recordkeystype) notation: + +```diff +type Token = { + token_id: string, + owner_id: string, ++ approved_account_ids: Record, + } +``` + +Example token data: + +```json +{ + "token_id": "1", + "owner_id": "alice.near", + "approved_account_ids": { + "bob.near": 1, + "carol.near": 2, + } +} +``` + +### What is an "approval ID"? + +This is a unique number given to each approval that allows well-intentioned marketplaces or other 3rd-party NFT resellers to avoid a race condition. The race condition occurs when: + +1. A token is listed in two marketplaces, which are both saved to the token as approved accounts. +2. One marketplace sells the token, which clears the approved accounts. +3. The new owner sells back to the original owner. +4. The original owner approves the token for the second marketplace again to list at a new price. But for some reason the second marketplace still lists the token at the previous price and is unaware of the transfers happening. +5. The second marketplace, operating from old information, attempts to again sell the token at the old price. + +Note that while this describes an honest mistake, the possibility of such a bug can also be taken advantage of by malicious parties via [front-running](https://defi.cx/front-running-ethereum/). + +To avoid this possibility, the NFT contract generates a unique approval ID each time it approves an account. Then when calling `nft_transfer` or `nft_transfer_call`, the approved account passes `approval_id` with this value to make sure the underlying state of the token hasn't changed from what the approved account expects. + +Keeping with the example above, say the initial approval of the second marketplace generated the following `approved_account_ids` data: + +```json +{ + "token_id": "1", + "owner_id": "alice.near", + "approved_account_ids": { + "marketplace_1.near": 1, + "marketplace_2.near": 2, + } +} +``` + +But after the transfers and re-approval described above, the token might have `approved_account_ids` as: + +```json +{ + "token_id": "1", + "owner_id": "alice.near", + "approved_account_ids": { + "marketplace_2.near": 3, + } +} +``` + +The marketplace then tries to call `nft_transfer`, passing outdated information: + +```bash +# oops! +near call nft-contract.near nft_transfer '{ "approval_id": 2 }' +``` + + +### Interface + +The NFT contract must implement the following methods: + +```ts +/******************/ +/* CHANGE METHODS */ +/******************/ + +// Add an approved account for a specific token. +// +// Requirements +// * Caller of the method must attach a deposit of at least 1 yoctoⓃ for +// security purposes +// * Contract MAY require caller to attach larger deposit, to cover cost of +// storing approver data +// * Contract MUST panic if called by someone other than token owner +// * Contract MUST panic if addition would cause `nft_revoke_all` to exceed +// single-block gas limit. See below for more info. +// * Contract MUST increment approval ID even if re-approving an account +// * If successfully approved or if had already been approved, and if `msg` is +// present, contract MUST call `nft_on_approve` on `account_id`. See +// `nft_on_approve` description below for details. +// +// Arguments: +// * `token_id`: the token for which to add an approval +// * `account_id`: the account to add to `approved_account_ids` +// * `msg`: optional string to be passed to `nft_on_approve` +// +// Returns void, if no `msg` given. Otherwise, returns promise call to +// `nft_on_approve`, which can resolve with whatever it wants. +function nft_approve( + token_id: TokenId, + account_id: string, + msg: string|null, +): void|Promise {} + +// Revoke an approved account for a specific token. +// +// Requirements +// * Caller of the method must attach a deposit of 1 yoctoⓃ for security +// purposes +// * If contract requires >1yN deposit on `nft_approve`, contract +// MUST refund associated storage deposit when owner revokes approval +// * Contract MUST panic if called by someone other than token owner +// +// Arguments: +// * `token_id`: the token for which to revoke an approval +// * `account_id`: the account to remove from `approved_account_ids` +function nft_revoke( + token_id: string, + account_id: string +) {} + +// Revoke all approved accounts for a specific token. +// +// Requirements +// * Caller of the method must attach a deposit of 1 yoctoⓃ for security +// purposes +// * If contract requires >1yN deposit on `nft_approve`, contract +// MUST refund all associated storage deposit when owner revokes approved_account_ids +// * Contract MUST panic if called by someone other than token owner +// +// Arguments: +// * `token_id`: the token with approved_account_ids to revoke +function nft_revoke_all(token_id: string) {} + +/****************/ +/* VIEW METHODS */ +/****************/ + +// Check if a token is approved for transfer by a given account, optionally +// checking an approval_id +// +// Arguments: +// * `token_id`: the token for which to revoke an approval +// * `approved_account_id`: the account to check the existence of in `approved_account_ids` +// * `approval_id`: an optional approval ID to check against current approval ID for given account +// +// Returns: +// if `approval_id` given, `true` if `approved_account_id` is approved with given `approval_id` +// otherwise, `true` if `approved_account_id` is in list of approved accounts +function nft_is_approved( + token_id: string, + approved_account_id: string, + approval_id: number|null +): boolean {} +``` + +### Why must `nft_approve` panic if `nft_revoke_all` would fail later? + +In the description of `nft_approve` above, it states: + + Contract MUST panic if addition would cause `nft_revoke_all` to exceed + single-block gas limit. + +What does this mean? + +First, it's useful to understand what we mean by "single-block gas limit". This refers to the [hard cap on gas per block at the protocol layer](https://docs.near.org/docs/concepts/gas#thinking-in-gas). This number will increase over time. + +Removing data from a contract uses gas, so if an NFT had a large enough number of approved_account_ids, `nft_revoke_all` would fail, because calling it would exceed the maximum gas. + +Contracts must prevent this by capping the number of approved_account_ids for a given token. However, it is up to contract authors to determine a sensible cap for their contract (and the single block gas limit at the time they deploy). Since contract implementations can vary, some implementations will be able to support a larger number of approved_account_ids than others, even with the same maximum gas per block. + +Contract authors may choose to set a cap of something small and safe like 10 approved_account_ids, or they could dynamically calculate whether a new approval would break future calls to `nft_revoke_all`. But every contract MUST ensure that they never break the functionality of `nft_revoke_all`. + + +### Approved Account Contract Interface + +If a contract that gets approved to transfer NFTs wants to, it can implement `nft_on_approve` to update its own state when granted approval for a token: + +```ts +// Respond to notification that contract has been granted approval for a token. +// +// Notes +// * Contract knows the token contract ID from `predecessor_account_id` +// +// Arguments: +// * `token_id`: the token to which this contract has been granted approval +// * `owner_id`: the owner of the token +// * `approval_id`: the approval ID stored by NFT contract for this approval. +// Expected to be a number within the 2^53 limit representable by JSON. +// * `msg`: specifies information needed by the approved contract in order to +// handle the approval. Can indicate both a function to call and the +// parameters to pass to that function. +function nft_on_approve( + token_id: TokenId, + owner_id: string, + approval_id: number, + msg: string, +) {} +``` + +Note that the NFT contract will fire-and-forget this call, ignoring any return values or errors generated. This means that even if the approved account does not have a contract or does not implement `nft_on_approve`, the approval will still work correctly from the point of view of the NFT contract. + +Further note that there is no parallel `nft_on_revoke` when revoking either a single approval or when revoking all. This is partially because scheduling many `nft_on_revoke` calls when revoking all approved_account_ids could incur prohibitive [gas fees](https://docs.near.org/docs/concepts/gas). Apps and contracts which cache NFT approved_account_ids can therefore not rely on having up-to-date information, and should periodically refresh their caches. Since this will be the necessary reality for dealing with `nft_revoke_all`, there is no reason to complicate `nft_revoke` with an `nft_on_revoke` call. + +### No incurred cost for core NFT behavior + +NFT contracts should be implemented in a way to avoid extra gas fees for serialization & deserialization of `approved_account_ids` for calls to `nft_*` methods other than `nft_token`. See `near-contract-standards` [implementation of `ft_metadata` using `LazyOption`](https://github.com/near/near-sdk-rs/blob/c2771af7fdfe01a4e8414046752ee16fb0d29d39/examples/fungible-token/ft/src/lib.rs#L71) as a reference example. + +## Reference Implementation + +[NFT Approval Receiver Interface](https://github.com/near/near-sdk-rs/blob/master/near-contract-standards/src/non_fungible_token/approval/approval_receiver.rs) + +[NFT Approval Implementation](https://github.com/near/near-sdk-rs/blob/master/near-contract-standards/src/non_fungible_token/approval/approval_impl.rs) + +## Errata + +* **2022-02-03**: updated `Token` struct field names. `id` was changed to `token_id` and `approvals` was changed to `approved_account_ids`. This is to be consistent with current implementations of the standard and the rust SDK docs. + +## Copyright +[copyright]: #copyright + +Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). \ No newline at end of file diff --git a/neps/nep-0181.md b/neps/nep-0181.md new file mode 100644 index 000000000..2ba0cd862 --- /dev/null +++ b/neps/nep-0181.md @@ -0,0 +1,96 @@ +--- +NEP: 181 +Title: Non Fungible Token Enumeration +Author: Chad Ostrowski <@chadoh>, Thor <@thor314> +DiscussionsTo: https://github.com/near/NEPs/discussions/181 +Status: Final +Type: Standards Track +Category: Contract +Created: 03-Mar-2022 +Requires: 171 +--- + +## Summary + +Standard interfaces for counting & fetching tokens, for an entire NFT contract or for a given owner. + +## Motivation + +Apps such as marketplaces and wallets need a way to show all tokens owned by a given account and to show statistics about all tokens for a given contract. This extension provides a standard way to do so. + +## Rationale and alternatives + +While some NFT contracts may forego this extension to save [storage] costs, this requires apps to have custom off-chain indexing layers. This makes it harder for apps to integrate with such NFTs. Apps which integrate only with NFTs that use the Enumeration extension do not even need a server-side component at all, since they can retrieve all information they need directly from the blockchain. + +Prior art: + +- [ERC-721]'s enumeration extension + +## Specification + +The contract must implement the following view methods: + +```ts +// Returns the total supply of non-fungible tokens as a string representing an +// unsigned 128-bit integer to avoid JSON number limit of 2^53; and "0" if there are no tokens. +function nft_total_supply(): string {} + +// Get a list of all tokens +// +// Arguments: +// * `from_index`: a string representing an unsigned 128-bit integer, +// representing the starting index of tokens to return +// * `limit`: the maximum number of tokens to return +// +// Returns an array of Token objects, as described in Core standard, and an empty array if there are no tokens +function nft_tokens( + from_index: string|null, // default: "0" + limit: number|null, // default: unlimited (could fail due to gas limit) +): Token[] {} + +// Get number of tokens owned by a given account +// +// Arguments: +// * `account_id`: a valid NEAR account +// +// Returns the number of non-fungible tokens owned by given `account_id` as +// a string representing the value as an unsigned 128-bit integer to avoid JSON +// number limit of 2^53; and "0" if there are no tokens. +function nft_supply_for_owner( + account_id: string, +): string {} + +// Get list of all tokens owned by a given account +// +// Arguments: +// * `account_id`: a valid NEAR account +// * `from_index`: a string representing an unsigned 128-bit integer, +// representing the starting index of tokens to return +// * `limit`: the maximum number of tokens to return +// +// Returns a paginated list of all tokens owned by this account, and an empty array if there are no tokens +function nft_tokens_for_owner( + account_id: string, + from_index: string|null, // default: 0 + limit: number|null, // default: unlimited (could fail due to gas limit) +): Token[] {} +``` + +## Notes + +At the time of this writing, the specialized collections in the `near-sdk` Rust crate are iterable, but not all of them have implemented an `iter_from` solution. There may be efficiency gains for large collections and contract developers are encouraged to test their data structures with a large amount of entries. + + [ERC-721]: https://eips.ethereum.org/EIPS/eip-721 + [storage]: https://docs.near.org/docs/concepts/storage-staking + + +## Reference Implementation + +[Minimum Viable Interface](https://github.com/near/near-sdk-rs/blob/master/near-contract-standards/src/non_fungible_token/enumeration/mod.rs) + +[Implementation](https://github.com/near/near-sdk-rs/blob/master/near-contract-standards/src/non_fungible_token/enumeration/enumeration_impl.rs) + +## Copyright +[copyright]: #copyright + +Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). \ No newline at end of file diff --git a/neps/nep-0199.md b/neps/nep-0199.md new file mode 100644 index 000000000..92c51f4bf --- /dev/null +++ b/neps/nep-0199.md @@ -0,0 +1,117 @@ +--- +NEP: 199 +Title: Non Fungible Token Royalties and Payouts +Author: Thor <@thor314>, Matt Lockyer <@mattlockyer> +DiscussionsTo: https://github.com/near/NEPs/discussions/199 +Status: Final +Type: Standards Track +Category: Contract +Created: 03-Mar-2022 +Requires: 171, 178 +--- + +## Summary + +An interface allowing non-fungible token contracts to request that financial contracts pay-out multiple receivers, enabling flexible royalty implementations. + +## Motivation + +Currently, NFTs on NEAR support the field `owner_id`, but lack flexibility for ownership and payout mechanics with more complexity, including but not limited to royalties. Financial contracts, such as marketplaces, auction houses, and NFT Loan contracts would benefit from a standard interface on NFT producer contracts for querying whom to pay out, and how much to pay. + +Therefore, the core goal of this standard is to define a set of methods for financial contracts to call, without specifying how NFT contracts define the divide of payout mechanics, and a standard `Payout` response structure. + + +## Specification + +This Payout extension standard adds two methods to NFT contracts: +- a view method: `nft_payout`, accepting a `token_id` and some `balance`, returning the `Payout` mapping for the given token. +- a call method: `nft_transfer_payout`, accepting all the arguments of`nft_transfer`, plus a field for some `Balance` that calculates the `Payout`, calls `nft_transfer`, and returns the `Payout` mapping. + +Financial contracts MUST validate several invariants on the returned +`Payout`: +1. The returned `Payout` MUST be no longer than the given maximum length (`max_len_payout` parameter) if provided. Payouts of excessive length can become prohibitively gas-expensive. Financial contracts can specify the maximum length of payout the contract is willing to respect with the `max_len_payout` field on `nft_transfer_payout`. +2. The balances MUST add up to less than or equal to the `balance` argument in `nft_transfer_payout`. If the balance adds up to less than the `balance` argument, the financial contract MAY claim the remainder for itself. +3. The sum of the balances MUST NOT overflow. This is technically identical to 2, but financial contracts should be expected to handle this possibility. + +Financial contracts MAY specify their own maximum length payout to respect. +At minimum, financial contracts MUST NOT set their maximum length below 10. + +If the Payout contains any addresses that do not exist, the financial contract MAY keep those wasted payout funds. + +Financial contracts MAY take a cut of the NFT sale price as commission, subtracting their cut from the total token sale price, and calling `nft_transfer_payout` with the remainder. + +## Example Flow +``` + ┌─────────────────────────────────────────────────┐ + │Token Owner approves marketplace for token_id "0"│ + ├─────────────────────────────────────────────────┘ + │ nft_approve("0",market.near,) + ▼ + ┌───────────────────────────────────────────────┐ + │Marketplace sells token to user.near for 10N │ + ├───────────────────────────────────────────────┘ + │ nft_transfer_payout(user.near,"0",0,"10000000",5) + ▼ + ┌───────────────────────────────────────────────┐ + │NFT contract returns Payout data │ + ├───────────────────────────────────────────────┘ + │ Payout(, +} + +pub trait Payouts{ + /// Given a `token_id` and NEAR-denominated balance, return the `Payout`. + /// struct for the given token. Panic if the length of the payout exceeds + /// `max_len_payout.` + fn nft_payout(&self, token_id: String, balance: U128, max_len_payout: u32) -> Payout; + /// Given a `token_id` and NEAR-denominated balance, transfer the token + /// and return the `Payout` struct for the given token. Panic if the + /// length of the payout exceeds `max_len_payout.` + #[payable] + fn nft_transfer_payout( + &mut self, + receiver_id: AccountId, + token_id: String, + approval_id: u64, + balance: U128, + max_len_payout: u32, + ) -> Payout{ + assert_one_yocto(); + let payout = self.nft_payout(token_id, balance); + self.nft_transfer(receiver_id, token_id, approval_id); + payout + } +} +``` + +Note that NFT and financial contracts will vary in implementation. This means that some extra CPU cycles may occur in one NFT contract and not another. Furthermore, a financial contract may accept fungible tokens, native NEAR, or another entity as payment. Transferring native NEAR tokens is less expensive in gas than sending fungible tokens. For these reasons, the maximum length of payouts may vary according to the customization of the smart contracts. + +## Future possibilities + +In the future, the NFT contract itself may be able to place an NFT transfer is a state that is "pending transfer" until all payouts have been awarded. This would keep all the information inside the NFT and remove trust. + +## Errata + +Version `2.0.0` contains the intended `approval_id` of `u64` instead of the stringified `U64` version. This was an oversight, but since the standard was live for a few months before noticing, the team thought it best to bump the major version. + +## Copyright +[copyright]: #copyright + +Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). \ No newline at end of file diff --git a/neps/nep-0297.md b/neps/nep-0297.md new file mode 100644 index 000000000..7be93307c --- /dev/null +++ b/neps/nep-0297.md @@ -0,0 +1,139 @@ +--- +NEP: 297 +Title: Events +Author: Olga Telezhnaya +DiscussionsTo: https://github.com/near/NEPs/issues/297 +Status: Final +Type: Standards Track +Category: Contract +Created: 03-Mar-2022 +--- + +## Summary + +Events format is a standard interface for tracking contract activity. +This document is a meta-part of other standards, such as [NEP-141](https://github.com/near/NEPs/issues/141) or [NEP-171](https://github.com/near/NEPs/discussions/171). + +## Motivation + +Apps usually perform many similar actions. +Each app may have its own way of performing these actions, introducing inconsistency in capturing these events. + +NEAR and third-party applications need to track these and similar events consistently. +If not, tracking state across many apps becomes infeasible. +Events address this issue, providing other applications with the needed standardized data. + +Initial discussion is [here](https://github.com/near/NEPs/issues/254). + +## Rationale and alternatives +[rationale-and-alternatives]: #rationale-and-alternatives + +- Why is this design the best in the space of possible designs? +- What other designs have been considered and what is the rationale for not choosing them? +- What is the impact of not doing this? + +## Specification + +Many apps use different interfaces that represent the same action. +This interface standardizes that process by introducing event logs. + +Events use the standard logs capability of NEAR. +Events are log entries that start with the `EVENT_JSON:` prefix followed by a single valid JSON string. +JSON string may have any number of space characters in the beginning, the middle, or the end of the string. +It's guaranteed that space characters do not break its parsing. +All the examples below are pretty-formatted for better readability. + +JSON string should have the following interface: + +```ts +// Interface to capture data about an event +// Arguments +// * `standard`: name of standard, e.g. nep171 +// * `version`: e.g. 1.0.0 +// * `event`: type of the event, e.g. nft_mint +// * `data`: associate event data. Strictly typed for each set {standard, version, event} inside corresponding NEP +interface EventLogData { + standard: string, + version: string, + event: string, + data?: unknown, +} +``` + +Thus, to emit an event, you only need to log a string following the rules above. Here is a barebones example using Rust SDK `near_sdk::log!` macro (security note: prefer using `serde_json` or alternatives to serialize the JSON string to avoid potential injections and corrupted events): +```rust +use near_sdk::log; + +// ... +log!( + r#"EVENT_JSON:{"standard": "nepXXX", "version": "1.0.0", "event": "YYY", "data": {"token_id": "{}"}}"#, + token_id +); +// ... +``` + +#### Valid event logs: + +```js +EVENT_JSON:{ + "standard": "nepXXX", + "version": "1.0.0", + "event": "xyz_is_triggered" +} +``` + +```js +EVENT_JSON:{ + "standard": "nepXXX", + "version": "1.0.0", + "event": "xyz_is_triggered", + "data": { + "triggered_by": "foundation.near" + } +} +``` + +#### Invalid event logs: + +* Two events in a single log entry (instead, call `log` for each individual event) +```js +EVENT_JSON:{ + "standard": "nepXXX", + "version": "1.0.0", + "event": "abc_is_triggered" +} +EVENT_JSON:{ + "standard": "nepXXX", + "version": "1.0.0", + "event": "xyz_is_triggered" +} +``` +* Invalid JSON data +```js +EVENT_JSON:invalid json +``` +* Missing required fields `standard`, `version` or `event` +```js +EVENT_JSON:{ + "standard": "nepXXX", + "event": "xyz_is_triggered", + "data": { + "triggered_by": "foundation.near" + } +} +``` + +## Reference Implementation + +[Fungible Token Events Implementation](https://github.com/near/near-sdk-rs/blob/master/near-contract-standards/src/fungible_token/events.rs) + +[Non-Fungible Token Events Implementation](https://github.com/near/near-sdk-rs/blob/master/near-contract-standards/src/non_fungible_token/events.rs) + +## Drawbacks +There is a known limitation of 16kb strings when capturing logs. +This impacts the amount of events that can be processed. + +## Copyright +[copyright]: #copyright + +Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). \ No newline at end of file From a3ee96a7e2a66acdf1c643908fd5ecef147ed49f Mon Sep 17 00:00:00 2001 From: Jay Logelin Date: Mon, 21 Mar 2022 17:18:19 -0300 Subject: [PATCH 007/150] Update README.md (#338) * Update README.md * Updated title of contract events standard in README --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 69e289b48..752a6bad6 100644 --- a/README.md +++ b/README.md @@ -84,7 +84,7 @@ Tip: build consensus and integrate feedback. NEPs that have broad support are mu |NEP # | Title | Author | Status | |---|---|---|---| -|[0001](https://github.com/near/NEPs/blob/master/neps/nep-0001.md) | FIP Purpose and Guidelines | @jlogelin | Active | +|[0001](https://github.com/near/NEPs/blob/master/neps/nep-0001.md) | NEP Purpose and Guidelines | @jlogelin | Active | |[0021](https://github.com/near/NEPs/blob/master/neps/nep-0021.md) | Fungible Token Standard (Deprecated) | @aevgenykuzyakov | Final | |[0141](https://github.com/near/NEPs/blob/master/neps/nep-0141.md) | Fungible Token Standard | @aevgenykuzyakov @oysterpack | Final | |[0145](https://github.com/near/NEPs/blob/master/neps/nep-0145.md) | Storage Management | @aevgenykuzyakov | Final | @@ -94,4 +94,4 @@ Tip: build consensus and integrate feedback. NEPs that have broad support are mu |[0178](https://github.com/near/NEPs/blob/master/neps/nep-0178.md) | Non Fungible Token Approval Management | @chadoh @thor314 | Final | |[0181](https://github.com/near/NEPs/blob/master/neps/nep-0181.md) | Non Fungible Token Enumeration | @chadoh @thor314 | Final | |[0199](https://github.com/near/NEPs/blob/master/neps/nep-0199.md) | Non Fungible Token Royalties and Payouts | @thor314 @mattlockyer | Final | -|[0297](https://github.com/near/NEPs/blob/master/neps/nep-0297.md) | Non Fungible Token Royalties and Payouts | @telezhnaya | Final | +|[0297](https://github.com/near/NEPs/blob/master/neps/nep-0297.md) | Contract Events Standard | @telezhnaya | Final | From a80507b292e05631fd11335a4625124af10c63d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dami=C3=A1n=20Parrino?= Date: Wed, 23 Mar 2022 19:11:25 -0300 Subject: [PATCH 008/150] Add link check (#339) * Add link check * Update mlc_config.json --- .github/workflows/links.yml | 15 +++++++++++++++ specs/DataStructures/AccessKey.md | 4 ++-- specs/Proposals/0005-access-keys.md | 2 +- specs/Proposals/0006-bindings.md | 2 +- specs/Proposals/0013-system-methods.md | 4 ++-- specs/RuntimeSpec/Actions.md | 4 ++-- .../Components/BindingsSpec/PromisesAPI.md | 4 ++-- specs/Standards/FungibleToken/Core.md | 2 +- specs/Standards/FungibleToken/Metadata.md | 4 +++- specs/Standards/NonFungibleToken/Metadata.md | 2 +- website/docusaurus.config.js | 4 ++++ website/mlc_config.json | 15 +++++++++++++++ 12 files changed, 49 insertions(+), 13 deletions(-) create mode 100644 .github/workflows/links.yml create mode 100644 website/mlc_config.json diff --git a/.github/workflows/links.yml b/.github/workflows/links.yml new file mode 100644 index 000000000..f53d968b7 --- /dev/null +++ b/.github/workflows/links.yml @@ -0,0 +1,15 @@ +name: Check Markdown links + +on: push + +jobs: + markdown-link-check: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@master + - uses: gaurav-nelson/github-action-markdown-link-check@v1 + with: + use-quiet-mode: 'yes' +# use-verbose-mode: 'yes' + config-file: 'website/mlc_config.json' + folder-path: 'specs' diff --git a/specs/DataStructures/AccessKey.md b/specs/DataStructures/AccessKey.md index 20f5512ab..9ec66c3ae 100644 --- a/specs/DataStructures/AccessKey.md +++ b/specs/DataStructures/AccessKey.md @@ -15,7 +15,7 @@ pub struct AccessKey { } ``` -There are 2 types of `AccessKeyPermission` in Near currently: `FullAccess` and `FunctionCall`. `FunctionCall` grants a permission to issue any action on account like [DeployContract](Transaction#DeployContract), [Transfer](Transaction#Transfer) tokens to other account, call functions [FunctionCall](Transaction#FunctionCall), [Stake](Transaction#Stake) and even delete account [DeleteAccountAction](Transaction#DeleteAccountAction). `FullAccess` also allow to manage access keys. `AccessKeyPermission::FunctionCall` limits to do only contract calls. +There are 2 types of `AccessKeyPermission` in Near currently: `FullAccess` and `FunctionCall`. `FunctionCall` grants a permission to issue any action on account like [DeployContract](Transaction.md#DeployContract), [Transfer](Transaction.md#Transfer) tokens to other account, call functions [FunctionCall](Transaction.md#FunctionCall), [Stake](Transaction.md#Stake) and even delete account [DeleteAccountAction](Transaction.md#DeleteAccountAction). `FullAccess` also allow to manage access keys. `AccessKeyPermission::FunctionCall` limits to do only contract calls. ```rust pub enum AccessKeyPermission { @@ -26,7 +26,7 @@ pub enum AccessKeyPermission { ## AccessKeyPermission::FunctionCall -Grants limited permission to make [FunctionCall](Transaction#FunctionCall) to a specified `receiver_id` and methods of a particular contract with a limit of allowed balance to spend. +Grants limited permission to make [FunctionCall](Transaction.md#FunctionCall) to a specified `receiver_id` and methods of a particular contract with a limit of allowed balance to spend. ```rust pub struct FunctionCallPermission { diff --git a/specs/Proposals/0005-access-keys.md b/specs/Proposals/0005-access-keys.md index c72549d92..982435538 100644 --- a/specs/Proposals/0005-access-keys.md +++ b/specs/Proposals/0005-access-keys.md @@ -1,6 +1,6 @@ - Proposal Code Name: access_keys - Start Date: 2019-07-08 -- NEP PR: [nearprotocol/neps#0000](https://github.com/nearprotocol/neps/pull/0000) +- NEP PR: [nearprotocol/neps#0000](https://github.com/near/NEPs/blob/master/nep-0000-template.md) - Issue(s): [nearprotocol/nearcore#687](https://github.com/nearprotocol/nearcore/issues/687) # Summary diff --git a/specs/Proposals/0006-bindings.md b/specs/Proposals/0006-bindings.md index d3724dc98..5d65d962c 100644 --- a/specs/Proposals/0006-bindings.md +++ b/specs/Proposals/0006-bindings.md @@ -1,6 +1,6 @@ - Proposal Name: `wasm_bindings` - Start Date: 2019-07-22 -- NEP PR: [nearprotocol/neps#0000](https://github.com/nearprotocol/neps/pull/0000) +- NEP PR: [nearprotocol/neps#0000](https://github.com/near/NEPs/blob/master/nep-0000-template.md) # Summary [summary]: #summary diff --git a/specs/Proposals/0013-system-methods.md b/specs/Proposals/0013-system-methods.md index d06d1607e..ed14e0892 100644 --- a/specs/Proposals/0013-system-methods.md +++ b/specs/Proposals/0013-system-methods.md @@ -156,7 +156,7 @@ promise_batch_action_add_key_with_full_access(promise_idx: u64, ``` Appends `AddKey` action to the batch of actions for the given promise pointed by `promise_idx`. Details for the action: https://github.com/nearprotocol/NEPs/pull/8/files#diff-15b6752ec7d78e7b85b8c7de4a19cbd4R54 -The access key will have `FullAccess` permission, details: https://github.com/nearprotocol/NEPs/blob/master/text/0005-access-keys.md#guide-level-explanation +The access key will have `FullAccess` permission, details: [0005-access-keys.md#guide-level-explanation](click here) ###### Panics * If `promise_idx` does not correspond to an existing promise panics with `InvalidPromiseIndex`. @@ -179,7 +179,7 @@ promise_batch_action_add_key_with_function_call(promise_idx: u64, ``` Appends `AddKey` action to the batch of actions for the given promise pointed by `promise_idx`. Details for the action: https://github.com/nearprotocol/NEPs/pull/8/files#diff-156752ec7d78e7b85b8c7de4a19cbd4R54 -The access key will have `FunctionCall` permission, details: https://github.com/nearprotocol/NEPs/blob/master/text/0005-access-keys.md#guide-level-explanation +The access key will have `FunctionCall` permission, details: [0005-access-keys.md#guide-level-explanation](click here) * If the `allowance` value (not the pointer) is `0`, the allowance is set to `None` (which means unlimited allowance). And positive value represents a `Some(...)` allowance. * Given `method_names` is a `utf-8` string with `,` used as a separator. The vm will split the given string into a vector of strings. diff --git a/specs/RuntimeSpec/Actions.md b/specs/RuntimeSpec/Actions.md index d95a0fe9c..7c5622533 100644 --- a/specs/RuntimeSpec/Actions.md +++ b/specs/RuntimeSpec/Actions.md @@ -184,7 +184,7 @@ pub struct AddKeyAction { ``` **Outcome**: -- Adds a new [AccessKey](../DataStructures/AccessKey) to the receiver's account and associates it with a `public_key` provided. +- Adds a new [AccessKey](/DataStructures/AccessKey.md) to the receiver's account and associates it with a `public_key` provided. ### Errors: @@ -228,7 +228,7 @@ pub struct DeleteKeyAction { ``` **Outcome**: -- Deletes the [AccessKey](../DataStructures/AccessKey) associated with `public_key`. +- Deletes the [AccessKey](/DataStructures/AccessKey.md) associated with `public_key`. ### Errors diff --git a/specs/RuntimeSpec/Components/BindingsSpec/PromisesAPI.md b/specs/RuntimeSpec/Components/BindingsSpec/PromisesAPI.md index e63cb0f08..5a9afb515 100644 --- a/specs/RuntimeSpec/Components/BindingsSpec/PromisesAPI.md +++ b/specs/RuntimeSpec/Components/BindingsSpec/PromisesAPI.md @@ -274,7 +274,7 @@ promise_batch_action_add_key_with_full_access(promise_idx: u64, Appends `AddKey` action to the batch of actions for the given promise pointed by `promise_idx`. Details for the action: https://github.com/nearprotocol/NEPs/pull/8/files#diff-15b6752ec7d78e7b85b8c7de4a19cbd4R54 -The access key will have `FullAccess` permission, details: https://github.com/nearprotocol/NEPs/blob/master/text/0005-access-keys.md#guide-level-explanation +The access key will have `FullAccess` permission, details: [/Proposals/0005-access-keys.md#guide-level-explanation](click here) ###### Panics @@ -300,7 +300,7 @@ promise_batch_action_add_key_with_function_call(promise_idx: u64, Appends `AddKey` action to the batch of actions for the given promise pointed by `promise_idx`. Details for the action: https://github.com/nearprotocol/NEPs/pull/8/files#diff-156752ec7d78e7b85b8c7de4a19cbd4R54 -The access key will have `FunctionCall` permission, details: https://github.com/nearprotocol/NEPs/blob/master/text/0005-access-keys.md#guide-level-explanation +The access key will have `FunctionCall` permission, details: [/Proposals/0005-access-keys.md#guide-level-explanation](click here) - If the `allowance` value (not the pointer) is `0`, the allowance is set to `None` (which means unlimited allowance). And positive value represents a `Some(...)` allowance. - Given `method_names` is a `utf-8` string with `,` used as a separator. The vm will split the given string into a vector of strings. diff --git a/specs/Standards/FungibleToken/Core.md b/specs/Standards/FungibleToken/Core.md index 4a5e98246..9aad27a68 100644 --- a/specs/Standards/FungibleToken/Core.md +++ b/specs/Standards/FungibleToken/Core.md @@ -30,7 +30,7 @@ Prior art: Learn about NEP-141: -- [Figment Learning Pathway](https://learn.figment.io/network-documentation/near/tutorials/1-project_overview/2-fungible-token) +- [Figment Learning Pathway](https://learn.figment.io/tutorials/stake-fungible-token) ## Guide-level explanation diff --git a/specs/Standards/FungibleToken/Metadata.md b/specs/Standards/FungibleToken/Metadata.md index 2c8ba6fb3..4dba6d3be 100644 --- a/specs/Standards/FungibleToken/Metadata.md +++ b/specs/Standards/FungibleToken/Metadata.md @@ -44,6 +44,7 @@ Alice issues a transaction to deploy and initialize the fungible token contract, 1. `alice` deploys a contract and calls `wbtc::new` with all metadata. If this deploy and initialization were done using [NEAR CLI](https://docs.near.org/docs/tools/near-cli) the command would be: +```sh near deploy wbtc --wasmFile res/ft.wasm --initFunction new --initArgs '{ "owner_id": "wbtc", "total_supply": "100000000000000", @@ -57,6 +58,7 @@ Alice issues a transaction to deploy and initialize the fungible token contract, "decimals": 8 } }' --accountId alice +``` ## Reference-level explanation @@ -90,7 +92,7 @@ type FungibleTokenMetadata = { **An implementing contract MAY include the following fields on-chain** - `icon`: a small image associated with this token. Must be a [data URL](https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/Data_URIs), to help consumers display it quickly while protecting user data. Recommendation: use [optimized SVG](https://codepen.io/tigt/post/optimizing-svgs-in-data-uris), which can result in high-resolution images with only 100s of bytes of [storage cost](https://docs.near.org/docs/concepts/storage-staking). (Note that these storage costs are incurred to the token owner/deployer, but that querying these icons is a very cheap & cacheable read operation for all consumers of the contract and the RPC nodes that serve the data.) Recommendation: create icons that will work well with both light-mode and dark-mode websites by either using middle-tone color schemes, or by [embedding `media` queries in the SVG](https://timkadlec.com/2013/04/media-queries-within-svg/). -- `reference`: a link to a valid JSON file containing various keys offering supplementary details on the token. Example: "/ipfs/QmdmQXB2mzChmMeKY47C43LxUdg1NDJ5MWcKMKxDu7RgQm", "https://example.com/token.json", etc. If the information given in this document conflicts with the on-chain attributes, the values in `reference` shall be considered the source of truth. +- `reference`: a link to a valid JSON file containing various keys offering supplementary details on the token. Example: `/ipfs/QmdmQXB2mzChmMeKY47C43LxUdg1NDJ5MWcKMKxDu7RgQm`, `https://example.com/token.json`, etc. If the information given in this document conflicts with the on-chain attributes, the values in `reference` shall be considered the source of truth. - `reference_hash`: the base64-encoded sha256 hash of the JSON file contained in the `reference` field. This is to guard against off-chain tampering. ## Drawbacks diff --git a/specs/Standards/NonFungibleToken/Metadata.md b/specs/Standards/NonFungibleToken/Metadata.md index c0b2aa69e..10e0046fc 100644 --- a/specs/Standards/NonFungibleToken/Metadata.md +++ b/specs/Standards/NonFungibleToken/Metadata.md @@ -80,7 +80,7 @@ A new attribute MUST be added to each `Token` struct: For `NFTContractMetadata`: - `icon`: a small image associated with this contract. Encouraged to be a [data URL](https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/Data_URIs), to help consumers display it quickly while protecting user data. Recommendation: use [optimized SVG](https://codepen.io/tigt/post/optimizing-svgs-in-data-uris), which can result in high-resolution images with only 100s of bytes of [storage cost](https://docs.near.org/docs/concepts/storage-staking). (Note that these storage costs are incurred to the contract deployer, but that querying these icons is a very cheap & cacheable read operation for all consumers of the contract and the RPC nodes that serve the data.) Recommendation: create icons that will work well with both light-mode and dark-mode websites by either using middle-tone color schemes, or by [embedding `media` queries in the SVG](https://timkadlec.com/2013/04/media-queries-within-svg/). -- `reference`: a link to a valid JSON file containing various keys offering supplementary details on the token. Example: "/ipfs/QmdmQXB2mzChmMeKY47C43LxUdg1NDJ5MWcKMKxDu7RgQm", "https://example.com/token.json", etc. If the information given in this document conflicts with the on-chain attributes, the values in `reference` shall be considered the source of truth. +- `reference`: a link to a valid JSON file containing various keys offering supplementary details on the token. Example: `/ipfs/QmdmQXB2mzChmMeKY47C43LxUdg1NDJ5MWcKMKxDu7RgQm`, `https://example.com/token.json`, etc. If the information given in this document conflicts with the on-chain attributes, the values in `reference` shall be considered the source of truth. - `reference_hash`: the base64-encoded sha256 hash of the JSON file contained in the `reference` field. This is to guard against off-chain tampering. For `TokenMetadata`: diff --git a/website/docusaurus.config.js b/website/docusaurus.config.js index e71b38970..bf1c32f64 100644 --- a/website/docusaurus.config.js +++ b/website/docusaurus.config.js @@ -53,6 +53,10 @@ const config = { changefreq: 'weekly', priority: 0.5, }, + gtag: { + trackingID: 'G-G8LCVP41F0', + anonymizeIP: true, + }, }), ], ], diff --git a/website/mlc_config.json b/website/mlc_config.json new file mode 100644 index 000000000..d94a1e5aa --- /dev/null +++ b/website/mlc_config.json @@ -0,0 +1,15 @@ +{ + "ignorePatterns": [ + { + "pattern": "^/" + }, + { + "pattern": "^https://codepen.io" + } + ], + "timeout": "20s", + "retryOn429": true, + "retryCount": 5, + "fallbackRetryDelay": "30s", + "aliveStatusCodes": [200, 206] +} From d2dfd94b1ace9d7ada647db3f6cb121480047231 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dami=C3=A1n=20Parrino?= Date: Wed, 23 Mar 2022 19:24:19 -0300 Subject: [PATCH 009/150] Improve FT/NFT sections (#335) Add DocCards --- specs/SUMMARY.md | 74 ---------------------- specs/Standards/FungibleToken/README.md | 9 +-- specs/Standards/NonFungibleToken/README.md | 12 ++-- specs/Standards/README.md | 7 ++ 4 files changed, 17 insertions(+), 85 deletions(-) delete mode 100644 specs/SUMMARY.md diff --git a/specs/SUMMARY.md b/specs/SUMMARY.md deleted file mode 100644 index d473a38c9..000000000 --- a/specs/SUMMARY.md +++ /dev/null @@ -1,74 +0,0 @@ -# Summary - -- [Introduction](README.md) -- [Terminology](Terminology.md) -- [Data Structures](DataStructures/) - - [Account](DataStructures/Account.md) - - [Access Key](DataStructures/AccessKey.md) - - [Transaction](DataStructures/Transaction.md) -- [Architecture](Architecture.md) -- [Chain specification](ChainSpec/) - - [Network specification](NetworkSpec/NetworkSpec.md) - - [Messages](NetworkSpec/Messages.md) - - [RoutingTableExchangeAlgorithm](NetworkSpec/RoutingTableExchangeAlgorithm.md) - - [Consensus](ChainSpec/Consensus.md) - - [Upgradability](ChainSpec/Upgradability.md) - - [Transactions](ChainSpec/Transactions.md) - - [Light Client](ChainSpec/LightClient.md) -- [Runtime specification](RuntimeSpec/) - - [Runtime](RuntimeSpec/Runtime.md) - - [Applying Chunk](RuntimeSpec/ApplyingChunk.md) - - [FunctionCall](RuntimeSpec/FunctionCall.md) - - [Transactions](RuntimeSpec/Transactions.md) - - [Actions](RuntimeSpec/Actions.md) - - [Receipts](RuntimeSpec/Receipts.md) - - [Refunds](RuntimeSpec/Refunds.md) - - [Runtime Fees](RuntimeSpec/Fees/Fees.md) - - [Scenarios](RuntimeSpec/Scenarios/Scenarios.md) - - [Financial Transaction](RuntimeSpec/Scenarios/FinancialTransaction.md) - - [Cross-Contract Call](RuntimeSpec/Scenarios/CrossContractCall.md) - - [Components](RuntimeSpec/Components/Components.md) - - [Runtime crate](RuntimeSpec/Components/RuntimeCrate.md) - - [Bindings Specification](RuntimeSpec/Components/BindingsSpec/BindingsSpec.md) - - [Registers API](RuntimeSpec/Components/BindingsSpec/RegistersAPI.md) - - [Trie API](RuntimeSpec/Components/BindingsSpec/TrieAPI.md) - - [Promises API](RuntimeSpec/Components/BindingsSpec/PromisesAPI.md) - - [Context API](RuntimeSpec/Components/BindingsSpec/ContextAPI.md) - - [Economics API](RuntimeSpec/Components/BindingsSpec/EconomicsAPI.md) - - [Math API](RuntimeSpec/Components/BindingsSpec/MathAPI.md) - - [Miscellaneous API](RuntimeSpec/Components/BindingsSpec/MiscellaneousAPI.md) -- [GenesisConfig](GenesisConfig/GenesisConfig.md) - - [RuntimeConfig](GenesisConfig/RuntimeConfig.md) - - [RuntimeFeeConfig](GenesisConfig/RuntimeFeeConfig.md) - - [AccessKeyCreationConfig](GenesisConfig/RuntimeFeeConfig/AccessKeyCreationConfig.md) - - [ActionCreationConfig](GenesisConfig/RuntimeFeeConfig/ActionCreationConfig.md) - - [DataReceiptCreationConfig](GenesisConfig/RuntimeFeeConfig/DataReceiptCreationConfig.md) - - [StorageUsageConfig](GenesisConfig/RuntimeFeeConfig/StorageUsageConfig.md) - - [Fee](GenesisConfig/RuntimeFeeConfig/Fee.md) - - [Fraction](GenesisConfig/RuntimeFeeConfig/Fraction.md) - - [VMConfig](GenesisConfig/VMConfig.md) - - [ExtCostsConfig](GenesisConfig/ExtCostsConfig.md) - - [StateRecord](GenesisConfig/StateRecord.md) -- [Economics](Economics/README.md) -- [Standards](Standards/README.md) - - [Fungible Token](Standards/FungibleToken/README.md) - - [Core Standard](Standards/FungibleToken/Core.md) - - [Metadata](Standards/FungibleToken/Metadata.md) - - [Events](Standards/FungibleToken/Event.md) - - [Non-Fungible Token](Standards/NonFungibleToken/README.md) - - [Core Standard](Standards/NonFungibleToken/Core.md) - - [Metadata](Standards/NonFungibleToken/Metadata.md) - - [Approval Management](Standards/NonFungibleToken/ApprovalManagement.md) - - [Enumeration](Standards/NonFungibleToken/Enumeration.md) - - [Royalty Payout](Standards/NonFungibleToken/Payout.md) - - [Events](Standards/NonFungibleToken/Event.md) - - [Storage Management](Standards/StorageManagement.md) - - [Events Format](Standards/EventsFormat.md) -- [Proposals](Proposals/README.md) - - [Access Keys](Proposals/0005-access-keys.md) - - [Wasm bindings](Proposals/0006-bindings.md) - - [Batch transactions](Proposals/0008-transaction-refactoring.md) - - [System Methods](Proposals/0013-system-methods.md) - - [Execution Outcome](Proposals/0017-execution-outcome.md) - - [View/Change Methods](Proposals/0018-view-change-method.md) - - [Economics](Proposals/0033-economics.md) diff --git a/specs/Standards/FungibleToken/README.md b/specs/Standards/FungibleToken/README.md index f1baf04e9..80e26007c 100644 --- a/specs/Standards/FungibleToken/README.md +++ b/specs/Standards/FungibleToken/README.md @@ -1,5 +1,6 @@ -## Fungible Token Standard +import DocCardList from '@theme/DocCardList'; +import {useCurrentSidebarCategory} from '@docusaurus/theme-common'; -- [Fungible Token Core](Core.md) -- [Fungible Token Metadata](Metadata.md) -- [Fungible Token Events](Event.md) +# Fungible Token Standard + + diff --git a/specs/Standards/NonFungibleToken/README.md b/specs/Standards/NonFungibleToken/README.md index 832f26846..cf5931b17 100644 --- a/specs/Standards/NonFungibleToken/README.md +++ b/specs/Standards/NonFungibleToken/README.md @@ -1,8 +1,6 @@ -## Non-Fungible Tokens +import DocCardList from '@theme/DocCardList'; +import {useCurrentSidebarCategory} from '@docusaurus/theme-common'; -- [Non-Fungible Token Core](Core.md) -- [Non-Fungible Token Metadata](Metadata.md) -- [Non-Fungible Token Approval Management](ApprovalManagement.md) -- [Non-Fungible Token Enumeration](Enumeration.md) -- [Non-Fungible Token Royalty Payout](Payout.md) -- [Non-Fungible Token Events](Event.md) +# Non-Fungible Tokens + + diff --git a/specs/Standards/README.md b/specs/Standards/README.md index 5de46442e..cb3083bd2 100644 --- a/specs/Standards/README.md +++ b/specs/Standards/README.md @@ -1,5 +1,12 @@ +import DocCardList from '@theme/DocCardList'; +import {useCurrentSidebarCategory} from '@docusaurus/theme-common'; + # Standards + + +## Table of Contents + - [Fungible Token](FungibleToken/README.md) - [Core Standard](FungibleToken/Core.md) - [Metadata](FungibleToken/Metadata.md) From e23f40f18e17aefa0299238602e97d603cfc2214 Mon Sep 17 00:00:00 2001 From: Jay Logelin Date: Thu, 24 Mar 2022 13:38:03 -0300 Subject: [PATCH 010/150] Update status of NEP1 to Living (#341) * Update status of NEP1 to Living * Updated repo README and nep-0001 editors list --- README.md | 58 ++++++++++++++++++++++++++---------------------- neps/nep-0001.md | 6 ++--- 2 files changed, 35 insertions(+), 29 deletions(-) diff --git a/README.md b/README.md index 752a6bad6..eaeef865c 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,22 @@ This includes the core protocol specification, APIs, contract standards, process Changes to the protocol specification and standards are called NEAR Enhancement Proposals (NEPs). -This repository uses [Docusaurus](https://docusaurus.io/) for the [Nomicon website](https://nomicon.io). +## NEPs + +|NEP # | Title | Author | Status | +|---|---|---|---| +|[0001](https://github.com/near/NEPs/blob/master/neps/nep-0001.md) | NEP Purpose and Guidelines | @jlogelin | Living | +|[0021](https://github.com/near/NEPs/blob/master/neps/nep-0021.md) | Fungible Token Standard (Deprecated) | @evgenykuzyakov | Final | +|[0141](https://github.com/near/NEPs/blob/master/neps/nep-0141.md) | Fungible Token Standard | @evgenykuzyakov @oysterpack | Final | +|[0145](https://github.com/near/NEPs/blob/master/neps/nep-0145.md) | Storage Management | @evgenykuzyakov | Final | +|[0148](https://github.com/near/NEPs/blob/master/neps/nep-0148.md) | Fungible Token Metadata | @robert-zaremba @evgenykuzyakov @oysterpack | Final | +|[0171](https://github.com/near/NEPs/blob/master/neps/nep-0171.md) | Non Fungible Token Standard | @mikedotexe @evgenykuzyakov @oysterpack | Final | +|[0177](https://github.com/near/NEPs/blob/master/neps/nep-0177.md) | Non Fungible Token Metadata | @chadoh @mikedotexe | Final | +|[0178](https://github.com/near/NEPs/blob/master/neps/nep-0178.md) | Non Fungible Token Approval Management | @chadoh @thor314 | Final | +|[0181](https://github.com/near/NEPs/blob/master/neps/nep-0181.md) | Non Fungible Token Enumeration | @chadoh @thor314 | Final | +|[0199](https://github.com/near/NEPs/blob/master/neps/nep-0199.md) | Non Fungible Token Royalties and Payouts | @thor314 @mattlockyer | Final | +|[0297](https://github.com/near/NEPs/blob/master/neps/nep-0297.md) | Contract Events Standard | @telezhnaya | Final | + ## Specification @@ -30,24 +45,32 @@ Ideas presented ultimately as NEPs will need to be driven by the author through #### Process -Spec changes are ultimately done via pull requests to this repository. However, in an effort to keep the pull request clean and readable, please follow these instructions to flesh out an idea. +Spec changes are ultimately done via pull requests to this repository (formalized process [here](neps/nep-0001.md)). In an effort to keep the pull request clean and readable, please follow these instructions to flesh out an idea. 1. Sign up for the [governance site](https://gov.near.org/) and make a post to the appropriate section. For instance, during the ideation phase of a standard, one might start a new conversation in the [Development » Standards section](https://gov.near.org/c/dev/standards/29). The other suggested category in the governance forum is the [Development » Proposals section](https://gov.near.org/c/dev/proposals/68). 2. The forum has comment threading which allows the community and NEAR Collective to ideate, ask questions, wrestle with approaches, etc. If more immediate responses are desired, consider bringing the conversation [to Discord](https://near.chat). 3. When the governance conversations have reached a point where a clear plan is evident, create a pull request, using the instructions below. -Pull request (only when governance discussion has concluded) - -* Clone this repository and create a branch with "my-feature". -* Update relevant content in the current specification that are affected by the proposal. -* Create PR, where information of the PR follows [0000-template.md](0000-template.md) to describe motivation and details of the change to the protocol. The file will be added to `specs/Proposals`, using the pull request number padded with zeroes. For instance, the pull request `19` might be created as `specs/Proposals/0019-short-slug-description.md`. -* Post pre-approval of the spec change, present a PR for NEAR Protocol client(s) that implements this specification change. -* Receive final approval and merge change into the `master` to be included in the next release. + * Clone this repository and create a branch with "my-feature". + * Update relevant content in the current specification that are affected by the proposal. + * Create a Pull request, using [nep-0000-template.md](nep-0000-template.md) to describe motivation and details of the new Contract or Protocol specification. In the document header, ensure the `Status` is marked as `Draft`, and any relevant discussion links are added to the `DiscussionsTo` section. + Use the pull request number padded with zeroes. For instance, the pull request `219` should be created as `neps/nep-0219.md`. + * Add your Draft standard to the `NEPs` section of this README.md. This helps advertise your standard via github. + * Update Docusaurus documentation under the `specs/Standards` to describe the contract standard at a high level, how to integrate it into a Dapp, and a link to the standard document (ie. `neps/nep-0123.md`). This helps advertise your standard via [nomicon](https://nomicon.io/). + * Once complete, submit the pull request for editor review. + + * The formalization dance begins: + * NEP Editors, who are unopinionated shepherds of the process, check document formatting, completeness and adherence to [NEP-0001](neps/nep-0001.md) and approve the pull request. + * Once ready, the author updates the NEP status to `Review` allowing further community participation, to address any gaps or clarifications, normally part of the Review PR. + * NEP Editors mark the NEP as `Last Call`, allowing a 14 day grace period for any final community feedback. Any unresolved show stoppers roll the state back to `Review`. + * NEP Editors mark the NEP as `Final`, marking the standard as complete. The standard should only be updated to correct errata and add non-normative clarifications. Tip: build consensus and integrate feedback. NEPs that have broad support are much more likely to make progress than those that don't receive any comments. Feel free to reach out to the NEP assignee in particular to get help identify stakeholders and obstacles. ### Running Docusaurus +This repository uses [Docusaurus](https://docusaurus.io/) for the [Nomicon website](https://nomicon.io). + 1. Move into the `/website` folder where you will run the following commands: - Make sure all the dependencies for the website are installed: @@ -78,20 +101,3 @@ Tip: build consensus and integrate feedback. NEPs that have broad support are mu 3. Observe those changes reflected in the local docs 4. Submit a pull request with your changes - - -## NEPs - -|NEP # | Title | Author | Status | -|---|---|---|---| -|[0001](https://github.com/near/NEPs/blob/master/neps/nep-0001.md) | NEP Purpose and Guidelines | @jlogelin | Active | -|[0021](https://github.com/near/NEPs/blob/master/neps/nep-0021.md) | Fungible Token Standard (Deprecated) | @aevgenykuzyakov | Final | -|[0141](https://github.com/near/NEPs/blob/master/neps/nep-0141.md) | Fungible Token Standard | @aevgenykuzyakov @oysterpack | Final | -|[0145](https://github.com/near/NEPs/blob/master/neps/nep-0145.md) | Storage Management | @aevgenykuzyakov | Final | -|[0148](https://github.com/near/NEPs/blob/master/neps/nep-0148.md) | Fungible Token Metadata | @robert-zaremba @aevgenykuzyakov @oysterpack | Final | -|[0171](https://github.com/near/NEPs/blob/master/neps/nep-0171.md) | Non Fungible Token Standard | @mikedotexe @aevgenykuzyakov @oysterpack | Final | -|[0177](https://github.com/near/NEPs/blob/master/neps/nep-0177.md) | Non Fungible Token Metadata | @chadoh @mikedotexe | Final | -|[0178](https://github.com/near/NEPs/blob/master/neps/nep-0178.md) | Non Fungible Token Approval Management | @chadoh @thor314 | Final | -|[0181](https://github.com/near/NEPs/blob/master/neps/nep-0181.md) | Non Fungible Token Enumeration | @chadoh @thor314 | Final | -|[0199](https://github.com/near/NEPs/blob/master/neps/nep-0199.md) | Non Fungible Token Royalties and Payouts | @thor314 @mattlockyer | Final | -|[0297](https://github.com/near/NEPs/blob/master/neps/nep-0297.md) | Contract Events Standard | @telezhnaya | Final | diff --git a/neps/nep-0001.md b/neps/nep-0001.md index 7a9ad1f44..c5efb1756 100644 --- a/neps/nep-0001.md +++ b/neps/nep-0001.md @@ -3,7 +3,7 @@ NEP: 1 Title: NEP Purpose and Guidelines Author: Jay Logelin DiscussionsTo: https://github.com/near/NEPs/pull/333 -Status: Active +Status: Living Type: Process Created: 03-Mar-2022 --- @@ -342,12 +342,12 @@ submit a competing NEP. If you are interested in assuming ownership of an NEP, you can also do this via pull request. Fork the `NEP repository`, make your ownership modification, and submit a pull request. You should mention both the original author and -``@Near/NEP-editors`` in a comment on the pull request. +``@near/nep-editors`` in a comment on the pull request. ## NEP Editors The current NEP Editors are: - * TBD + * Jay Logelin - @jlogelin ## NEP Editor Responsibilities & Workflow From 4c5f2b3513747cfc9fb8bb506ebf1344375a91e3 Mon Sep 17 00:00:00 2001 From: Benjamin Kurrek <57506486+BenKurrek@users.noreply.github.com> Date: Tue, 29 Mar 2022 14:55:48 -0400 Subject: [PATCH 011/150] feat: Add Contract Metadata Standard (#330) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Initial implementation of contract metadata standard * bumped NEP version and fixed minor typo * removed setter function * Apply suggestions from code review Co-authored-by: Damián Parrino * Updated to new templates and standard formatting * Added example implementation for contract metadata view function * Added more fleshed out implementation Co-authored-by: Damián Parrino --- neps/nep-0330.md | 103 ++++++++++++++++++++++++++++ specs/Standards/ContractMetadata.md | 93 +++++++++++++++++++++++++ 2 files changed, 196 insertions(+) create mode 100644 neps/nep-0330.md create mode 100644 specs/Standards/ContractMetadata.md diff --git a/neps/nep-0330.md b/neps/nep-0330.md new file mode 100644 index 000000000..4b544c6d6 --- /dev/null +++ b/neps/nep-0330.md @@ -0,0 +1,103 @@ +--- +NEP: 330 +Title: Contract Metadata +Author: Ben Kurrek +DiscussionsTo: https://github.com/near/NEPs/discussions/329 +Status: Draft +Type: Standards Track +Category: Contract +Created: 27-Feb-2022 +--- + +## Summary + +The contract metadata is a standard interface that allows auditing and viewing source code for a deployed smart contract. Implementation of this standard is purely optional but is recommended for developers whose contracts are open source. + +## Motivation + +There is no trivial way of finding the source code or author of a deployed smart contract. Having a standard that outlines how to view the source code of an arbitrary smart contract creates an environment of openness and collaboration. + +The initial discussion can be found [here](https://github.com/near/NEPs/discussions/329). + +## Rationale and alternatives + +There is a lot of information that can be held about a contract. Ultimately, we wanted to limit it to the least amount fields while still maintaining our goal. This decision was made to not bloat the contracts with unnecessary storage and also to keep the standard simple and understandable. + +## Specification + +Successful implementations of this standard will introduce a new (`ContractMetadata`) struct that will hold all the necessary information to be queried for. This struct will be kept on the contract level. + +The metadata will include two optional fields: +- `version`: a string that references the specific commit hash or version of the code that is currently deployed on-chain. This can be included regardless of whether or not the contract is open-sourced and can also be used for organizational purposes. +- `link`: a string that references the link to the open-source code. This can be anything such as Github or a CID to somewhere on IPFS. + +```ts +type ContractMetadata = { + version: string|null, // optional, commit hash being used for the currently deployed wasm. If the contract is not open-sourced, this could also be a numbering system for internal organization / tracking such as "1.0.0" and "2.1.0". + link: string|null, //optional, link to open source code such as a Github repository or a CID to somewhere on IPFS. +} +``` + +In order to view this information, contracts must include a getter which will return the struct. + +```ts +function contract_metadata(): ContractMetadata {} +``` + +## Reference Implementation + +As an example, say there was an NFT contract deployed on-chain which was currently using the commit hash `39f2d2646f2f60e18ab53337501370dc02a5661c` and had its open source code located at `https://github.com/near-examples/nft-tutorial`. This contract would then include a struct which has the following fields: + +```ts +type ContractMetadata = { + version: "39f2d2646f2f60e18ab53337501370dc02a5661c" + link: "https://github.com/near-examples/nft-tutorial" +} +``` + +If someone were to call the view function `contract_metadata`, the contract would return: + +```bash +{ + version: "39f2d2646f2f60e18ab53337501370dc02a5661c" + link: "https://github.com/near-examples/nft-tutorial" +} +``` + +An example implementation can be seen below. + +```rust +/// Simple Implementation +#[near_bindgen] +pub struct Contract { + pub contract_metadata: ContractMetadata +} + +/// Contract metadata structure +pub struct ContractMetadata { + pub version: String, + pub link: String, +} + +/// Minimum Viable Interface +pub trait ContractMetadataTrait { + fn contract_metadata(&self) -> ContractMetadata; +} + +/// Implementation of the view function +#[near_bindgen] +impl ContractMetadataTrait for Contract { + fn contract_metadata(&self) -> ContractMetadata { + self.contract_metadata.get().unwrap() + } +} +``` + +## Future possibilities + +- By having a standard outlining metadata for an arbitrary contract, any information that pertains on a contract level can be added based on the requests of the developer community. + +## Copyright +[copyright]: #copyright + +Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). \ No newline at end of file diff --git a/specs/Standards/ContractMetadata.md b/specs/Standards/ContractMetadata.md new file mode 100644 index 000000000..94465128d --- /dev/null +++ b/specs/Standards/ContractMetadata.md @@ -0,0 +1,93 @@ +# Contract Metadata + +## [NEP-330](https://github.com/near/NEPs/discussions/329) + +Version `1.0.0` + +## Summary + +The contract metadata is a standard interface that allows auditing and viewing source code for a deployed smart contract. Implementation of this standard is purely optional but is recommended for developers whose contracts are open source. + +## Motivation + +There is no trivial way of finding the source code or author of a deployed smart contract. Having a standard that outlines how to view the source code of an arbitrary smart contract creates an environment of openness and collaboration. + +The initial discussion can be found [here](https://github.com/near/NEPs/discussions/329). + +## Rationale and alternatives + +There is a lot of information that can be held about a contract. Ultimately, we wanted to limit it to the least amount fields while still maintaining our goal. This decision was made to not bloat the contracts with unnecessary storage and also to keep the standard simple and understandable. + +## Specification + +Successful implementations of this standard will introduce a new (`ContractMetadata`) struct that will hold all the necessary information to be queried for. This struct will be kept on the contract level. + +The metadata will include two optional fields: +- `version`: a string that references the specific commit hash or version of the code that is currently deployed on-chain. This can be included regardless of whether or not the contract is open-sourced and can also be used for organizational purposes. +- `link`: a string that references the link to the open-source code. This can be anything such as Github or a CID to somewhere on IPFS. + +```ts +type ContractMetadata = { + version: string|null, // optional, commit hash being used for the currently deployed wasm. If the contract is not open-sourced, this could also be a numbering system for internal organization / tracking such as "1.0.0" and "2.1.0". + link: string|null, //optional, link to open source code such as a Github repository or a CID to somewhere on IPFS. +} +``` + +In order to view this information, contracts must include a getter which will return the struct. + +```ts +function contract_metadata(): ContractMetadata {} +``` + +## Reference Implementation + +As an example, say there was an NFT contract deployed on-chain which was currently using the commit hash `39f2d2646f2f60e18ab53337501370dc02a5661c` and had its open source code located at `https://github.com/near-examples/nft-tutorial`. This contract would then include a struct which has the following fields: + +```ts +type ContractMetadata = { + version: "39f2d2646f2f60e18ab53337501370dc02a5661c" + link: "https://github.com/near-examples/nft-tutorial" +} +``` + +If someone were to call the view function `contract_metadata`, the contract would return: + +```bash +{ + version: "39f2d2646f2f60e18ab53337501370dc02a5661c" + link: "https://github.com/near-examples/nft-tutorial" +} +``` + +An example implementation can be seen below. + +```rust +/// Simple Implementation +#[near_bindgen] +pub struct Contract { + pub contract_metadata: ContractMetadata +} + +/// Contract metadata structure +pub struct ContractMetadata { + pub version: String, + pub link: String, +} + +/// Minimum Viable Interface +pub trait ContractMetadataTrait { + fn contract_metadata(&self) -> ContractMetadata; +} + +/// Implementation of the view function +#[near_bindgen] +impl ContractMetadataTrait for Contract { + fn contract_metadata(&self) -> ContractMetadata { + self.contract_metadata.get().unwrap() + } +} +``` + +## Future possibilities + +- By having a standard outlining metadata for an arbitrary contract, any information that pertains on a contract level can be added based on the requests of the developer community. \ No newline at end of file From c7d72138117ed0ab86629a27d1f84e9cce80848f Mon Sep 17 00:00:00 2001 From: Blas Rodriguez Irizar Date: Thu, 31 Mar 2022 03:05:18 +0200 Subject: [PATCH 012/150] doc: update light client spec (#343) broken link on rpc-endpoint --- specs/ChainSpec/LightClient.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/specs/ChainSpec/LightClient.md b/specs/ChainSpec/LightClient.md index 978199b29..59eda69c6 100644 --- a/specs/ChainSpec/LightClient.md +++ b/specs/ChainSpec/LightClient.md @@ -7,7 +7,7 @@ The state of the light client is defined by: The `epoch_id` refers to the epoch to which the block that is the current known head belongs, and `next_epoch_id` is the epoch that will follow. -Light clients operate by periodically fetching instances of `LightClientBlockView` via particular RPC end-point described [below](#rpc-end-point). +Light clients operate by periodically fetching instances of `LightClientBlockView` via particular RPC end-point described [below](#rpc-end-points). Light client doesn't need to receive `LightClientBlockView` for all the blocks. Having the `LightClientBlockView` for block `B` is sufficient to be able to verify any statement about state or outcomes in any block in the ancestry of `B` (including `B` itself). In particular, having the `LightClientBlockView` for the head is sufficient to locally verify any statement about state or outcomes in any block on the canonical chain. From 3d566ab95a327f79178750010d02c157d19f5313 Mon Sep 17 00:00:00 2001 From: Yassine Date: Thu, 31 Mar 2022 17:37:34 +0200 Subject: [PATCH 013/150] Typos in FungibleToken Core (#247) --- specs/Standards/FungibleToken/Core.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/specs/Standards/FungibleToken/Core.md b/specs/Standards/FungibleToken/Core.md index 9aad27a68..eecbcaacd 100644 --- a/specs/Standards/FungibleToken/Core.md +++ b/specs/Standards/FungibleToken/Core.md @@ -155,7 +155,7 @@ Altogether then, Alice may take two steps, though the first may be a background Then Alice (or the app she uses) will hold onto the result and use it in the next step. Let's say this result is `"swap:bnna,2"`. -2. Call `wnear::ft_on_transfer`. Using NEAR CLI: +2. Call `wnear::ft_transfer_call`. Using NEAR CLI: near call wnear ft_transfer_call '{ "receiver_id": "amm", "amount": "5000000000000000000000000", @@ -166,7 +166,7 @@ Altogether then, Alice may take two steps, though the first may be a background 1. Decrease the balance of `alice` and increase the balance of `amm` by 5000000000000000000000000. 2. Makes async call `amm::ft_on_transfer({"sender_id": "alice", "amount": "5000000000000000000000000", "msg": "swap:bnna,2"})`. - 3. Attaches a callback `wnear::ft_resolve_transfer({"sender_id": "alice", "receiver_id": "compound", "amount": "5000000000000000000000000"})`. + 3. Attaches a callback `wnear::ft_resolve_transfer({"sender_id": "alice", "receiver_id": "amm", "amount": "5000000000000000000000000"})`. 4. `amm` finishes the swap, either successfully swapping all 5 wNEAR within the desired slippage, or failing. 5. The `wnear::ft_resolve_transfer` function receives success/failure of the promise. Assuming `amm` implements all-or-nothing transfers (as in, it will not transfer less-than-the-specified amount in order to fulfill the slippage requirements), `wnear` will do nothing at this point if the swap succeeded, or it will decrease the balance of `amm` and increase the balance of `alice` by 5000000000000000000000000. From fc500e0ab6e692787b6d2cbc8233bce0f55a5a1d Mon Sep 17 00:00:00 2001 From: Mykle Date: Thu, 31 Mar 2022 08:40:51 -0700 Subject: [PATCH 014/150] Update Metadata.md (#320) Clarifying the correct value & meaning of the 'spec' field in version 2.0.0 of NEP-177. --- specs/Standards/NonFungibleToken/Metadata.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/specs/Standards/NonFungibleToken/Metadata.md b/specs/Standards/NonFungibleToken/Metadata.md index 10e0046fc..03d98abb1 100644 --- a/specs/Standards/NonFungibleToken/Metadata.md +++ b/specs/Standards/NonFungibleToken/Metadata.md @@ -27,7 +27,7 @@ Metadata applies at both the contract level (`NFTContractMetadata`) and the toke ```ts type NFTContractMetadata = { - spec: string, // required, essentially a version like "nft-1.0.0" + spec: string, // required, essentially a version like "nft-2.0.0", replacing "2.0.0" with the implemented version of NEP-177 name: string, // required, ex. "Mochi Rising — Digital Edition" or "Metaverse 3" symbol: string, // required, ex. "MOCHI" icon: string|null, // Data URL @@ -70,7 +70,7 @@ A new attribute MUST be added to each `Token` struct: ### An implementing contract MUST include the following fields on-chain -- `spec`: a string that MUST be formatted `nft-1.0.0` to indicate that a Non-Fungible Token contract adheres to the current versions of this Metadata spec. This will allow consumers of the Non-Fungible Token to know if they support the features of a given contract. +- `spec`: a string that MUST be formatted `nft-n.n.n` where "n.n.n" is replaced with the implemented version of this Metadata spec: for instance, "nft-2.0.0" to indicate NEP-177 version 2.0.0. This will allow consumers of the Non-Fungible Token to know which set of metadata features the contract supports. - `name`: the human-readable name of the contract. - `symbol`: the abbreviated symbol of the contract, like MOCHI or MV3 - `base_uri`: Centralized gateway known to have reliable access to decentralized storage assets referenced by `reference` or `media` URLs. Can be used by other frontends for initial retrieval of assets, even if these frontends then replicate the data to their own decentralized nodes, which they are encouraged to do. @@ -123,4 +123,4 @@ The first version (`1.0.0`) had confusing language regarding the fields: - `starts_at` - `updated_at` -It gave those fields the type `string|null` but it was unclear whether it should be a Unix epoch in milliseconds or [ISO 8601](https://www.iso.org/iso-8601-date-and-time-format.html). Upon having to revisit this, it was determined to be the most efficient to use epoch milliseconds as it would reduce the computation on the smart contract and can be derived trivially from the block timestamp. \ No newline at end of file +It gave those fields the type `string|null` but it was unclear whether it should be a Unix epoch in milliseconds or [ISO 8601](https://www.iso.org/iso-8601-date-and-time-format.html). Upon having to revisit this, it was determined to be the most efficient to use epoch milliseconds as it would reduce the computation on the smart contract and can be derived trivially from the block timestamp. From 9ed3ff916fedd54b50bd20e9eca91e2b021e61e7 Mon Sep 17 00:00:00 2001 From: Jay Logelin Date: Thu, 31 Mar 2022 15:31:49 -0300 Subject: [PATCH 015/150] Editor review nep-0330 (#345) * Update README with nep-0330 ref * Updated Status to Review * Update README.md --- README.md | 2 ++ neps/nep-0330.md | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index eaeef865c..9ca5a1f6f 100644 --- a/README.md +++ b/README.md @@ -23,6 +23,8 @@ Changes to the protocol specification and standards are called NEAR Enhancement |[0181](https://github.com/near/NEPs/blob/master/neps/nep-0181.md) | Non Fungible Token Enumeration | @chadoh @thor314 | Final | |[0199](https://github.com/near/NEPs/blob/master/neps/nep-0199.md) | Non Fungible Token Royalties and Payouts | @thor314 @mattlockyer | Final | |[0297](https://github.com/near/NEPs/blob/master/neps/nep-0297.md) | Contract Events Standard | @telezhnaya | Final | +|[0330](https://github.com/near/NEPs/blob/master/neps/nep-0330.md) | Contract Metadata | @BenKurrek | Review | + ## Specification diff --git a/neps/nep-0330.md b/neps/nep-0330.md index 4b544c6d6..34c305e15 100644 --- a/neps/nep-0330.md +++ b/neps/nep-0330.md @@ -3,7 +3,7 @@ NEP: 330 Title: Contract Metadata Author: Ben Kurrek DiscussionsTo: https://github.com/near/NEPs/discussions/329 -Status: Draft +Status: Review Type: Standards Track Category: Contract Created: 27-Feb-2022 @@ -100,4 +100,4 @@ impl ContractMetadataTrait for Contract { ## Copyright [copyright]: #copyright -Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). \ No newline at end of file +Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). From 1a56a25e3e771dde8b72e5edbd40b0eff922ae91 Mon Sep 17 00:00:00 2001 From: Jay Logelin Date: Thu, 31 Mar 2022 16:05:59 -0300 Subject: [PATCH 016/150] Create CODEOWNERS file (#347) --- CODEOWNERS | 1 + 1 file changed, 1 insertion(+) create mode 100644 CODEOWNERS diff --git a/CODEOWNERS b/CODEOWNERS new file mode 100644 index 000000000..9e37ed73a --- /dev/null +++ b/CODEOWNERS @@ -0,0 +1 @@ +@near/nep-editors From fe79f11c9d591bc28815fe209a9d3de54ab6da1a Mon Sep 17 00:00:00 2001 From: Jay Logelin Date: Thu, 31 Mar 2022 16:13:15 -0300 Subject: [PATCH 017/150] Update CODEOWNERS (#348) --- CODEOWNERS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CODEOWNERS b/CODEOWNERS index 9e37ed73a..3e9bdbbaf 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -1 +1 @@ -@near/nep-editors +* @near/nep-editors From 9a766647ffd1a9c708f269944e4ea6443a55f9ab Mon Sep 17 00:00:00 2001 From: Jay Logelin Date: Thu, 31 Mar 2022 16:30:05 -0300 Subject: [PATCH 018/150] Update CODEOWNERS --- CODEOWNERS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CODEOWNERS b/CODEOWNERS index 3e9bdbbaf..26b913c38 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -1 +1 @@ -* @near/nep-editors +* @nep-editors From 37afda9bc1cc699a52c6647ae5a1de5e828556b0 Mon Sep 17 00:00:00 2001 From: Jay Logelin Date: Thu, 31 Mar 2022 16:30:47 -0300 Subject: [PATCH 019/150] Update CODEOWNERS --- CODEOWNERS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CODEOWNERS b/CODEOWNERS index 26b913c38..3e9bdbbaf 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -1 +1 @@ -* @nep-editors +* @near/nep-editors From bc0c572b26cfeaf2117f4a1c0af7f09c186d434c Mon Sep 17 00:00:00 2001 From: Jay Logelin Date: Thu, 31 Mar 2022 23:27:29 -0300 Subject: [PATCH 020/150] Added Runtime Category type Also updated reference implementation to be an optional section for non-Contract categories --- neps/nep-0001.md | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/neps/nep-0001.md b/neps/nep-0001.md index c5efb1756..e966d17e2 100644 --- a/neps/nep-0001.md +++ b/neps/nep-0001.md @@ -210,9 +210,11 @@ Each NEP should have the following parts/sections: version. 6. Reference Implementation - The reference implementation must be - completed before any Standards Track NEP is given status "Final", - but it need not be completed before the NEP is accepted. While - there is merit to the approach of reaching consensus on the + completed before any `Standards Track` in the `Contract` category NEP + is given status "Final", but it need not be completed before the NEP + is accepted. For other Categories, this section is optional. + + While there is merit to the approach of reaching consensus on the specification and rationale before writing code, the principle of "rough consensus and running code" is still useful when it comes to resolving many discussions of API details. @@ -276,7 +278,7 @@ header preamble. The headers must appear in the following order. DiscussionsTo: Status: Type: - Category: if Type is "Standards Track" one of + Category: if Type is "Standards Track" one of Requires (Optional): Replaces (Optional): SupersededBy (Optional): @@ -305,7 +307,7 @@ canonical discussion thread for the NEP. Informational, or Process. `Category`: The Category header only exists iff the Type header is `Standards Track`, -one of Protocol or Contract. +one of Protocol, Contract or Runtime. `Created`: The Created header records the date that the NEP was assigned a number, should be in dd-mmm-yyyy format, e.g. 03-Mar-2022. From 20339388e957c0899f8b76cec06b3f1597cd81a9 Mon Sep 17 00:00:00 2001 From: Jay Logelin Date: Thu, 31 Mar 2022 23:28:46 -0300 Subject: [PATCH 021/150] Update nep-0000-template.md --- nep-0000-template.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/nep-0000-template.md b/nep-0000-template.md index 2d8c051a1..6a7123d4c 100644 --- a/nep-0000-template.md +++ b/nep-0000-template.md @@ -34,7 +34,7 @@ Explain the proposal as if it was already implemented and you were teaching it t For user-facing NEPs this section should focus on user stories. -## Reference Implementation +## Reference Implementation (Required for Contract category, optional for other categories) This is the technical portion of the NEP. Explain the design in sufficient detail that: @@ -82,4 +82,4 @@ The section merely provides additional information. ## Copyright [copyright]: #copyright -Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). \ No newline at end of file +Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). From fb2dd6973d571ad19839328dc16e5db2ef20a2e3 Mon Sep 17 00:00:00 2001 From: Jay Logelin Date: Fri, 1 Apr 2022 11:33:16 -0300 Subject: [PATCH 022/150] Added proposal prefix header to ContractMetadata.md --- README.md | 7 +++++-- specs/Standards/ContractMetadata.md | 2 +- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 9ca5a1f6f..cfe100fc3 100644 --- a/README.md +++ b/README.md @@ -58,8 +58,11 @@ Spec changes are ultimately done via pull requests to this repository (formalize * Create a Pull request, using [nep-0000-template.md](nep-0000-template.md) to describe motivation and details of the new Contract or Protocol specification. In the document header, ensure the `Status` is marked as `Draft`, and any relevant discussion links are added to the `DiscussionsTo` section. Use the pull request number padded with zeroes. For instance, the pull request `219` should be created as `neps/nep-0219.md`. * Add your Draft standard to the `NEPs` section of this README.md. This helps advertise your standard via github. - * Update Docusaurus documentation under the `specs/Standards` to describe the contract standard at a high level, how to integrate it into a Dapp, and a link to the standard document (ie. `neps/nep-0123.md`). This helps advertise your standard via [nomicon](https://nomicon.io/). - * Once complete, submit the pull request for editor review. + * Update Docusaurus documentation under the `specs/Standards` to describe the contract standard at a high level, how to integrate it into a Dapp, and a link to the standard document (ie. `neps/nep-0123.md`). This helps advertise your standard via [nomicon](https://nomicon.io/). Any nomicon sections should be prefixed with the following note following the header: + + Note: this is part of proposed spec [NEP-123](https://github.com/near/NEPs/blob/master/neps/nep-0123.md) and subject to change. + + * Once complete, submit the pull request for editor review. * The formalization dance begins: * NEP Editors, who are unopinionated shepherds of the process, check document formatting, completeness and adherence to [NEP-0001](neps/nep-0001.md) and approve the pull request. diff --git a/specs/Standards/ContractMetadata.md b/specs/Standards/ContractMetadata.md index 94465128d..da4f89dd4 100644 --- a/specs/Standards/ContractMetadata.md +++ b/specs/Standards/ContractMetadata.md @@ -1,6 +1,6 @@ # Contract Metadata -## [NEP-330](https://github.com/near/NEPs/discussions/329) +Note: this is part of proposed spec [NEP-330](https://github.com/near/NEPs/blob/master/neps/nep-0330.md) and subject to change. Version `1.0.0` From 26f57ead0ee7f3e4b1a4e42a2b018651658fd58c Mon Sep 17 00:00:00 2001 From: Jay Logelin Date: Fri, 1 Apr 2022 11:53:58 -0300 Subject: [PATCH 023/150] Added new NEP zulip stream link --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index cfe100fc3..7101ad0a3 100644 --- a/README.md +++ b/README.md @@ -50,7 +50,7 @@ Ideas presented ultimately as NEPs will need to be driven by the author through Spec changes are ultimately done via pull requests to this repository (formalized process [here](neps/nep-0001.md)). In an effort to keep the pull request clean and readable, please follow these instructions to flesh out an idea. 1. Sign up for the [governance site](https://gov.near.org/) and make a post to the appropriate section. For instance, during the ideation phase of a standard, one might start a new conversation in the [Development » Standards section](https://gov.near.org/c/dev/standards/29). The other suggested category in the governance forum is the [Development » Proposals section](https://gov.near.org/c/dev/proposals/68). -2. The forum has comment threading which allows the community and NEAR Collective to ideate, ask questions, wrestle with approaches, etc. If more immediate responses are desired, consider bringing the conversation [to Discord](https://near.chat). +2. The forum has comment threading which allows the community and NEAR Collective to ideate, ask questions, wrestle with approaches, etc. If more immediate responses are desired, consider bringing the conversation [Zulip](https://near.zulipchat.com/#narrow/stream/320497-nep-standards) or [to Discord](https://near.chat). 3. When the governance conversations have reached a point where a clear plan is evident, create a pull request, using the instructions below. * Clone this repository and create a branch with "my-feature". From ef51fa4e7cb98c29459f10a88f50b0f82c32e90a Mon Sep 17 00:00:00 2001 From: Jay Logelin Date: Fri, 1 Apr 2022 14:00:05 -0300 Subject: [PATCH 024/150] Added warning prefix to nep-330 documentation --- README.md | 8 ++++++-- specs/Standards/ContractMetadata.md | 4 +++- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index cfe100fc3..9c8b81381 100644 --- a/README.md +++ b/README.md @@ -58,9 +58,13 @@ Spec changes are ultimately done via pull requests to this repository (formalize * Create a Pull request, using [nep-0000-template.md](nep-0000-template.md) to describe motivation and details of the new Contract or Protocol specification. In the document header, ensure the `Status` is marked as `Draft`, and any relevant discussion links are added to the `DiscussionsTo` section. Use the pull request number padded with zeroes. For instance, the pull request `219` should be created as `neps/nep-0219.md`. * Add your Draft standard to the `NEPs` section of this README.md. This helps advertise your standard via github. - * Update Docusaurus documentation under the `specs/Standards` to describe the contract standard at a high level, how to integrate it into a Dapp, and a link to the standard document (ie. `neps/nep-0123.md`). This helps advertise your standard via [nomicon](https://nomicon.io/). Any nomicon sections should be prefixed with the following note following the header: + * Update Docusaurus documentation under the `specs/Standards` to describe the contract standard at a high level, how to integrate it into a Dapp, and a link to the standard document (ie. `neps/nep-0123.md`). This helps advertise your standard via [nomicon](https://nomicon.io/). Any related nomicon sections should be prefixed and styled using the following snippet: - Note: this is part of proposed spec [NEP-123](https://github.com/near/NEPs/blob/master/neps/nep-0123.md) and subject to change. + ``` + :::caution + This is part of proposed spec [NEP-123](https://github.com/near/NEPs/blob/master/neps/nep-0123.md) and subject to change. + ::: + ``` * Once complete, submit the pull request for editor review. diff --git a/specs/Standards/ContractMetadata.md b/specs/Standards/ContractMetadata.md index da4f89dd4..63682b60b 100644 --- a/specs/Standards/ContractMetadata.md +++ b/specs/Standards/ContractMetadata.md @@ -1,6 +1,8 @@ # Contract Metadata -Note: this is part of proposed spec [NEP-330](https://github.com/near/NEPs/blob/master/neps/nep-0330.md) and subject to change. +:::caution +This is part of proposed spec [NEP-330](https://github.com/near/NEPs/blob/master/neps/nep-0330.md) and subject to change. +::: Version `1.0.0` From 8e0cf307bbb91d26722d06e6a7df469e9f2eaa07 Mon Sep 17 00:00:00 2001 From: Jay Logelin Date: Fri, 1 Apr 2022 14:47:49 -0300 Subject: [PATCH 025/150] Updated standards links (#349) --- specs/Standards/ContractMetadata.md | 2 ++ specs/Standards/EventsFormat.md | 2 +- specs/Standards/FungibleToken/Core.md | 2 +- specs/Standards/FungibleToken/Metadata.md | 2 +- specs/Standards/NonFungibleToken/ApprovalManagement.md | 2 +- specs/Standards/NonFungibleToken/Core.md | 2 +- specs/Standards/NonFungibleToken/Enumeration.md | 2 +- specs/Standards/NonFungibleToken/Metadata.md | 2 +- specs/Standards/NonFungibleToken/Payout.md | 2 +- specs/Standards/StorageManagement.md | 2 +- 10 files changed, 11 insertions(+), 9 deletions(-) diff --git a/specs/Standards/ContractMetadata.md b/specs/Standards/ContractMetadata.md index 63682b60b..6411b30b6 100644 --- a/specs/Standards/ContractMetadata.md +++ b/specs/Standards/ContractMetadata.md @@ -1,5 +1,7 @@ # Contract Metadata +## [NEP-330](https://github.com/near/NEPs/blob/master/neps/nep-0330.md) + :::caution This is part of proposed spec [NEP-330](https://github.com/near/NEPs/blob/master/neps/nep-0330.md) and subject to change. ::: diff --git a/specs/Standards/EventsFormat.md b/specs/Standards/EventsFormat.md index e69aa2583..ca12754ac 100644 --- a/specs/Standards/EventsFormat.md +++ b/specs/Standards/EventsFormat.md @@ -1,6 +1,6 @@ # Events Format -## [NEP-297](https://github.com/near/NEPs/issues/297) +## [NEP-297](https://github.com/near/NEPs/blob/master/neps/nep-0297.md) Version `1.0.0` diff --git a/specs/Standards/FungibleToken/Core.md b/specs/Standards/FungibleToken/Core.md index eecbcaacd..ccfcf08c8 100644 --- a/specs/Standards/FungibleToken/Core.md +++ b/specs/Standards/FungibleToken/Core.md @@ -1,6 +1,6 @@ # Fungible Token -## [NEP-141](https://github.com/near/NEPs/issues/141) +## [NEP-141](https://github.com/near/NEPs/blob/master/neps/nep-0141.md) Version `1.0.0` diff --git a/specs/Standards/FungibleToken/Metadata.md b/specs/Standards/FungibleToken/Metadata.md index 4dba6d3be..8ba698980 100644 --- a/specs/Standards/FungibleToken/Metadata.md +++ b/specs/Standards/FungibleToken/Metadata.md @@ -1,6 +1,6 @@ # Fungible Token Metadata -## [NEP-148](https://github.com/near/NEPs/discussions/148) +## [NEP-148](https://github.com/near/NEPs/blob/master/neps/nep-0148.md) Version `1.0.0` diff --git a/specs/Standards/NonFungibleToken/ApprovalManagement.md b/specs/Standards/NonFungibleToken/ApprovalManagement.md index 7cf4b5d42..bdd2cecb6 100644 --- a/specs/Standards/NonFungibleToken/ApprovalManagement.md +++ b/specs/Standards/NonFungibleToken/ApprovalManagement.md @@ -1,6 +1,6 @@ # Approval Management -## [NEP-178](https://github.com/near/NEPs/discussions/178) +## [NEP-178](https://github.com/near/NEPs/blob/master/neps/nep-0178.md) Version `1.1.0` diff --git a/specs/Standards/NonFungibleToken/Core.md b/specs/Standards/NonFungibleToken/Core.md index 36aafcbac..605345d34 100644 --- a/specs/Standards/NonFungibleToken/Core.md +++ b/specs/Standards/NonFungibleToken/Core.md @@ -1,6 +1,6 @@ # Core Functionality -## [NEP-171](https://github.com/near/NEPs/discussions/171) +## [NEP-171](https://github.com/near/NEPs/blob/master/neps/nep-0171.md) Version `1.0.2` diff --git a/specs/Standards/NonFungibleToken/Enumeration.md b/specs/Standards/NonFungibleToken/Enumeration.md index 38093c825..43910a5db 100644 --- a/specs/Standards/NonFungibleToken/Enumeration.md +++ b/specs/Standards/NonFungibleToken/Enumeration.md @@ -1,6 +1,6 @@ # Enumeration -## [NEP-181](https://github.com/near/NEPs/discussions/181) +## [NEP-181](https://github.com/near/NEPs/blob/master/neps/nep-0181.md) Version `1.0.0` diff --git a/specs/Standards/NonFungibleToken/Metadata.md b/specs/Standards/NonFungibleToken/Metadata.md index 03d98abb1..38daa9b52 100644 --- a/specs/Standards/NonFungibleToken/Metadata.md +++ b/specs/Standards/NonFungibleToken/Metadata.md @@ -1,6 +1,6 @@ # Metadata -## [NEP-177](https://github.com/near/NEPs/discussions/177) +## [NEP-177](https://github.com/near/NEPs/blob/master/neps/nep-0177.md) Version `2.0.1` diff --git a/specs/Standards/NonFungibleToken/Payout.md b/specs/Standards/NonFungibleToken/Payout.md index 86f31f9e8..f7012de2b 100644 --- a/specs/Standards/NonFungibleToken/Payout.md +++ b/specs/Standards/NonFungibleToken/Payout.md @@ -1,6 +1,6 @@ # Royalties and Payouts -## (NEP-199) +## [NEP-199](https://github.com/near/NEPs/blob/master/neps/nep-0199.md) Version `2.0.0`. diff --git a/specs/Standards/StorageManagement.md b/specs/Standards/StorageManagement.md index c703eef0c..5a506ba5d 100644 --- a/specs/Standards/StorageManagement.md +++ b/specs/Standards/StorageManagement.md @@ -1,6 +1,6 @@ # Storage Management -## [NEP-145](https://github.com/near/NEPs/discussions/145) +## [NEP-145](https://github.com/near/NEPs/blob/master/neps/nep-0145.md) Version `1.0.0` From 3316778981c5b7bb607a9730092cbe312317276a Mon Sep 17 00:00:00 2001 From: Jay Logelin Date: Fri, 1 Apr 2022 16:29:47 -0300 Subject: [PATCH 026/150] Added zulip stream badge --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 85fe7f25c..7a7e4fa0e 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,6 @@ # NEAR Protocol Specifications and Standards +[![project chat](https://img.shields.io/badge/zulip-join_chat-brightgreen.svg)](https://near.zulipchat.com/#narrow/stream/320497-nep-standards) [![Discord](https://img.shields.io/discord/490367152054992913.svg)](http://near.chat) [![CI](https://github.com/near/NEPs/actions/workflows/build.yml/badge.svg)](https://github.com/near/NEPs/actions/workflows/build.yml) @@ -50,7 +51,7 @@ Ideas presented ultimately as NEPs will need to be driven by the author through Spec changes are ultimately done via pull requests to this repository (formalized process [here](neps/nep-0001.md)). In an effort to keep the pull request clean and readable, please follow these instructions to flesh out an idea. 1. Sign up for the [governance site](https://gov.near.org/) and make a post to the appropriate section. For instance, during the ideation phase of a standard, one might start a new conversation in the [Development » Standards section](https://gov.near.org/c/dev/standards/29). The other suggested category in the governance forum is the [Development » Proposals section](https://gov.near.org/c/dev/proposals/68). -2. The forum has comment threading which allows the community and NEAR Collective to ideate, ask questions, wrestle with approaches, etc. If more immediate responses are desired, consider bringing the conversation [Zulip](https://near.zulipchat.com/#narrow/stream/320497-nep-standards) or [to Discord](https://near.chat). +2. The forum has comment threading which allows the community and NEAR Collective to ideate, ask questions, wrestle with approaches, etc. If more immediate responses are desired, consider bringing the conversation to [Zulip](https://near.zulipchat.com/#narrow/stream/320497-nep-standards) or [Discord](https://near.chat). 3. When the governance conversations have reached a point where a clear plan is evident, create a pull request, using the instructions below. * Clone this repository and create a branch with "my-feature". From 3ff5cb0973dde7dcb83999ada69d89a8f1b1c3d2 Mon Sep 17 00:00:00 2001 From: Bowen Wang Date: Sat, 2 Apr 2022 11:43:08 -0700 Subject: [PATCH 027/150] fix: add genesis height documentation (#296) --- specs/GenesisConfig/GenesisConfig.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/specs/GenesisConfig/GenesisConfig.md b/specs/GenesisConfig/GenesisConfig.md index 74063189f..a2556a81c 100644 --- a/specs/GenesisConfig/GenesisConfig.md +++ b/specs/GenesisConfig/GenesisConfig.md @@ -12,6 +12,13 @@ _type: DateTime_ Official time of blockchain start. +## genesis_height + +_type: u64_ + +Height of the genesis block. Note that genesis height is not necessarily 0. +For example, mainnet genesis height is `9820210`. + ## chain_id _type: String_ From c4dba0b56f12afc0b7dd31a9ee79fe93a5191645 Mon Sep 17 00:00:00 2001 From: Zane Starr Date: Mon, 4 Apr 2022 04:34:38 -0700 Subject: [PATCH 028/150] feat: Multi Token Standard Contract [NEP] (#245) * feat: initial work for an emerging multi token standard This features the traits and proposal background information required have a proper specification for multiple tokens in a contract, that can be symmetric with other multi token contracts across chains. * chore: wrong issue link * chore: fix example comment on metadata * fix: add missing memo field to guide level entry for batch transfer Co-authored-by: marco-sundsk <47070476+marco-sundsk@users.noreply.github.com> * fix: add missing memo field to guide level entry for transfer Co-authored-by: marco-sundsk <47070476+marco-sundsk@users.noreply.github.com> * fix: consolidate batch versions of balance_of and balance_bounds * feat: add decimals to the contract to support tokens with precision reqs * fix: This refactors metadata to be one token metadata. The original thought was that splitting the metadata in two would allow users to more easily represent metadata that correspond to series. That said it was found that developers are more likely to write their own metadata view logic by implementing the metadata provider. The metadata provider is just the interface and the underlying implementation can do the sharing of data the same if its split or not .Therefore we decided to have on metadata interface to respond to to request and to implement. * feat: add answers to the unresolved questions in the NEP * fix: missing mt prefix from balance and suppky methods * chore: typo correction Co-authored-by: Mike Purvis * chore: typo correction Co-authored-by: Mike Purvis * fix: this makes symbol optional to be more in alignment with the other metadata standards. Symbol required doesn't make sense for NFT like tokens, and there fore should be optional. This will also serve to help consumers subjectively understand the nature of the token. * fix: add verson information at the top * fix: remove gnr8 example doesn't adhere to standard Co-authored-by: Mike Purvis * chore: typo correction Co-authored-by: Mike Purvis * chore: consistency of layout Co-authored-by: Daryl Collins * chore: lint typo Co-authored-by: Daryl Collins * chore: correct wording to make things more clear Co-authored-by: Daryl Collins * chore: tidy Co-authored-by: Daryl Collins * chore: tidy and clarify Co-authored-by: Daryl Collins * chore: typo correction and tidy Co-authored-by: Daryl Collins * chore: lint correction Co-authored-by: Daryl Collins * chore: tidy Co-authored-by: Daryl Collins * chore: typo correction Co-authored-by: Daryl Collins * chore: clarify Co-authored-by: Daryl Collins * chore: lint tidy Co-authored-by: Daryl Collins * fix: refactor to full spec naming Co-authored-by: Daryl Collins * fix: refactor to full spec naming Co-authored-by: Daryl Collins * chore: refactor to full spec naming and tidy Co-authored-by: Daryl Collins * fix: refactor to full spec naming Co-authored-by: Daryl Collins * fix: refactor to full spec naming and tidy Co-authored-by: Daryl Collins * chore: refactor to full spec naming and tidy Co-authored-by: Daryl Collins * chore: refactor to full spec naming Co-authored-by: Daryl Collins * chore: refactor to full spec naming and tidy Co-authored-by: Daryl Collins * chore: refactor to full spec naming Co-authored-by: Daryl Collins * chore: refactor to full spec naming and tidy Co-authored-by: Daryl Collins * chore: refactor to full spec naming and tidy Co-authored-by: Daryl Collins * chore: refactor to full spec naming and tidy Co-authored-by: Daryl Collins * chore: refactor to full spec naming and tidy Co-authored-by: Daryl Collins * chore: refactor to full spec naming and tidy Co-authored-by: Daryl Collins * chore: refactor to full spec naming and tidy Co-authored-by: Daryl Collins * chore: tidy Co-authored-by: Daryl Collins * chore: clarification Co-authored-by: Daryl Collins * chore: typo correction Co-authored-by: Daryl Collins * feat: add an approval management standard proposal for discussion * chore: clarify guide level explanation of balance * chore: clarify guide level explanation of supply * chore: clarify transfer tokens guide-level explanation * chore: reorder key for guide-level explanation * chore: add missing comments for balance_bounds and balance_of * fix: update standard to only support approvals by specific id * feat: refactor and add approval management back into the spec * chore: tidy Co-authored-by: Daryl Collins * fix: refactor metadata to split out metadata into it's own md * feat: add enumeration standard to multi token standard * chore: fix typos * fix: add MT prefixed datastructure descritpion and mt_prefixed methods * fix: refactor to have MT and mt_metadata prefixes and describe new MT metadata structures * chore: fix typos * fix: refactor Core description into typescript * chore: fix typos and lint * chore: lint and fix typos * fix: add support for mt_tokens * chore: fix typo and lint * fix: typos and lint * feat: add event spec for mt * fix: refactor README to match other standards * chore: lint, tidy, and typo correction to core Co-authored-by: Mike Purvis * chore: fix typos with enumeration Co-authored-by: Mike Purvis * chore: typos, lint, and tidy with approval management Co-authored-by: Mike Purvis * chore: refactor naming consistency , typo, lint with events Co-authored-by: Mike Purvis * chore: refactor to match event description Co-authored-by: Mike Purvis * chore: typos and lint with metadata Co-authored-by: Mike Purvis * chore: rm dead code for mt_approvals * chore: comment argument order matches impl order * chore: reorder comments to match impl args * chore: rm duplicate event description * fix: adjust consistency between standards for mt_tokens * chore: fix comments referencing Token and MTBaseTokenMetadata * chore: consistent spacing between metadata fields * chore: newline * fix: refactor events to match NFT events per standard spec * chore: fix link consistency within markdown * fix: token_ids to be an array for batch_balance_of * fix: confusing comment on the return for mt_resolve_transfer * chore: remove misleading comment from transfer methods * fix: base_by_metadata_id should return array * feat: add rationale section to further clarify decisions * chore: tidy account to account_id Co-authored-by: Olga Telezhnaya * chore: reword rationale to be more clear and less broad and more specific about limitations * chore: bring clarity to token type explanation * fix: add additional examples of authorized_id and clarify account_id * fix: align mt standard wth nft standard ref/ event standard * fix: update approvals to approved_account_ids to match other specs * fix: update specs to use token_id vs. id to align with other specs * fix: add new summary format for mt token spec * chore: refactor nep from 246 to 245 * chore: set status to draft * fix: refactor approvals to be iterative, vs included in Token. This change comes about because with Multi Token standard there may be many holders of a single token id. It may be gas prohibitive to return back all of the approval data for a token in the Token response. The solution was to introduce a new method called mt_token_approvals which allows one to iterate through, the list of token approvals for a specific token id. This is a minimal addition that allows consumers of the data to find all the approvals for a particular token id. * fix: add approval view logic for singular request * fix: adjust mt_transfer* and mt_resolve to provide granular resolution Prior to this fix, we had singular representation for token_ids that may have many owners. There was no way to resolve approvals for those types of tokens, typically ft style tokens. This change links together the owners of the accounts to the ft. So when an approval occurs we can resolve which account to transfer the tokens from as well as handle resolution of transfer failures from a singular token id with many owners. * fix: add summary listing to main readme * fix: refactor approval owner_id to approval_owner_id * fix: add reference current reference implementation locations * chore: add caution warning label to specification * chore: update links to latest reference implementation * chore: correct typos Co-authored-by: marco-sundsk <47070476+marco-sundsk@users.noreply.github.com> Co-authored-by: Mike Purvis Co-authored-by: Daryl Collins Co-authored-by: Olga Telezhnaya --- README.md | 1 + neps/nep-0245.md | 583 ++++++++++++++++++ .../MultiToken/ApprovalManagement.md | 503 +++++++++++++++ specs/Standards/MultiToken/Core.md | 399 ++++++++++++ specs/Standards/MultiToken/Enumeration.md | 84 +++ specs/Standards/MultiToken/Events.md | 187 ++++++ specs/Standards/MultiToken/Metadata.md | 144 +++++ specs/Standards/MultiToken/README.md | 7 + 8 files changed, 1908 insertions(+) create mode 100644 neps/nep-0245.md create mode 100644 specs/Standards/MultiToken/ApprovalManagement.md create mode 100644 specs/Standards/MultiToken/Core.md create mode 100644 specs/Standards/MultiToken/Enumeration.md create mode 100644 specs/Standards/MultiToken/Events.md create mode 100644 specs/Standards/MultiToken/Metadata.md create mode 100644 specs/Standards/MultiToken/README.md diff --git a/README.md b/README.md index 7a7e4fa0e..256041cc5 100644 --- a/README.md +++ b/README.md @@ -23,6 +23,7 @@ Changes to the protocol specification and standards are called NEAR Enhancement |[0178](https://github.com/near/NEPs/blob/master/neps/nep-0178.md) | Non Fungible Token Approval Management | @chadoh @thor314 | Final | |[0181](https://github.com/near/NEPs/blob/master/neps/nep-0181.md) | Non Fungible Token Enumeration | @chadoh @thor314 | Final | |[0199](https://github.com/near/NEPs/blob/master/neps/nep-0199.md) | Non Fungible Token Royalties and Payouts | @thor314 @mattlockyer | Final | +|[0245](https://github.com/near/NEPs/blob/master/neps/nep-0245.md) | Multi Token Standard | @zcstarr @riqi @jriemann @marcos.sun | Draft | |[0297](https://github.com/near/NEPs/blob/master/neps/nep-0297.md) | Contract Events Standard | @telezhnaya | Final | |[0330](https://github.com/near/NEPs/blob/master/neps/nep-0330.md) | Contract Metadata | @BenKurrek | Review | diff --git a/neps/nep-0245.md b/neps/nep-0245.md new file mode 100644 index 000000000..a9247bd3b --- /dev/null +++ b/neps/nep-0245.md @@ -0,0 +1,583 @@ +--- +NEP: 245 +Title: Multi Token Standard +Author: Zane Starr , @riqi, @jriemann, @marcos.sun +DiscussionsTo: https://github.com/near/NEPs/discussions/246 +Status: Draft +Type: Standards Track +Category: Contract +Created: 03-Mar-2022 +Requires: 297 +--- + +## Summary + +A standard interface for a multi token standard that supports fungible, semi-fungible,non-fungible, and tokens of any type, allowing for ownership, transfer, and batch transfer of tokens regardless of specific type. + +## Motivation + + +In the three years since [ERC-1155] was ratified by the Ethereum Community, Multi Token based contracts have proven themselves valuable assets. Many blockchain projects emulate this standard for representing multiple token assets classes in a single contract. The ability to reduce transaction overhead for marketplaces, video games, DAOs, and exchanges is appealing to the blockchain ecosystem and simplifies transactions for developers. + +Having a single contract represent NFTs, FTs, and tokens that sit inbetween greatly improves efficiency. The standard also introduced the ability to make batch requests with multiple asset classes reducing complexity. This standard allows operations that currently require _many_ transactions to be completed in a single transaction that can transfer not only NFTs and FTs, but any tokens that are a part of same token contract. + +With this standard, we have sought to take advantage of the ability of the NEAR blockchain to scale. Its sharded runtime, and [storage staking] model that decouples [gas] fees from storage demand, enables ultra low transaction fees and greater on chain storage ( see [Metadata] extension). + +With the aforementioned, it is noteworthy to mention that like the [NFT] standard the Multi Token standard, implements `mt_transfer_call`, +which allows, a user to attach many tokens to a call to a separate contract. Additionally, this standard includes an optional [Approval Management] extension. The extension allows marketplaces to trade on behalf of a user, providing additional flexibility for dApps. + +Prior art: + +- [ERC-721] +- [ERC-1155] +- [NEAR Fungible Token Standard][FT], which first pioneered the "transfer and call" technique +- [NEAR Non-Fungible Token Standard][NFT] + +## Rationale and alternatives + +Why have another standard, aren't fungible and non-fungible tokens enough? The current fungible token and non-fungible token standards, do not provide support for representing many FT tokens in a single contract, as well as the flexibility to define different token types with different behavior in a single contract. This is something that makes it difficult to be interoperable with other major blockchain networks, that implement standards that allow for representation of many different FT tokens in a single contract such as Ethereum. + +The standard here introduces a few concepts that evolve the original [ERC-1155] standard to have more utility, while maintaining the original flexibility of the standard. So keeping that in mind, we are defining this as a new token type. It combines two main features of FT and NFT. It allows us to represent many token types in a single contract, and it's possible to store the amount for each token. + +The decision to not use FT and NFT as explicit token types was taken to allow the community to define their own standards and meanings through metadata. As standards evolve on other networks, this specification allows the standard to be able to represent tokens across networks accurately, without necessarily restricting the behavior to any preset definition. + +The issues with this in general is a problem with defining what metadata means and how is that interpreted. We have chosen to follow the pattern that is currently in use on Ethereum in the [ERC-1155] standard. That pattern relies on people to make extensions or to make signals as to how they want the metadata to be represented for their use case. + +One of the areas that has broad sweeping implications from the [ERC-1155] standard is the lack of direct access to metadata. With Near's sharding we are able to have a [Metadata Extension](Metadata.md) for the standard that exists on chain. So developers and users are not required to use an indexer to understand, how to interact or interpret tokens, via token identifiers that they receive. + +Another extension that we made was to provide an explicit ability for developers and users to group or link together series of NFTs/FTs or any combination of tokens. This provides additional flexiblity that the [ERC-1155] standard only has loose guidelines on. This was chosen to make it easy for consumers to understand the relationship between tokens within the contract. + +To recap, we choose to create this standard, to improve interoperability, developer ease of use, and to extend token representability beyond what was available directly in the FT or NFT standards. We believe this to be another tool in the developer's toolkit. It makes it possible to represent many types of tokens and to enable exchanges of many tokens within a single `transaction`. + +## Specification + +**NOTES**: +- All amounts, balances and allowance are limited by `U128` (max value `2**128 - 1`). +- Token standard uses JSON for serialization of arguments and results. +- Amounts in arguments and results are serialized as Base-10 strings, e.g. `"100"`. This is done to avoid JSON limitation of max integer value of `2**53`. +- The contract must track the change in storage when adding to and removing from collections. This is not included in this core multi token standard but instead in the [Storage Standard](../StorageManagement.md). +- To prevent the deployed contract from being modified or deleted, it should not have any access keys on its account. + +### MT Interface + +```ts +// The base structure that will be returned for a token. If contract is using +// extensions such as Approval Management, Enumeration, Metadata, or other +// attributes may be included in this structure. +type Token = { + token_id: string, + owner_id: string | null +} + +/******************/ +/* CHANGE METHODS */ +/******************/ + +// Simple transfer. Transfer a given `token_id` from current owner to +// `receiver_id`. +// +// Requirements +// * Caller of the method must attach a deposit of 1 yoctoⓃ for security purposes +// * Caller must have greater than or equal to the `amount` being requested +// * Contract MUST panic if called by someone other than token owner or, +// if using Approval Management, one of the approved accounts +// * `approval_id` is for use with Approval Management extension, see +// that document for full explanation. +// * If using Approval Management, contract MUST nullify approved accounts on +// successful transfer. +// +// Arguments: +// * `receiver_id`: the valid NEAR account receiving the token +// * `token_id`: the token to transfer +// * `amount`: the number of tokens to transfer, wrapped in quotes and treated +// like a string, although the number will be stored as an unsigned integer +// with 128 bits. +// * `approval` (optional): is a tuple of [`owner_id`,`approval_id`]. +// `owner_id` is the valid Near account that owns the tokens. +// `approval_id` is the expected approval ID. A number smaller than +// 2^53, and therefore representable as JSON. See Approval Management +// standard for full explanation. +// * `memo` (optional): for use cases that may benefit from indexing or +// providing information for a transfer + + +function mt_transfer( + receiver_id: string, + token_id: string, + amount: string, + approval: [owner_id: string, approval_id: number]|null, + memo: string|null, +) {} + +// Simple batch transfer. Transfer a given `token_ids` from current owner to +// `receiver_id`. +// +// Requirements +// * Caller of the method must attach a deposit of 1 yoctoⓃ for security purposes +// * Caller must have greater than or equal to the `amounts` being requested for the given `token_ids` +// * Contract MUST panic if called by someone other than token owner or, +// if using Approval Management, one of the approved accounts +// * `approval_id` is for use with Approval Management extension, see +// that document for full explanation. +// * If using Approval Management, contract MUST nullify approved accounts on +// successful transfer. +// * Contract MUST panic if called with the length of `token_ids` not equal to `amounts` is not equal +// * Contract MUST panic if `approval_ids` is not `null` and does not equal the length of `token_ids` +// +// Arguments: +// * `receiver_id`: the valid NEAR account receiving the token +// * `token_ids`: the tokens to transfer +// * `amounts`: the number of tokens to transfer, wrapped in quotes and treated +// like an array of strings, although the numbers will be stored as an array of unsigned integer +// with 128 bits. +// * `approvals` (optional): is an array of expected `approval` per `token_ids`. +// If a `token_id` does not have a corresponding `approval` then the entry in the array +// must be marked null. +// `approval` is a tuple of [`owner_id`,`approval_id`]. +// `owner_id` is the valid Near account that owns the tokens. +// `approval_id` is the expected approval ID. A number smaller than +// 2^53, and therefore representable as JSON. See Approval Management +// standard for full explanation. +// * `memo` (optional): for use cases that may benefit from indexing or +// providing information for a transfer + + +function mt_batch_transfer( + receiver_id: string, + token_ids: string[], + amounts: string[], + approvals: ([owner_id: string, approval_id: number]| null)[]| null, + memo: string|null, +) {} + + +// Transfer token and call a method on a receiver contract. A successful +// workflow will end in a success execution outcome to the callback on the MT +// contract at the method `mt_resolve_transfer`. +// +// You can think of this as being similar to attaching native NEAR tokens to a +// function call. It allows you to attach any Multi Token, token in a call to a +// receiver contract. +// +// Requirements: +// * Caller of the method must attach a deposit of 1 yoctoⓃ for security +// purposes +// * Caller must have greater than or equal to the `amount` being requested +// * Contract MUST panic if called by someone other than token owner or, +// if using Approval Management, one of the approved accounts +// * The receiving contract must implement `mt_on_transfer` according to the +// standard. If it does not, MT contract's `mt_resolve_transfer` MUST deal +// with the resulting failed cross-contract call and roll back the transfer. +// * Contract MUST implement the behavior described in `mt_resolve_transfer` +// * `approval_id` is for use with Approval Management extension, see +// that document for full explanation. +// * If using Approval Management, contract MUST nullify approved accounts on +// successful transfer. +// +// Arguments: +// * `receiver_id`: the valid NEAR account receiving the token. +// * `token_id`: the token to send. +// * `amount`: the number of tokens to transfer, wrapped in quotes and treated +// like a string, although the number will be stored as an unsigned integer +// with 128 bits. +// * `owner_id`: the valid NEAR account that owns the token +// * `approval` (optional): is a tuple of [`owner_id`,`approval_id`]. +// `owner_id` is the valid Near account that owns the tokens. +// `approval_id` is the expected approval ID. A number smaller than +// 2^53, and therefore representable as JSON. See Approval Management +// * `memo` (optional): for use cases that may benefit from indexing or +// providing information for a transfer. +// * `msg`: specifies information needed by the receiving contract in +// order to properly handle the transfer. Can indicate both a function to +// call and the parameters to pass to that function. + + +function mt_transfer_call( + receiver_id: string, + token_id: string, + amount: string, + approval: [owner_id: string, approval_id: number]|null, + memo: string|null, + msg: string, +): Promise {} + + + +// Transfer tokens and call a method on a receiver contract. A successful +// workflow will end in a success execution outcome to the callback on the MT +// contract at the method `mt_resolve_transfer`. +// +// You can think of this as being similar to attaching native NEAR tokens to a +// function call. It allows you to attach any Multi Token, token in a call to a +// receiver contract. +// +// Requirements: +// * Caller of the method must attach a deposit of 1 yoctoⓃ for security +// purposes +// * Caller must have greater than or equal to the `amount` being requested +// * Contract MUST panic if called by someone other than token owner or, +// if using Approval Management, one of the approved accounts +// * The receiving contract must implement `mt_on_transfer` according to the +// standard. If it does not, MT contract's `mt_resolve_transfer` MUST deal +// with the resulting failed cross-contract call and roll back the transfer. +// * Contract MUST implement the behavior described in `mt_resolve_transfer` +// * `approval_id` is for use with Approval Management extension, see +// that document for full explanation. +// * If using Approval Management, contract MUST nullify approved accounts on +// successful transfer. +// * Contract MUST panic if called with the length of `token_ids` not equal to `amounts` is not equal +// * Contract MUST panic if `approval_ids` is not `null` and does not equal the length of `token_ids` +// +// Arguments: +// * `receiver_id`: the valid NEAR account receiving the token. +// * `token_ids`: the tokens to transfer +// * `amounts`: the number of tokens to transfer, wrapped in quotes and treated +// like an array of string, although the numbers will be stored as an array of +// unsigned integer with 128 bits. +// * `approvals` (optional): is an array of expected `approval` per `token_ids`. +// If a `token_id` does not have a corresponding `approval` then the entry in the array +// must be marked null. +// `approval` is a tuple of [`owner_id`,`approval_id`]. +// `owner_id` is the valid Near account that owns the tokens. +// `approval_id` is the expected approval ID. A number smaller than +// 2^53, and therefore representable as JSON. See Approval Management +// standard for full explanation. +// * `memo` (optional): for use cases that may benefit from indexing or +// providing information for a transfer. +// * `msg`: specifies information needed by the receiving contract in +// order to properly handle the transfer. Can indicate both a function to +// call and the parameters to pass to that function. + + +function mt_batch_transfer_call( + receiver_id: string, + token_ids: string[], + amounts: string[], + approvals: ([owner_id: string, approval_id: number]|null)[] | null, + memo: string|null, + msg: string, +): Promise {} + +/****************/ +/* VIEW METHODS */ +/****************/ + + +// Returns the tokens with the given `token_ids` or `null` if no such token. +function mt_token(token_ids: string[]) (Token | null)[] + +// Returns the balance of an account for the given `token_id`. +// The balance though wrapped in quotes and treated like a string, +// the number will be stored as an unsigned integer with 128 bits. +// Arguments: +// * `account_id`: the NEAR account that owns the token. +// * `token_id`: the token to retrieve the balance from +function mt_balance_of(account_id: string, token_id: string): string + +// Returns the balances of an account for the given `token_ids`. +// The balances though wrapped in quotes and treated like strings, +// the numbers will be stored as an unsigned integer with 128 bits. +// Arguments: +// * `account_id`: the NEAR account that owns the tokens. +// * `token_ids`: the tokens to retrieve the balance from +function mt_batch_balance_of(account_id: string, token_ids: string[]): string[] + +// Returns the token supply with the given `token_id` or `null` if no such token exists. +// The supply though wrapped in quotes and treated like a string, the number will be stored +// as an unsigned integer with 128 bits. +function mt_supply(token_id: string): string | null + +// Returns the token supplies with the given `token_ids`, a string value is returned or `null` +// if no such token exists. The supplies though wrapped in quotes and treated like strings, +// the numbers will be stored as an unsigned integer with 128 bits. +function mt_batch_supply(token_ids: string[]): (string | null)[] +``` + +The following behavior is required, but contract authors may name this function something other than the conventional `mt_resolve_transfer` used here. + +```ts +// Finalize an `mt_transfer_call` or `mt_batch_transfer_call` chain of cross-contract calls. Generically +// referred to as `mt_transfer_call` as it applies to `mt_batch_transfer_call` as well. +// +// The `mt_transfer_call` process: +// +// 1. Sender calls `mt_transfer_call` on MT contract +// 2. MT contract transfers token from sender to receiver +// 3. MT contract calls `mt_on_transfer` on receiver contract +// 4+. [receiver contract may make other cross-contract calls] +// N. MT contract resolves promise chain with `mt_resolve_transfer`, and may +// transfer token back to sender +// +// Requirements: +// * Contract MUST forbid calls to this function by any account except self +// * If promise chain failed, contract MUST revert token transfer +// * If promise chain resolves with `true`, contract MUST return token to +// `sender_id` +// +// Arguments: +// * `sender_id`: the sender of `mt_transfer_call` +// * `receiver_id`: the `receiver_id` argument given to `mt_transfer_call` +// * `token_ids`: the `token_ids` argument given to `mt_transfer_call` +// * `amounts`: the `token_ids` argument given to `mt_transfer_call` +// * `approvals (optional)`: if using Approval Management, contract MUST provide +// set of original approvals in this argument, and restore the +// approved accounts in case of revert. +// `approvals` is an array of expected `approval_list` per `token_ids`. +// If a `token_id` does not have a corresponding `approvals_list` then the entry in the +// array must be marked null. +// `approvals_list` is an array of triplets of [`owner_id`,`approval_id`,`amount`]. +// `owner_id` is the valid Near account that owns the tokens. +// `approval_id` is the expected approval ID. A number smaller than +// 2^53, and therefore representable as JSON. See Approval Management +// standard for full explanation. +// `amount`: the number of tokens to transfer, wrapped in quotes and treated +// like a string, although the number will be stored as an unsigned integer +// with 128 bits. +// +// +// +// Returns total amount spent by the `receiver_id`, corresponding to the `token_id`. +// The amounts returned, though wrapped in quotes and treated like strings, +// the numbers will be stored as an unsigned integer with 128 bits. +// Example: if sender_id calls `mt_transfer_call({ "amounts": ["100"], token_ids: ["55"], receiver_id: "games" })`, +// but `receiver_id` only uses 80, `mt_on_transfer` will resolve with `["20"]`, and `mt_resolve_transfer` +// will return `["80"]`. + + +function mt_resolve_transfer( + sender_id: string, + receiver_id: string, + token_ids: string[], + approvals: (null | [owner_id: string, approval_id: number, amount: string][]) []| null +):string[] {} +``` + +### Receiver Interface + +Contracts which want to make use of `mt_transfer_call` and `mt_batch_transfer_call` must implement the following: + +```ts +// Take some action after receiving a multi token +// +// Requirements: +// * Contract MUST restrict calls to this function to a set of whitelisted +// contracts +// * Contract MUST panic if `token_ids` length does not equals `amounts` +// length +// * Contract MUST panic if `previous_owner_ids` length does not equals `token_ids` +// length +// +// Arguments: +// * `sender_id`: the sender of `mt_transfer_call` +// * `previous_owner_ids`: the account that owned the tokens prior to it being +// transferred to this contract, which can differ from `sender_id` if using +// Approval Management extension +// * `token_ids`: the `token_ids` argument given to `mt_transfer_call` +// * `amounts`: the `token_ids` argument given to `mt_transfer_call` +// * `msg`: information necessary for this contract to know how to process the +// request. This may include method names and/or arguments. +// +// Returns the number of unused tokens in string form. For instance, if `amounts` +// is `["10"]` but only 9 are needed, it will return `["1"]`. The amounts returned, +// though wrapped in quotes and treated like strings, the numbers will be stored as +// an unsigned integer with 128 bits. + + +function mt_on_transfer( + sender_id: string, + previous_owner_ids: string[], + token_ids: string[], + amounts: string[], + msg: string, +): Promise; +``` + +## Events + +NEAR and third-party applications need to track + `mint`, `burn`, `transfer` events for all MT-driven apps consistently. This exension addresses that. + +Note that applications, including NEAR Wallet, could require implementing additional methods to display tokens correctly such as [`mt_metadata`](Metadata.md) and [`mt_tokens_for_owner`](Enumeration.md). + +### Events Interface +Multi Token Events MUST have `standard` set to `"nep245"`, standard version set to `"1.0.0"`, `event` value is one of `mt_mint`, `mt_burn`, `mt_transfer`, and `data` must be of one of the following relavant types: `MtMintLog[] | MtBurnLog[] | MtTransferLog[]`: + + + +```ts +interface MtEventLogData { + EVENT_JSON: { + standard: "nep245", + version: "1.0.0", + event: MtEvent, + data: MtMintLog[] | MtBurnLog[] | MtTransferLog[] + } +} +``` + +```ts +// Minting event log. Emitted when a token is minted/created. +// Requirements +// * Contract MUST emit event when minting a token +// Fields +// * Contract token_ids and amounts MUST be the same length +// * `owner_id`: the account receiving the minted token +// * `token_ids`: the tokens minted +// * `amounts`: the number of tokens minted, wrapped in quotes and treated +// like a string, although the numbers will be stored as an unsigned integer +// array with 128 bits. +// * `memo`: optional message +interface MtMintLog { + owner_id: string, + token_ids: string[], + amounts: string[], + memo?: string +} + +// Burning event log. Emitted when a token is burned. +// Requirements +// * Contract MUST emit event when minting a token +// Fields +// * Contract token_ids and amounts MUST be the same length +// * `owner_id`: the account whose token(s) are being burned +// * `authorized_id`: approved account_id to burn, if applicable +// * `token_ids`: the tokens being burned +// * `amounts`: the number of tokens burned, wrapped in quotes and treated +// like a string, although the numbers will be stored as an unsigned integer +// array with 128 bits. +// * `memo`: optional message +interface MtBurnLog { + owner_id: string, + authorized_id?: string, + token_ids: string[], + amounts: string[], + memo?: string +} + +// Transfer event log. Emitted when a token is transferred. +// Requirements +// * Contract MUST emit event when transferring a token +// Fields +// * `authorized_id`: approved account_id to transfer +// * `old_owner_id`: the account sending the tokens "sender.near" +// * `new_owner_id`: the account receiving the tokens "receiver.near" +// * `token_ids`: the tokens to transfer +// * `amounts`: the number of tokens to transfer, wrapped in quotes and treated +// like a string, although the numbers will be stored as an unsigned integer +// array with 128 bits. +interface MtTransferLog { + authorized_id?: string, + old_owner_id: string, + new_owner_id: string, + token_ids: string[], + amounts: string[], + memo?: string +} +``` + +## Examples + +Single owner minting (pretty-formatted for readability purposes): + +```js +EVENT_JSON:{ + "standard": "nep245", + "version": "1.0.0", + "event": "mt_mint", + "data": [ + {"owner_id": "foundation.near", "token_ids": ["aurora", "proximitylabs_ft"], "amounts":["1", "100"]} + ] +} +``` + +Different owners minting: + +```js +EVENT_JSON:{ + "standard": "nep245", + "version": "1.0.0", + "event": "mt_mint", + "data": [ + {"owner_id": "foundation.near", "token_ids": ["aurora", "proximitylabs_ft"], "amounts":["1","100"]}, + {"owner_id": "user1.near", "token_ids": ["meme"], "amounts": ["1"]} + ] +} +``` + +Different events (separate log entries): + +```js +EVENT_JSON:{ + "standard": "nep245", + "version": "1.0.0", + "event": "mt_burn", + "data": [ + {"owner_id": "foundation.near", "token_ids": ["aurora", "proximitylabs_ft"], "amounts": ["1","100"]}, + ] +} +``` + +Authorized id: + +```js +EVENT_JSON:{ + "standard": "nep245", + "version": "1.0.0", + "event": "mt_burn", + "data": [ + {"owner_id": "foundation.near", "token_ids": ["aurora_alpha", "proximitylabs_ft"], "amounts": ["1","100"], "authorized_id": "thirdparty.near" }, + ] +} +``` + +```js +EVENT_JSON:{ + "standard": "nep245", + "version": "1.0.0", + "event": "mt_transfer", + "data": [ + {"old_owner_id": "user1.near", "new_owner_id": "user2.near", "token_ids": ["meme"], "amounts":["1"], "memo": "have fun!"} + ] +} + +EVENT_JSON:{ + "standard": "nep245", + "version": "1.0.0", + "event": "mt_transfer", + "data": [ + {"old_owner_id": "user2.near", "new_owner_id": "user3.near", "token_ids": ["meme"], "amounts":["1"], "authorized_id": "thirdparty.near", "memo": "have fun!"} + ] +} +``` + +## Further Event Methods + +Note that the example events covered above cover two different kinds of events: +1. Events that are not specified in the MT Standard (`mt_mint`, `mt_burn`) +2. An event that is covered in the [Multi Token Core Standard](https://nomicon.io/Standards/MultiToken/Core.html#mt-interface). (`mt_transfer`) + +This event standard also applies beyond the three events highlighted here, where future events follow the same convention of as the second type. For instance, if an MT contract uses the [approval management standard](https://nomicon.io/Standards/MultiToken/ApprovalManagement.html), it may emit an event for `mt_approve` if that's deemed as important by the developer community. + +Please feel free to open pull requests for extending the events standard detailed here as needs arise. + +## Reference Implementation + +[Minimum Viable Interface](https://github.com/jriemann/near-sdk-rs/blob/multi-token-reference-impl/near-contract-standards/src/multi_token/core/mod.rs) + +[MT Implementation](https://github.com/jriemann/near-sdk-rs/blob/multi-token-reference-impl/near-contract-standards/src/multi_token/core/core_impl.rs) + + + +## Copyright +[copyright]: #copyright + +Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). + + [ERC-721]: https://eips.ethereum.org/EIPS/eip-721 + [ERC-1155]: https://eips.ethereum.org/EIPS/eip-1155 + [storage staking]: https://docs.near.org/docs/concepts/storage-staking + [gas]: https://docs.near.org/docs/concepts/gas + [Metadata]: ../specs/Standards/MultiToken/Metadata.md + [NFT]: ../specs/Standards/NonFungibleToken/Core.md + [Approval Management]: ../specs/Standards/MultiToken/ApprovalManagement.md + [FT]: ../specs/Standards/FungibleToken/Core.md \ No newline at end of file diff --git a/specs/Standards/MultiToken/ApprovalManagement.md b/specs/Standards/MultiToken/ApprovalManagement.md new file mode 100644 index 000000000..11420f76e --- /dev/null +++ b/specs/Standards/MultiToken/ApprovalManagement.md @@ -0,0 +1,503 @@ +# Multi Token Standard Approval Management([NEP-245](https://github.com/near/NEPs/discussions/246)) + +:::caution +This is part of the proposed spec [NEP-245](https://github.com/near/NEPs/blob/master/neps/nep-0245.md) and is subject to change. +::: + + +Version `1.0.0` + +## Summary + +A system for allowing a set of users or contracts to transfer specific tokens on behalf of an owner. Similar to approval management systems in standards like [ERC-721] and [ERC-1155]. + + [ERC-721]: https://eips.ethereum.org/EIPS/eip-721 + [ERC-1155]: https://eips.ethereum.org/EIPS/eip-1155 +## Motivation + +People familiar with [ERC-721] may expect to need an approval management system for basic transfers, where a simple transfer from Alice to Bob requires that Alice first _approve_ Bob to spend one of her tokens, after which Bob can call `transfer_from` to actually transfer the token to himself. + +NEAR's [core Multi Token standard](README.md) includes good support for safe atomic transfers without such complexity. It even provides "transfer and call" functionality (`mt_transfer_call`) which allows specific tokens to be "attached" to a call to a separate contract. For many token workflows, these options may circumvent the need for a full-blown Approval Management system. + +However, some Multi Token developers, marketplaces, dApps, or artists may require greater control. This standard provides a uniform interface allowing token owners to approve other NEAR accounts, whether individuals or contracts, to transfer specific tokens on the owner's behalf. + +Prior art: + +- Ethereum's [ERC-721] +- Ethereum's [ERC-1155] + +## Example Scenarios + +Let's consider some examples. Our cast of characters & apps: + +* Alice: has account `alice` with no contract deployed to it +* Bob: has account `bob` with no contract deployed to it +* MT: a contract with account `mt`, implementing only the [Multi Token Standard](Core.md) with this Approval Management extension +* Market: a contract with account `market` which sells tokens from `mt` as well as other token contracts +* Bazaar: similar to Market, but implemented differently (spoiler alert: has no `mt_on_approve` function!), has account `bazaar` + +Alice and Bob are already [registered](../StorageManagement.md) with MT, Market, and Bazaar, and Alice owns a token on the MT contract with ID=`"1"` and a fungible style token with ID =`"2"` and AMOUNT =`"100"`. + +Let's examine the technical calls through the following scenarios: + +1. [Simple approval](#1-simple-approval): Alice approves Bob to transfer her token. +2. [Approval with cross-contract call (XCC)](#2-approval-with-cross-contract-call): Alice approves Market to transfer one of her tokens and passes `msg` so that MT will call `mt_on_approve` on Market's contract. +3. [Approval with XCC, edge case](#3-approval-with-cross-contract-call-edge-case): Alice approves Bazaar and passes `msg` again, but what's this? Bazaar doesn't implement `mt_on_approve`, so Alice sees an error in the transaction result. Not to worry, though, she checks `mt_is_approved` and sees that she did successfully approve Bazaar, despite the error. +4. [Approval IDs](#4-approval-ids): Bob buys Alice's token via Market. +5. [Approval IDs, edge case](#5-approval-ids-edge-case): Bob transfers same token back to Alice, Alice re-approves Market & Bazaar. Bazaar has an outdated cache. Bob tries to buy from Bazaar at the old price. +6. [Revoke one](#6-revoke-one): Alice revokes Market's approval for this token. +7. [Revoke all](#7-revoke-all): Alice revokes all approval for this token. + +### 1. Simple Approval + +Alice approves Bob to transfer her tokens. + +**High-level explanation** + +1. Alice approves Bob +2. Alice queries the token to verify + +**Technical calls** + +1. Alice calls `mt::mt_approve({ "token_ids": ["1","2"], amounts:["1","100"], "account_id": "bob" })`. She attaches 1 yoctoⓃ, (.000000000000000000000001Ⓝ). Using [NEAR CLI](https://docs.near.org/docs/tools/near-cli) to make this call, the command would be: + + near call mt mt_approve \ + '{ "token_ids": ["1","2"], amounts: ["1","100"], "account_id": "bob" }' \ + --accountId alice --amount .000000000000000000000001 + + The response: + + '' +2. Alice calls view method `mt_is_approved`: + + near view mt mt_is_approved \ + '{ "token_ids": ["1", "2"], amounts:["1","100"], "approved_account_id": "bob" }' + + The response: + + true + +### 3. Approval with cross-contract call + +Alice approves Market to transfer some of her tokens and passes `msg` so that MT will call `mt_on_approve` on Market's contract. She probably does this via Market's frontend app which would know how to construct `msg` in a useful way. + +**High-level explanation** + +1. Alice calls `mt_approve` to approve `market` to transfer her token, and passes a `msg` +2. Since `msg` is included, `mt` will schedule a cross-contract call to `market` +3. Market can do whatever it wants with this info, such as listing the token for sale at a given price. The result of this operation is returned as the promise outcome to the original `mt_approve` call. + +**Technical calls** + +1. Using near-cli: + + near call mt mt_approve '{ + "token_ids": ["1","2"], + "amounts": ["1", "100"], + "account_id": "market", + "msg": "{\"action\": \"list\", \"price\": [\"100\",\"50\"],\"token\": \"nDAI\" }" + }' --accountId alice --amount .000000000000000000000001 + + At this point, near-cli will hang until the cross-contract call chain fully resolves, which would also be true if Alice used a Market frontend using [near-api-js](https://docs.near.org/docs/develop/front-end/near-api-js). Alice's part is done, though. The rest happens behind the scenes. + +2. `mt` schedules a call to `mt_on_approve` on `market`. Using near-cli notation for easy cross-reference with the above, this would look like: + + near call market mt_on_approve '{ + "token_ids": ["1","2"], + "amounts": ["1","100"], + "owner_id": "alice", + "approval_ids": ["4","5"], + "msg": "{\"action\": \"list\", \"price\": [\"100\",\"50\"], \"token\": \"nDAI\" }" + }' --accountId mt + +3. `market` now knows that it can sell Alice's tokens for 100 [nDAI](https://explorer.mainnet.near.org/accounts/6b175474e89094c44da98b954eedeac495271d0f.factory.bridge.near) and 50 [nDAI](https://explorer.mainnet.near.org/accounts/6b175474e89094c44da98b954eedeac495271d0f.factory.bridge.near), and that when it transfers it to a buyer using `mt_batch_transfer`, it can pass along the given `approval_ids` to ensure that Alice hasn't changed her mind. It can schedule any further cross-contract calls it wants, and if it returns these promises correctly, Alice's initial near-cli call will resolve with the outcome from the final step in the chain. If Alice actually made this call from a Market frontend, the frontend can use this return value for something useful. + +### 3. Approval with cross-contract call, edge case + +Alice approves Bazaar and passes `msg` again. Maybe she actually does this via near-cli, rather than using Bazaar's frontend, because what's this? Bazaar doesn't implement `mt_on_approve`, so Alice sees an error in the transaction result. + +Not to worry, though, she checks `mt_is_approved` and sees that she did successfully approve Bazaar, despite the error. She will have to find a new way to list her token for sale in Bazaar, rather than using the same `msg` shortcut that worked for Market. + +**High-level explanation** + +1. Alice calls `mt_approve` to approve `bazaar` to transfer her token, and passes a `msg`. +2. Since `msg` is included, `mt` will schedule a cross-contract call to `bazaar`. +3. Bazaar doesn't implement `mt_on_approve`, so this call results in an error. The approval still worked, but Alice sees an error in her near-cli output. +4. Alice checks if `bazaar` is approved, and sees that it is, despite the error. + +**Technical calls** + +1. Using near-cli: + + near call mt mt_approve '{ + "token_ids": ["1"], + "amounts: ["1000"], + "account_id": "bazaar", + "msg": "{\"action\": \"list\", \"price\": \"100\", \"token\": \"nDAI\" }" + }' --accountId alice --amount .000000000000000000000001 + +2. `mt` schedules a call to `mt_on_approve` on `market`. Using near-cli notation for easy cross-reference with the above, this would look like: + + near call bazaar mt_on_approve '{ + "token_ids": ["1"], + "amounts": ["1000"], + "owner_id": "alice", + "approval_ids": [3], + "msg": "{\"action\": \"list\", \"price\": \"100\", \"token\": \"nDAI\" }" + }' --accountId mt + +3. 💥 `bazaar` doesn't implement this method, so the call results in an error. Alice sees this error in the output from near-cli. + +4. Alice checks if the approval itself worked, despite the error on the cross-contract call: + + near view mt mt_is_approved \ + '{ "token_ids": ["1","2"], "amounts":["1","100"], "approved_account_id": "bazaar" }' + + The response: + + true + +### 4. Approval IDs + +Bob buys Alice's token via Market. Bob probably does this via Market's frontend, which will probably initiate the transfer via a call to `ft_transfer_call` on the nDAI contract to transfer 100 nDAI to `market`. Like the MT standard's "transfer and call" function, [Fungible Token](../FungibleToken/Core.md)'s `ft_transfer_call` takes a `msg` which `market` can use to pass along information it will need to pay Alice and actually transfer the MT. The actual transfer of the MT is the only part we care about here. + +**High-level explanation** + +1. Bob signs some transaction which results in the `market` contract calling `mt_transfer` on the `mt` contract, as described above. To be trustworthy and pass security audits, `market` needs to pass along `approval_id` so that it knows it has up-to-date information. + +**Technical calls** + +Using near-cli notation for consistency: + + near call mt mt_transfer '{ + "receiver_id": "bob", + "token_id": "1", + "amount": "1", + "approval_id": 2, + }' --accountId market --amount .000000000000000000000001 + +### 5. Approval IDs, edge case +Bob transfers same token back to Alice, Alice re-approves Market & Bazaar, listing her token at a higher price than before. Bazaar is somehow unaware of these changes, and still stores `approval_id: 3` internally along with Alice's old price. Bob tries to buy from Bazaar at the old price. Like the previous example, this probably starts with a call to a different contract, which eventually results in a call to `mt_transfer` on `bazaar`. Let's consider a possible scenario from that point. + +**High-level explanation** + +Bob signs some transaction which results in the `bazaar` contract calling `mt_transfer` on the `mt` contract, as described above. To be trustworthy and pass security audits, `bazaar` needs to pass along `approval_id` so that it knows it has up-to-date information. It does not have up-to-date information, so the call fails. If the initial `mt_transfer` call is part of a call chain originating from a call to `ft_transfer_call` on a fungible token, Bob's payment will be refunded and no assets will change hands. + +**Technical calls** + +Using near-cli notation for consistency: + + near call mt mt_transfer '{ + "receiver_id": "bob", + "token_id": "1", + "amount": "1", + "approval_id": 3, + }' --accountId bazaar --amount .000000000000000000000001 + +### 6. Revoke one + +Alice revokes Market's approval for this token. + +**Technical calls** + +Using near-cli: + + near call mt mt_revoke '{ + "account_id": "market", + "token_ids": ["1"], + }' --accountId alice --amount .000000000000000000000001 + +Note that `market` will not get a cross-contract call in this case. The implementors of the Market app should implement [cron](https://en.wikipedia.org/wiki/Cron)-type functionality to intermittently check that Market still has the access they expect. + +### 7. Revoke all + +Alice revokes all approval for these tokens + +**Technical calls** + +Using near-cli: + + near call mt mt_revoke_all '{ + "token_ids": ["1", "2"], + }' --accountId alice --amount .000000000000000000000001 + +Again, note that no previous approvers will get cross-contract calls in this case. + + +## Reference-level explanation + +The `TokenApproval` structure returned by `mt_token_approvals` returns `approved_account_ids` field, which is a map of account IDs to `Approval` and `approval_owner_id` which is the associated account approved for removal from. The `amount` field though wrapped in quotes and treated like strings, the number will be stored as an unsigned integer with 128 bits. + in approval is Using TypeScript's [Record type](https://www.typescriptlang.org/docs/handbook/utility-types.html#recordkeystype) notation: + +```diff ++ type Approval = { ++ amount: string ++ approval_id: string ++ } ++ ++ type TokenApproval = { ++ approval_owner_id: string, ++ approved_account_ids: Record, ++ }; +``` + +Example token approval data: + +```json +[{ + "approval_owner_id": "alice.near", + "approved_account_ids": { + "bob.near": { + "amount": "100", + "approval_id":1, + }, + "carol.near": { + "amount":"2", + "approval_id": 2, + } + } +}] +``` + +### What is an "approval ID"? + +This is a unique number given to each approval that allows well-intentioned marketplaces or other 3rd-party MT resellers to avoid a race condition. The race condition occurs when: + +1. A token is listed in two marketplaces, which are both saved to the token as approved accounts. +2. One marketplace sells the token, which clears the approved accounts. +3. The new owner sells back to the original owner. +4. The original owner approves the token for the second marketplace again to list at a new price. But for some reason the second marketplace still lists the token at the previous price and is unaware of the transfers happening. +5. The second marketplace, operating from old information, attempts to again sell the token at the old price. + +Note that while this describes an honest mistake, the possibility of such a bug can also be taken advantage of by malicious parties via [front-running](https://defi.cx/front-running-ethereum/). + +To avoid this possibility, the MT contract generates a unique approval ID each time it approves an account. Then when calling `mt_transfer`, `mt_transfer_call`, `mt_batch_transfer`, or `mt_batch_transfer_call` the approved account passes `approval_id` or `approval_ids` with this value to make sure the underlying state of the token(s) hasn't changed from what the approved account expects. + +Keeping with the example above, say the initial approval of the second marketplace generated the following `approved_account_ids` data: + +```json +{ + "approval_owner_id": "alice.near", + "approved_account_ids": { + "marketplace_1.near": { + "approval_id": 1, + "amount": "100", + }, + "marketplace_2.near": 2, + "approval_id": 2, + "amount": "50", + } +} +``` + +But after the transfers and re-approval described above, the token might have `approved_account_ids` as: + +```json +{ + "approval_owner_id": "alice.near", + "approved_account_ids": { + "marketplace_2.near": { + "approval_id": 3, + "amount": "50", + } + } +} +``` + +The marketplace then tries to call `mt_transfer`, passing outdated information: + +```bash +# oops! +near call mt-contract.near mt_transfer '{"account_id": "someacct", "amount":"50", "approval_id": 2 }' +``` + + +### Interface + +The MT contract must implement the following methods: + +```ts +/******************/ +/* CHANGE METHODS */ +/******************/ + +// Add an approved account for a specific set of tokens. +// +// Requirements +// * Caller of the method must attach a deposit of at least 1 yoctoⓃ for +// security purposes +// * Contract MAY require caller to attach larger deposit, to cover cost of +// storing approver data +// * Contract MUST panic if called by someone other than token owner +// * Contract MUST panic if addition would cause `mt_revoke_all` to exceed +// single-block gas limit. See below for more info. +// * Contract MUST increment approval ID even if re-approving an account +// * If successfully approved or if had already been approved, and if `msg` is +// present, contract MUST call `mt_on_approve` on `account_id`. See +// `mt_on_approve` description below for details. +// +// Arguments: +// * `token_ids`: the token ids for which to add an approval +// * `account_id`: the account to add to `approved_account_ids` +// * `amounts`: the number of tokens to approve for transfer, wrapped in quotes and treated +// like an array of string, although the numbers will be stored as an array of +// unsigned integer with 128 bits. + +// * `msg`: optional string to be passed to `mt_on_approve` +// +// Returns void, if no `msg` given. Otherwise, returns promise call to +// `mt_on_approve`, which can resolve with whatever it wants. +function mt_approve( + token_ids: [string], + amounts: [string], + account_id: string, + msg: string|null, +): void|Promise {} + +// Revoke an approved account for a specific token. +// +// Requirements +// * Caller of the method must attach a deposit of 1 yoctoⓃ for security +// purposes +// * If contract requires >1yN deposit on `mt_approve`, contract +// MUST refund associated storage deposit when owner revokes approval +// * Contract MUST panic if called by someone other than token owner +// +// Arguments: +// * `token_ids`: the token for which to revoke approved_account_ids +// * `account_id`: the account to remove from `approvals` +function mt_revoke( + token_ids: [string], + account_id: string +) {} + +// Revoke all approved accounts for a specific token. +// +// Requirements +// * Caller of the method must attach a deposit of 1 yoctoⓃ for security +// purposes +// * If contract requires >1yN deposit on `mt_approve`, contract +// MUST refund all associated storage deposit when owner revokes approved_account_ids +// * Contract MUST panic if called by someone other than token owner +// +// Arguments: +// * `token_ids`: the token ids with approved_account_ids to revoke +function mt_revoke_all(token_ids: [string]) {} + +/****************/ +/* VIEW METHODS */ +/****************/ + +// Check if tokens are approved for transfer by a given account, optionally +// checking an approval_id +// +// Requirements: +// * Contract MUST panic if `approval_ids` is not null and the length of +// `approval_ids` is not equal to `token_ids` +// +// Arguments: +// * `token_ids`: the tokens for which to check an approval +// * `approved_account_id`: the account to check the existence of in `approved_account_ids` +// * `amounts`: specify the positionally corresponding amount for the `token_id` +// that at least must be approved. The number of tokens to approve for transfer, +// wrapped in quotes and treated like an array of string, although the numbers will be +// stored as an array of unsigned integer with 128 bits. +// * `approval_ids`: an optional array of approval IDs to check against +// current approval IDs for given account and `token_ids`. +// +// Returns: +// if `approval_ids` is given, `true` if `approved_account_id` is approved with given `approval_id` +// and has at least the amount specified approved otherwise, `true` if `approved_account_id` +// is in list of approved accounts and has at least the amount specified approved +// finally it returns false for all other states +function mt_is_approved( + token_ids: [string], + approved_account_id: string, + amounts: [string], + approval_ids: number[]|null +): boolean {} + +// Get a the list of approvals for a given token_id and account_id +// +// Arguments: +// * `token_id`: the token for which to check an approval +// * `account_id`: the account to retrieve approvals for +// +// Returns a TokenApproval object, as described in Approval Management standard +function mt_token_approval( + token_id: string, + account_id: string, +): TokenApproval {} + + +// Get a list of all approvals for a given token_id +// +// Arguments: +// * `from_index`: a string representing an unsigned 128-bit integer, +// representing the starting index of tokens to return +// * `limit`: the maximum number of tokens to return +// +// Returns an array of TokenApproval objects, as described in Approval Management standard, and an empty array if there are no approvals +function mt_token_approvals( + token_id: string, + from_index: string|null, // default: "0" + limit: number|null, +): TokenApproval[] {} +``` + +### Why must `mt_approve` panic if `mt_revoke_all` would fail later? + +In the description of `mt_approve` above, it states: + + Contract MUST panic if addition would cause `mt_revoke_all` to exceed + single-block gas limit. + +What does this mean? + +First, it's useful to understand what we mean by "single-block gas limit". This refers to the [hard cap on gas per block at the protocol layer](https://docs.near.org/docs/concepts/gas#thinking-in-gas). This number will increase over time. + +Removing data from a contract uses gas, so if an MT had a large enough number of approvals, `mt_revoke_all` would fail, because calling it would exceed the maximum gas. + +Contracts must prevent this by capping the number of approvals for a given token. However, it is up to contract authors to determine a sensible cap for their contract (and the single block gas limit at the time they deploy). Since contract implementations can vary, some implementations will be able to support a larger number of approvals than others, even with the same maximum gas per block. + +Contract authors may choose to set a cap of something small and safe like 10 approvals, or they could dynamically calculate whether a new approval would break future calls to `mt_revoke_all`. But every contract MUST ensure that they never break the functionality of `mt_revoke_all`. + + +### Approved Account Contract Interface + +If a contract that gets approved to transfer MTs wants to, it can implement `mt_on_approve` to update its own state when granted approval for a token: + +```ts +// Respond to notification that contract has been granted approval for a token. +// +// Notes +// * Contract knows the token contract ID from `predecessor_account_id` +// +// Arguments: +// * `token_ids`: the token_ids to which this contract has been granted approval +// * `amounts`: the ositionally corresponding amount for the token_id +// that at must be approved. The number of tokens to approve for transfer, +// wrapped in quotes and treated like an array of string, although the numbers will be +// stored as an array of unsigned integer with 128 bits. +// * `owner_id`: the owner of the token +// * `approval_ids`: the approval ID stored by NFT contract for this approval. +// Expected to be a number within the 2^53 limit representable by JSON. +// * `msg`: specifies information needed by the approved contract in order to +// handle the approval. Can indicate both a function to call and the +// parameters to pass to that function. +function mt_on_approve( + token_ids: [TokenId], + amounts: [string], + owner_id: string, + approval_ids: [number], + msg: string, +) {} +``` + +Note that the MT contract will fire-and-forget this call, ignoring any return values or errors generated. This means that even if the approved account does not have a contract or does not implement `mt_on_approve`, the approval will still work correctly from the point of view of the MT contract. + +Further note that there is no parallel `mt_on_revoke` when revoking either a single approval or when revoking all. This is partially because scheduling many `mt_on_revoke` calls when revoking all approvals could incur prohibitive [gas fees](https://docs.near.org/docs/concepts/gas). Apps and contracts which cache MT approvals can therefore not rely on having up-to-date information, and should periodically refresh their caches. Since this will be the necessary reality for dealing with `mt_revoke_all`, there is no reason to complicate `mt_revoke` with an `mt_on_revoke` call. + +### No incurred cost for core MT behavior + +MT contracts should be implemented in a way to avoid extra gas fees for serialization & deserialization of `approved_account_ids` for calls to `mt_*` methods other than `mt_tokens`. See `near-contract-standards` [implementation of `ft_metadata` using `LazyOption`](https://github.com/near/near-sdk-rs/blob/c2771af7fdfe01a4e8414046752ee16fb0d29d39/examples/fungible-token/ft/src/lib.rs#L71) as a reference example. \ No newline at end of file diff --git a/specs/Standards/MultiToken/Core.md b/specs/Standards/MultiToken/Core.md new file mode 100644 index 000000000..8a1770d83 --- /dev/null +++ b/specs/Standards/MultiToken/Core.md @@ -0,0 +1,399 @@ +# Multi Token ([NEP-245](https://github.com/near/NEPs/discussions/246)) + +:::caution +This is part of the proposed spec [NEP-245](https://github.com/near/NEPs/blob/master/neps/nep-0245.md) and is subject to change. +::: + +Version `1.0.0` + +## Summary + +A standard interface for a multi token standard that supports fungible, semi-fungible,non-fungible, and tokens of any type, allowing for ownership, transfer, and batch transfer of tokens regardless of specific type. + +## Motivation + + +In the three years since [ERC-1155] was ratified by the Ethereum Community, Multi Token based contracts have proven themselves valuable assets. Many blockchain projects emulate this standard for representing multiple token assets classes in a single contract. The ability to reduce transaction overhead for marketplaces, video games, DAOs, and exchanges is appealing to the blockchain ecosystem and simplifies transactions for developers. + +Having a single contract represent NFTs, FTs, and tokens that sit in-between greatly improves efficiency. The standard also introduced the ability to make batch requests with multiple asset classes reducing complexity. This standard allows operations that currently require _many_ transactions to be completed in a single transaction that can transfer not only NFTs and FTs, but any tokens that are a part of same token contract. + +With this standard, we have sought to take advantage of the ability of the NEAR blockchain to scale. Its sharded runtime, and [storage staking] model that decouples [gas] fees from storage demand, enables ultra low transaction fees and greater on chain storage ( see [Metadata] extension). + +With the aforementioned, it is noteworthy to mention that like the [NFT] standard the Multi Token standard, implements `mt_transfer_call`, +which allows, a user to attach many tokens to a call to a separate contract. Additionally, this standard includes an optional [Approval Management] extension. The extension allows marketplaces to trade on behalf of a user, providing additional flexibility for dApps. + +Prior art: + +- [ERC-721] +- [ERC-1155] +- [NEAR Fungible Token Standard][FT], which first pioneered the "transfer and call" technique +- [NEAR Non-Fungible Token Standard][NFT] +## Rationale + +Why have another standard, aren't fungible and non-fungible tokens enough? The current fungible token and non-fungible token standards, do not provide support for representing many FT tokens in a single contract, as well as the flexibility to define different token types with different behavior in a single contract. This is something that makes it difficult to be interoperable with other major blockchain networks, that implement standards that allow for representation of many different FT tokens in a single contract such as Ethereum. + +The standard here introduces a few concepts that evolve the original [ERC-1155] standard to have more utility, while maintaining the original flexibility of the standard. So keeping that in mind, we are defining this as a new token type. It combines two main features of FT and NFT. It allows us to represent many token types in a single contract, and it's possible to store the amount for each token. + +The decision to not use FT and NFT as explicit token types was taken to allow the community to define their own standards and meanings through metadata. As standards evolve on other networks, this specification allows the standard to be able to represent tokens across networks accurately, without necessarily restricting the behavior to any preset definition. + +The issues with this in general is a problem with defining what metadata means and how is that interpreted. We have chosen to follow the pattern that is currently in use on Ethereum in the [ERC-1155] standard. That pattern relies on people to make extensions or to make signals as to how they want the metadata to be represented for their use case. + +One of the areas that has broad sweeping implications from the [ERC-1155] standard is the lack of direct access to metadata. With Near's sharding we are able to have a [Metadata Extension](Metadata.md) for the standard that exists on chain. So developers and users are not required to use an indexer to understand, how to interact or interpret tokens, via token identifiers that they receive. + +Another extension that we made was to provide an explicit ability for developers and users to group or link together series of NFTs/FTs or any combination of tokens. This provides additional flexiblity that the [ERC-1155] standard only has loose guidelines on. This was chosen to make it easy for consumers to understand the relationship between tokens within the contract. + +To recap, we choose to create this standard, to improve interoperability, developer ease of use, and to extend token representability beyond what was available directly in the FT or NFT standards. We believe this to be another tool in the developer's toolkit. It makes it possible to represent many types of tokens and to enable exchanges of many tokens within a single `transaction`. + +## Reference-level explanation + +**NOTES**: +- All amounts, balances and allowance are limited by `U128` (max value `2**128 - 1`). +- Token standard uses JSON for serialization of arguments and results. +- Amounts in arguments and results are serialized as Base-10 strings, e.g. `"100"`. This is done to avoid JSON limitation of max integer value of `2**53`. +- The contract must track the change in storage when adding to and removing from collections. This is not included in this core multi token standard but instead in the [Storage Standard](../StorageManagement.md). +- To prevent the deployed contract from being modified or deleted, it should not have any access keys on its account. + +### MT Interface + +```ts +// The base structure that will be returned for a token. If contract is using +// extensions such as Approval Management, Enumeration, Metadata, or other +// attributes may be included in this structure. +type Token = { + token_id: string, + owner_id: string | null +} + + +/******************/ +/* CHANGE METHODS */ +/******************/ + +// Simple transfer. Transfer a given `token_id` from current owner to +// `receiver_id`. +// +// Requirements +// * Caller of the method must attach a deposit of 1 yoctoⓃ for security purposes +// * Caller must have greater than or equal to the `amount` being requested +// * Contract MUST panic if called by someone other than token owner or, +// if using Approval Management, one of the approved accounts +// * `approval_id` is for use with Approval Management extension, see +// that document for full explanation. +// * If using Approval Management, contract MUST nullify approved accounts on +// successful transfer. +// +// Arguments: +// * `receiver_id`: the valid NEAR account receiving the token +// * `token_id`: the token to transfer +// * `amount`: the number of tokens to transfer, wrapped in quotes and treated +// like a string, although the number will be stored as an unsigned integer +// with 128 bits. +// * `approval` (optional): is a tuple of [`owner_id`,`approval_id`]. +// `owner_id` is the valid Near account that owns the tokens. +// `approval_id` is the expected approval ID. A number smaller than +// 2^53, and therefore representable as JSON. See Approval Management +// standard for full explanation. +// * `memo` (optional): for use cases that may benefit from indexing or +// providing information for a transfer + + +function mt_transfer( + receiver_id: string, + token_id: string, + amount: string, + approval: [owner_id: string, approval_id: number]|null, + memo: string|null, +) {} + +// Simple batch transfer. Transfer a given `token_ids` from current owner to +// `receiver_id`. +// +// Requirements +// * Caller of the method must attach a deposit of 1 yoctoⓃ for security purposes +// * Caller must have greater than or equal to the `amounts` being requested for the given `token_ids` +// * Contract MUST panic if called by someone other than token owner or, +// if using Approval Management, one of the approved accounts +// * `approval_id` is for use with Approval Management extension, see +// that document for full explanation. +// * If using Approval Management, contract MUST nullify approved accounts on +// successful transfer. +// * Contract MUST panic if called with the length of `token_ids` not equal to `amounts` is not equal +// * Contract MUST panic if `approval_ids` is not `null` and does not equal the length of `token_ids` +// +// Arguments: +// * `receiver_id`: the valid NEAR account receiving the token +// * `token_ids`: the tokens to transfer +// * `amounts`: the number of tokens to transfer, wrapped in quotes and treated +// like an array of strings, although the numbers will be stored as an array of unsigned integer +// with 128 bits. +// * `approvals` (optional): is an array of expected `approval` per `token_ids`. +// If a `token_id` does not have a corresponding `approval` then the entry in the array +// must be marked null. +// `approval` is a tuple of [`owner_id`,`approval_id`]. +// `owner_id` is the valid Near account that owns the tokens. +// `approval_id` is the expected approval ID. A number smaller than +// 2^53, and therefore representable as JSON. See Approval Management +// standard for full explanation. +// * `memo` (optional): for use cases that may benefit from indexing or +// providing information for a transfer + + +function mt_batch_transfer( + receiver_id: string, + token_ids: string[], + amounts: string[], + approvals: ([owner_id: string, approval_id: number]| null)[]| null, + memo: string|null, +) {} + + +// Transfer token and call a method on a receiver contract. A successful +// workflow will end in a success execution outcome to the callback on the MT +// contract at the method `mt_resolve_transfer`. +// +// You can think of this as being similar to attaching native NEAR tokens to a +// function call. It allows you to attach any Multi Token, token in a call to a +// receiver contract. +// +// Requirements: +// * Caller of the method must attach a deposit of 1 yoctoⓃ for security +// purposes +// * Caller must have greater than or equal to the `amount` being requested +// * Contract MUST panic if called by someone other than token owner or, +// if using Approval Management, one of the approved accounts +// * The receiving contract must implement `mt_on_transfer` according to the +// standard. If it does not, MT contract's `mt_resolve_transfer` MUST deal +// with the resulting failed cross-contract call and roll back the transfer. +// * Contract MUST implement the behavior described in `mt_resolve_transfer` +// * `approval_id` is for use with Approval Management extension, see +// that document for full explanation. +// * If using Approval Management, contract MUST nullify approved accounts on +// successful transfer. +// +// Arguments: +// * `receiver_id`: the valid NEAR account receiving the token. +// * `token_id`: the token to send. +// * `amount`: the number of tokens to transfer, wrapped in quotes and treated +// like a string, although the number will be stored as an unsigned integer +// with 128 bits. +// * `owner_id`: the valid NEAR account that owns the token +// * `approval` (optional): is a tuple of [`owner_id`,`approval_id`]. +// `owner_id` is the valid Near account that owns the tokens. +// `approval_id` is the expected approval ID. A number smaller than +// 2^53, and therefore representable as JSON. See Approval Management +// * `memo` (optional): for use cases that may benefit from indexing or +// providing information for a transfer. +// * `msg`: specifies information needed by the receiving contract in +// order to properly handle the transfer. Can indicate both a function to +// call and the parameters to pass to that function. + + +function mt_transfer_call( + receiver_id: string, + token_id: string, + amount: string, + approval: [owner_id: string, approval_id: number]|null, + memo: string|null, + msg: string, +): Promise {} + + + +// Transfer tokens and call a method on a receiver contract. A successful +// workflow will end in a success execution outcome to the callback on the MT +// contract at the method `mt_resolve_transfer`. +// +// You can think of this as being similar to attaching native NEAR tokens to a +// function call. It allows you to attach any Multi Token, token in a call to a +// receiver contract. +// +// Requirements: +// * Caller of the method must attach a deposit of 1 yoctoⓃ for security +// purposes +// * Caller must have greater than or equal to the `amount` being requested +// * Contract MUST panic if called by someone other than token owner or, +// if using Approval Management, one of the approved accounts +// * The receiving contract must implement `mt_on_transfer` according to the +// standard. If it does not, MT contract's `mt_resolve_transfer` MUST deal +// with the resulting failed cross-contract call and roll back the transfer. +// * Contract MUST implement the behavior described in `mt_resolve_transfer` +// * `approval_id` is for use with Approval Management extension, see +// that document for full explanation. +// * If using Approval Management, contract MUST nullify approved accounts on +// successful transfer. +// * Contract MUST panic if called with the length of `token_ids` not equal to `amounts` is not equal +// * Contract MUST panic if `approval_ids` is not `null` and does not equal the length of `token_ids` +// +// Arguments: +// * `receiver_id`: the valid NEAR account receiving the token. +// * `token_ids`: the tokens to transfer +// * `amounts`: the number of tokens to transfer, wrapped in quotes and treated +// like an array of string, although the numbers will be stored as an array of +// unsigned integer with 128 bits. +// * `approvals` (optional): is an array of expected `approval` per `token_ids`. +// If a `token_id` does not have a corresponding `approval` then the entry in the array +// must be marked null. +// `approval` is a tuple of [`owner_id`,`approval_id`]. +// `owner_id` is the valid Near account that owns the tokens. +// `approval_id` is the expected approval ID. A number smaller than +// 2^53, and therefore representable as JSON. See Approval Management +// standard for full explanation. +// * `memo` (optional): for use cases that may benefit from indexing or +// providing information for a transfer. +// * `msg`: specifies information needed by the receiving contract in +// order to properly handle the transfer. Can indicate both a function to +// call and the parameters to pass to that function. + + +function mt_batch_transfer_call( + receiver_id: string, + token_ids: string[], + amounts: string[], + approvals: ([owner_id: string, approval_id: number]|null)[] | null, + memo: string|null, + msg: string, +): Promise {} + +/****************/ +/* VIEW METHODS */ +/****************/ + + +// Returns the tokens with the given `token_ids` or `null` if no such token. +function mt_token(token_ids: string[]) (Token | null)[] + +// Returns the balance of an account for the given `token_id`. +// The balance though wrapped in quotes and treated like a string, +// the number will be stored as an unsigned integer with 128 bits. +// Arguments: +// * `account_id`: the NEAR account that owns the token. +// * `token_id`: the token to retrieve the balance from +function mt_balance_of(account_id: string, token_id: string): string + +// Returns the balances of an account for the given `token_ids`. +// The balances though wrapped in quotes and treated like strings, +// the numbers will be stored as an unsigned integer with 128 bits. +// Arguments: +// * `account_id`: the NEAR account that owns the tokens. +// * `token_ids`: the tokens to retrieve the balance from +function mt_batch_balance_of(account_id: string, token_ids: string[]): string[] + +// Returns the token supply with the given `token_id` or `null` if no such token exists. +// The supply though wrapped in quotes and treated like a string, the number will be stored +// as an unsigned integer with 128 bits. +function mt_supply(token_id: string): string | null + +// Returns the token supplies with the given `token_ids`, a string value is returned or `null` +// if no such token exists. The supplies though wrapped in quotes and treated like strings, +// the numbers will be stored as an unsigned integer with 128 bits. +function mt_batch_supply(token_ids: string[]): (string | null)[] +``` + +The following behavior is required, but contract authors may name this function something other than the conventional `mt_resolve_transfer` used here. + +```ts +// Finalize an `mt_transfer_call` or `mt_batch_transfer_call` chain of cross-contract calls. Generically +// referred to as `mt_transfer_call` as it applies to `mt_batch_transfer_call` as well. +// +// The `mt_transfer_call` process: +// +// 1. Sender calls `mt_transfer_call` on MT contract +// 2. MT contract transfers token from sender to receiver +// 3. MT contract calls `mt_on_transfer` on receiver contract +// 4+. [receiver contract may make other cross-contract calls] +// N. MT contract resolves promise chain with `mt_resolve_transfer`, and may +// transfer token back to sender +// +// Requirements: +// * Contract MUST forbid calls to this function by any account except self +// * If promise chain failed, contract MUST revert token transfer +// * If promise chain resolves with `true`, contract MUST return token to +// `sender_id` +// +// Arguments: +// * `sender_id`: the sender of `mt_transfer_call` +// * `receiver_id`: the `receiver_id` argument given to `mt_transfer_call` +// * `token_ids`: the `token_ids` argument given to `mt_transfer_call` +// * `amounts`: the `token_ids` argument given to `mt_transfer_call` +// * `approvals (optional)`: if using Approval Management, contract MUST provide +// set of original approvals in this argument, and restore the +// approved accounts in case of revert. +// `approvals` is an array of expected `approval_list` per `token_ids`. +// If a `token_id` does not have a corresponding `approvals_list` then the entry in the +// array must be marked null. +// `approvals_list` is an array of triplets of [`owner_id`,`approval_id`,`amount`]. +// `owner_id` is the valid Near account that owns the tokens. +// `approval_id` is the expected approval ID. A number smaller than +// 2^53, and therefore representable as JSON. See Approval Management +// standard for full explanation. +// `amount`: the number of tokens to transfer, wrapped in quotes and treated +// like a string, although the number will be stored as an unsigned integer +// with 128 bits. +// +// +// +// Returns total amount spent by the `receiver_id`, corresponding to the `token_id`. +// The amounts returned, though wrapped in quotes and treated like strings, +// the numbers will be stored as an unsigned integer with 128 bits. +// Example: if sender_id calls `mt_transfer_call({ "amounts": ["100"], token_ids: ["55"], receiver_id: "games" })`, +// but `receiver_id` only uses 80, `mt_on_transfer` will resolve with `["20"]`, and `mt_resolve_transfer` +// will return `["80"]`. + + +function mt_resolve_transfer( + sender_id: string, + receiver_id: string, + token_ids: string[], + approvals: (null | [owner_id: string, approval_id: number, amount: string][]) []| null +):string[] {} +``` + +### Receiver Interface + +Contracts which want to make use of `mt_transfer_call` and `mt_batch_transfer_call` must implement the following: + +```ts +// Take some action after receiving a multi token +// +// Requirements: +// * Contract MUST restrict calls to this function to a set of whitelisted +// contracts +// * Contract MUST panic if `token_ids` length does not equals `amounts` +// length +// * Contract MUST panic if `previous_owner_ids` length does not equals `token_ids` +// length +// +// Arguments: +// * `sender_id`: the sender of `mt_transfer_call` +// * `previous_owner_ids`: the account that owned the tokens prior to it being +// transferred to this contract, which can differ from `sender_id` if using +// Approval Management extension +// * `token_ids`: the `token_ids` argument given to `mt_transfer_call` +// * `amounts`: the `token_ids` argument given to `mt_transfer_call` +// * `msg`: information necessary for this contract to know how to process the +// request. This may include method names and/or arguments. +// +// Returns the number of unused tokens in string form. For instance, if `amounts` +// is `["10"]` but only 9 are needed, it will return `["1"]`. The amounts returned, +// though wrapped in quotes and treated like strings, the numbers will be stored as +// an unsigned integer with 128 bits. + + +function mt_on_transfer( + sender_id: string, + previous_owner_ids: string[], + token_ids: string[], + amounts: string[], + msg: string, +): Promise; +``` + + [ERC-721]: https://eips.ethereum.org/EIPS/eip-721 + [ERC-1155]: https://eips.ethereum.org/EIPS/eip-1155 + [storage staking]: https://docs.near.org/docs/concepts/storage-staking + [gas]: https://docs.near.org/docs/concepts/gas + [Metadata]: Metadata.md + [NFT]: ../NonFungibleToken/Core.md + [Approval Management]: ApprovalManagement.md + [FT]: ../FungibleToken/Core.md + diff --git a/specs/Standards/MultiToken/Enumeration.md b/specs/Standards/MultiToken/Enumeration.md new file mode 100644 index 000000000..7a0b560ba --- /dev/null +++ b/specs/Standards/MultiToken/Enumeration.md @@ -0,0 +1,84 @@ +# Multi Token Enumeration([NEP-245](https://github.com/near/NEPs/discussions/246)) + +:::caution +This is part of the proposed spec [NEP-245](https://github.com/near/NEPs/blob/master/neps/nep-0245.md) and is subject to change. +::: + +Version `1.0.0` + +## Summary + +Standard interfaces for counting & fetching tokens, for an entire Multi Token contract or for a given owner. + +## Motivation + +Apps such as marketplaces and wallets need a way to show all tokens owned by a given account and to show statistics about all tokens for a given contract. This extension provides a standard way to do so. + +While some Multi Token contracts may forego this extension to save [storage] costs, this requires apps to have custom off-chain indexing layers. This makes it harder for apps to integrate with such Multi Token contracts. Apps which integrate only with Multi Token Standards that use the Enumeration extension do not even need a server-side component at all, since they can retrieve all information they need directly from the blockchain. + +Prior art: + +- [ERC-721]'s enumeration extension +- [Non Fungible Token Standard's](../NonFungibleToken/Enumeration.md) enumeration extension + +## Interface + +The contract must implement the following view methods: + +// Metadata field is optional if metadata extension is implemented. Includes the base token metadata id and the token_metadata object, that represents the token specific metadata. + +```ts +// Get a list of all tokens +// +// Arguments: +// * `from_index`: a string representing an unsigned 128-bit integer, +// representing the starting index of tokens to return +// * `limit`: the maximum number of tokens to return +// +// Returns an array of `Token` objects, as described in the Core standard, +// and an empty array if there are no tokens +function mt_tokens( + from_index: string|null, // default: "0" + limit: number|null, // default: unlimited (could fail due to gas limit) +): Token[] {} + +// Get list of all tokens owned by a given account +// +// Arguments: +// * `account_id`: a valid NEAR account +// * `from_index`: a string representing an unsigned 128-bit integer, +// representing the starting index of tokens to return +// * `limit`: the maximum number of tokens to return +// +// Returns a paginated list of all tokens owned by this account, and an empty array if there are no tokens +function mt_tokens_for_owner( + account_id: string, + from_index: string|null, // default: 0 + limit: number|null, // default: unlimited (could fail due to gas limit) +): Token[] {} +``` + +The contract must implement the following view methods if using metadata extension: + +```ts +// Get list of all base metadata for the contract +// +// Arguments: +// * `from_index`: a string representing an unsigned 128-bit integer, +// representing the starting index of tokens to return +// * `limit`: the maximum number of tokens to return +// +// Returns an array of `MTBaseTokenMetadata` objects, as described in the Metadata standard, and an empty array if there are no tokens +function mt_tokens_base_metadata_all( + from_index: string | null, + limit: number | null + ): MTBaseTokenMetadata[] +``` + + +## Notes + +At the time of this writing, the specialized collections in the `near-sdk` Rust crate are iterable, but not all of them have implemented an `iter_from` solution. There may be efficiency gains for large collections and contract developers are encouraged to test their data structures with a large amount of entries. + + [ERC-721]: https://eips.ethereum.org/EIPS/eip-721 + [storage]: https://docs.near.org/docs/concepts/storage-staking diff --git a/specs/Standards/MultiToken/Events.md b/specs/Standards/MultiToken/Events.md new file mode 100644 index 000000000..3076b5b85 --- /dev/null +++ b/specs/Standards/MultiToken/Events.md @@ -0,0 +1,187 @@ +# Multi Token Event([NEP-245](https://github.com/near/NEPs/discussions/246)) + +:::caution +This is part of the proposed spec [NEP-245](https://github.com/near/NEPs/blob/master/neps/nep-0245.md) and is subject to change. +::: + +Version `1.0.0` + +## Summary + +Standard interfaces for Multi Token Contract actions. +Extension of [NEP-297](../EventsFormat.md) + +## Motivation + +NEAR and third-party applications need to track + `mint`, `burn`, `transfer` events for all MT-driven apps consistently. This exension addresses that. + +Note that applications, including NEAR Wallet, could require implementing additional methods to display tokens correctly such as [`mt_metadata`](Metadata.md) and [`mt_tokens_for_owner`](Enumeration.md). + +## Interface +Multi Token Events MUST have `standard` set to `"nep245"`, standard version set to `"1.0.0"`, `event` value is one of `mt_mint`, `mt_burn`, `mt_transfer`, and `data` must be of one of the following relavant types: `MtMintLog[] | MtBurnLog[] | MtTransferLog[]`: + + + +```ts +interface MtEventLogData { + EVENT_JSON: { + standard: "nep245", + version: "1.0.0", + event: MtEvent, + data: MtMintLog[] | MtBurnLog[] | MtTransferLog[] + } +} +``` + +```ts +// Minting event log. Emitted when a token is minted/created. +// Requirements +// * Contract MUST emit event when minting a token +// Fields +// * Contract token_ids and amounts MUST be the same length +// * `owner_id`: the account receiving the minted token +// * `token_ids`: the tokens minted +// * `amounts`: the number of tokens minted, wrapped in quotes and treated +// like a string, although the numbers will be stored as an unsigned integer +// array with 128 bits. +// * `memo`: optional message +interface MtMintLog { + owner_id: string, + token_ids: string[], + amounts: string[], + memo?: string +} + +// Burning event log. Emitted when a token is burned. +// Requirements +// * Contract MUST emit event when minting a token +// Fields +// * Contract token_ids and amounts MUST be the same length +// * `owner_id`: the account whose token(s) are being burned +// * `authorized_id`: approved account_id to burn, if applicable +// * `token_ids`: the tokens being burned +// * `amounts`: the number of tokens burned, wrapped in quotes and treated +// like a string, although the numbers will be stored as an unsigned integer +// array with 128 bits. +// * `memo`: optional message +interface MtBurnLog { + owner_id: string, + authorized_id?: string, + token_ids: string[], + amounts: string[], + memo?: string +} + +// Transfer event log. Emitted when a token is transferred. +// Requirements +// * Contract MUST emit event when transferring a token +// Fields +// * `authorized_id`: approved account_id to transfer +// * `old_owner_id`: the account sending the tokens "sender.near" +// * `new_owner_id`: the account receiving the tokens "receiver.near" +// * `token_ids`: the tokens to transfer +// * `amounts`: the number of tokens to transfer, wrapped in quotes and treated +// like a string, although the numbers will be stored as an unsigned integer +// array with 128 bits. +interface MtTransferLog { + authorized_id?: string, + old_owner_id: string, + new_owner_id: string, + token_ids: string[], + amounts: string[], + memo?: string +} +``` + +## Examples + +Single owner minting (pretty-formatted for readability purposes): + +```js +EVENT_JSON:{ + "standard": "nep245", + "version": "1.0.0", + "event": "mt_mint", + "data": [ + {"owner_id": "foundation.near", "token_ids": ["aurora", "proximitylabs_ft"], "amounts":["1", "100"]} + ] +} +``` + +Different owners minting: + +```js +EVENT_JSON:{ + "standard": "nep245", + "version": "1.0.0", + "event": "mt_mint", + "data": [ + {"owner_id": "foundation.near", "token_ids": ["aurora", "proximitylabs_ft"], "amounts":["1","100"]}, + {"owner_id": "user1.near", "token_ids": ["meme"], "amounts": ["1"]} + ] +} +``` + +Different events (separate log entries): + +```js +EVENT_JSON:{ + "standard": "nep245", + "version": "1.0.0", + "event": "mt_burn", + "data": [ + {"owner_id": "foundation.near", "token_ids": ["aurora", "proximitylabs_ft"], "amounts": ["1","100"]}, + ] +} +``` + +Authorized id: + +```js +EVENT_JSON:{ + "standard": "nep245", + "version": "1.0.0", + "event": "mt_burn", + "data": [ + {"owner_id": "foundation.near", "token_ids": ["aurora_alpha", "proximitylabs_ft"], "amounts": ["1","100"], "authorized_id": "thirdparty.near" }, + ] +} +``` + +```js +EVENT_JSON:{ + "standard": "nep245", + "version": "1.0.0", + "event": "mt_transfer", + "data": [ + {"old_owner_id": "user1.near", "new_owner_id": "user2.near", "token_ids": ["meme"], "amounts":["1"], "memo": "have fun!"} + ] +} + +EVENT_JSON:{ + "standard": "nep245", + "version": "1.0.0", + "event": "mt_transfer", + "data": [ + {"old_owner_id": "user2.near", "new_owner_id": "user3.near", "token_ids": ["meme"], "amounts":["1"], "authorized_id": "thirdparty.near", "memo": "have fun!"} + ] +} +``` + +## Further methods + +Note that the example events covered above cover two different kinds of events: +1. Events that are not specified in the MT Standard (`mt_mint`, `mt_burn`) +2. An event that is covered in the [Multi Token Core Standard](https://nomicon.io/Standards/MultiToken/Core.html#mt-interface). (`mt_transfer`) + +This event standard also applies beyond the three events highlighted here, where future events follow the same convention of as the second type. For instance, if an MT contract uses the [approval management standard](https://nomicon.io/Standards/MultiToken/ApprovalManagement.html), it may emit an event for `mt_approve` if that's deemed as important by the developer community. + +Please feel free to open pull requests for extending the events standard detailed here as needs arise. + +## Drawbacks + +There is a known limitation of 16kb strings when capturing logs. +This can be observed from `token_ids` that may vary in length +for different apps so the amount of logs that can +be executed may vary. diff --git a/specs/Standards/MultiToken/Metadata.md b/specs/Standards/MultiToken/Metadata.md new file mode 100644 index 000000000..09b6237ea --- /dev/null +++ b/specs/Standards/MultiToken/Metadata.md @@ -0,0 +1,144 @@ +# Multi Token Metadata([NEP-245](https://github.com/near/NEPs/discussions/246)) + +:::caution +This is part of the proposed spec [NEP-245](https://github.com/near/NEPs/blob/master/neps/nep-0245.md) and is subject to change. +::: + +Version `1.0.0` + +## Summary + +An interface for a multi token's metadata. The goal is to keep the metadata future-proof as well as lightweight. This will be important to dApps needing additional information about multi token properties, and broadly compatible with other token standards such that the [NEAR Rainbow Bridge](https://near.org/blog/eth-near-rainbow-bridge/) can move tokens between chains. + +## Motivation + +The primary value of tokens comes from their metadata. While the [core standard](Core.md) provides the minimum interface that can be considered a multi token, most artists, developers, and dApps will want to associate more data with each token, and will want a predictable way to interact with any MT's metadata. + +NEAR's unique [storage staking](https://docs.near.org/docs/concepts/storage-staking) approach makes it feasible to store more data on-chain than other blockchains. This standard leverages this strength for common metadata attributes, and provides a standard way to link to additional offchain data to support rapid community experimentation. + +This standard also provides a `spec` version. This makes it easy for consumers of Multi Tokens, such as marketplaces, to know if they support all the features of a given token. + +Prior art: + +- NEAR's [Fungible Token Metadata Standard](../FungibleToken/Metadata.md) +- NEAR's [Non-Fungible Token Metadata Standard](../NonFungibleToken/Metadata.md) +- Discussion about NEAR's complete NFT standard: #171 +- Discussion about NEAR's complete Multi Token standard: #245 + +## Interface + +Metadata applies at both the class level (`MTBaseTokenMetadata`) and the specific instance level (`MTTokenMetadata`). The relevant metadata for each: + +```ts + +type MTContractMetadata = { + spec: string, // required, essentially a version like "mt-1.0.0" + name: string, // required Zoink's Digitial Sword Collection +} + +type MTBaseTokenMetadata = { + name: string, // required, ex. "Silver Swords" or "Metaverse 3" + id: string, // required a unique identifier for the metadata + symbol: string|null, // required, ex. "MOCHI" + icon: string|null, // Data URL + decimals: string|null // number of decimals for the token useful for FT related tokens + base_uri: string|null, // Centralized gateway known to have reliable access to decentralized storage assets referenced by `reference` or `media` URLs + reference: string|null, // URL to a JSON file with more info + copies: number|null, // number of copies of this set of metadata in existence when token was minted. + reference_hash: string|null, // Base64-encoded sha256 hash of JSON from reference field. Required if `reference` is included. +} + +type MTTokenMetadata = { + title: string|null, // ex. "Arch Nemesis: Mail Carrier" or "Parcel #5055" + description: string|null, // free-form description + media: string|null, // URL to associated media, preferably to decentralized, content-addressed storage + media_hash: string|null, // Base64-encoded sha256 hash of content referenced by the `media` field. Required if `media` is included. + issued_at: string|null, // When token was issued or minted, Unix epoch in milliseconds + expires_at: string|null, // When token expires, Unix epoch in milliseconds + starts_at: string|null, // When token starts being valid, Unix epoch in milliseconds + updated_at: string|null, // When token was last updated, Unix epoch in milliseconds + extra: string|null, // Anything extra the MT wants to store on-chain. Can be stringified JSON. + reference: string|null, // URL to an off-chain JSON file with more info. + reference_hash: string|null // Base64-encoded sha256 hash of JSON from reference field. Required if `reference` is included. +} + +type MTTokenMetadataAll = { + base: MTBaseTokenMetadata + token: MTTokenMetadata +} +``` + +A new set of functions MUST be supported on the MT contract: + +```ts +// Returns the top-level contract level metadtata +function mt_metadata_contract(): MTContractMetadata {} +function mt_metadata_token_all(token_ids: string[]): MTTokenMetadataAll[] +function mt_metadata_token_by_token_id(token_ids: string[]): MTTokenMetadata[] +function mt_metadata_base_by_token_id(token_ids: string[]): MTBaseTokenMetadata[] +function mt_metadata_base_by_metadata_id(base_metadata_ids: string[]): MTBaseTokenMetadata[] + +``` + +A new attribute MUST be added to each `Token` struct: + +```diff + type Token = { + token_id: string, ++ token_metadata?: MTTokenMetadata, ++ base_metadata_id: string, + } +``` + +### An implementing contract MUST include the following fields on-chain +For `MTContractMetadata`: +- `spec`: a string that MUST be formatted `mt-1.0.0` to indicate that a Multi Token contract adheres to the current versions of this Metadata spec. This will allow consumers of the Multi Token to know if they support the features of a given contract. +- `name`: the human-readable name of the contract. + +### An implementing contract must include the following fields on-chain +For `MTBaseTokenMetadata`: +- `name`: the human-readable name of the Token. +- `base_uri`: Centralized gateway known to have reliable access to decentralized storage assets referenced by `reference` or `media` URLs. Can be used by other frontends for initial retrieval of assets, even if these frontends then replicate the data to their own decentralized nodes, which they are encouraged to do. + +### An implementing contract MAY include the following fields on-chain +For `MTBaseTokenMetadata`: +- `symbol`: the abbreviated symbol of the contract, like MOCHI or MV3 +- `icon`: a small image associated with this contract. Encouraged to be a [data URL](https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/Data_URIs), to help consumers display it quickly while protecting user data. Recommendation: use [optimized SVG](https://codepen.io/tigt/post/optimizing-svgs-in-data-uris), which can result in high-resolution images with only 100s of bytes of [storage cost](https://docs.near.org/docs/concepts/storage-staking). (Note that these storage costs are incurred to the contract deployer, but that querying these icons is a very cheap & cacheable read operation for all consumers of the contract and the RPC nodes that serve the data.) Recommendation: create icons that will work well with both light-mode and dark-mode websites by either using middle-tone color schemes, or by [embedding `media` queries in the SVG](https://timkadlec.com/2013/04/media-queries-within-svg/). +- `reference`: a link to a valid JSON file containing various keys offering supplementary details on the token. Example: "/ipfs/QmdmQXB2mzChmMeKY47C43LxUdg1NDJ5MWcKMKxDu7RgQm", "https://example.com/token.json", etc. If the information given in this document conflicts with the on-chain attributes, the values in `reference` shall be considered the source of truth. +- `reference_hash`: the base64-encoded sha256 hash of the JSON file contained in the `reference` field. This is to guard against off-chain tampering. +- `copies`: The number of tokens with this set of metadata or `media` known to exist at time of minting. Supply is a more accurate current reflection. + +For `MTTokenMetadata`: + +- `title`: The title of this specific token. +- `description`: A longer description of the token. +- `media`: URL to associated media. Preferably to decentralized, content-addressed storage. +- `media_hash`: the base64-encoded sha256 hash of content referenced by the `media` field. This is to guard against off-chain tampering. +- `copies`: The number of tokens with this set of metadata or `media` known to exist at time of minting. +- `issued_at`: Unix epoch in milliseconds when token was issued or minted (an unsigned 32-bit integer would suffice until the year 2106) +- `expires_at`: Unix epoch in milliseconds when token expires +- `starts_at`: Unix epoch in milliseconds when token starts being valid +- `updated_at`: Unix epoch in milliseconds when token was last updated +- `extra`: anything extra the MT wants to store on-chain. Can be stringified JSON. +- `reference`: URL to an off-chain JSON file with more info. +- `reference_hash`: Base64-encoded sha256 hash of JSON from reference field. Required if `reference` is included. + +For `MTTokenMetadataAll `: + +- `base`: The base metadata that corresponds to `MTBaseTokenMetadata` for the token. +- `token`: The token specific metadata that corresponds to `MTTokenMetadata`. + +### No incurred cost for core MT behavior + +Contracts should be implemented in a way to avoid extra gas fees for serialization & deserialization of metadata for calls to `mt_*` methods other than `mt_metadata*` or `mt_tokens`. See `near-contract-standards` [implementation using `LazyOption`](https://github.com/near/near-sdk-rs/blob/c2771af7fdfe01a4e8414046752ee16fb0d29d39/examples/fungible-token/ft/src/lib.rs#L71) as a reference example. + +## Drawbacks + +* When this MT contract is created and initialized, the storage use per-token will be higher than an MT Core version. Frontends can account for this by adding extra deposit when minting. This could be done by padding with a reasonable amount, or by the frontend using the [RPC call detailed here](https://docs.near.org/docs/develop/front-end/rpc#genesis-config) that gets genesis configuration and actually determine precisely how much deposit is needed. +* Convention of `icon` being a data URL rather than a link to an HTTP endpoint that could contain privacy-violating code cannot be done on deploy or update of contract metadata, and must be done on the consumer/app side when displaying token data. +* If on-chain icon uses a data URL or is not set but the document given by `reference` contains a privacy-violating `icon` URL, consumers & apps of this data should not naïvely display the `reference` version, but should prefer the safe version. This is technically a violation of the "`reference` setting wins" policy described above. + +## Future possibilities + +- Detailed conventions that may be enforced for versions. +- A fleshed out schema for what the `reference` object should contain. diff --git a/specs/Standards/MultiToken/README.md b/specs/Standards/MultiToken/README.md new file mode 100644 index 000000000..a593d3907 --- /dev/null +++ b/specs/Standards/MultiToken/README.md @@ -0,0 +1,7 @@ +## Multi Token Standard + +- [Multi Token Core](Core.md) +- [Multi Token Metadata](Metadata.md) +- [Multi Token Approval Management](ApprovalManagement.md) +- [Multi Token Enumeration](Enumeration.md) +- [Multi Token Events](Events.md) From 0b229290cb6099971d77864d4d113d9c75c81f70 Mon Sep 17 00:00:00 2001 From: Jay Logelin Date: Mon, 4 Apr 2022 09:19:38 -0300 Subject: [PATCH 029/150] Update nep-245 status to Review --- neps/nep-0245.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/neps/nep-0245.md b/neps/nep-0245.md index a9247bd3b..a92df5aa8 100644 --- a/neps/nep-0245.md +++ b/neps/nep-0245.md @@ -3,7 +3,7 @@ NEP: 245 Title: Multi Token Standard Author: Zane Starr , @riqi, @jriemann, @marcos.sun DiscussionsTo: https://github.com/near/NEPs/discussions/246 -Status: Draft +Status: Review Type: Standards Track Category: Contract Created: 03-Mar-2022 @@ -580,4 +580,4 @@ Copyright and related rights waived via [CC0](https://creativecommons.org/public [Metadata]: ../specs/Standards/MultiToken/Metadata.md [NFT]: ../specs/Standards/NonFungibleToken/Core.md [Approval Management]: ../specs/Standards/MultiToken/ApprovalManagement.md - [FT]: ../specs/Standards/FungibleToken/Core.md \ No newline at end of file + [FT]: ../specs/Standards/FungibleToken/Core.md From cdca855b70f70db0088d71995ef1ce83a96077a1 Mon Sep 17 00:00:00 2001 From: Jay Logelin Date: Mon, 4 Apr 2022 09:19:57 -0300 Subject: [PATCH 030/150] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 256041cc5..081109a2d 100644 --- a/README.md +++ b/README.md @@ -23,7 +23,7 @@ Changes to the protocol specification and standards are called NEAR Enhancement |[0178](https://github.com/near/NEPs/blob/master/neps/nep-0178.md) | Non Fungible Token Approval Management | @chadoh @thor314 | Final | |[0181](https://github.com/near/NEPs/blob/master/neps/nep-0181.md) | Non Fungible Token Enumeration | @chadoh @thor314 | Final | |[0199](https://github.com/near/NEPs/blob/master/neps/nep-0199.md) | Non Fungible Token Royalties and Payouts | @thor314 @mattlockyer | Final | -|[0245](https://github.com/near/NEPs/blob/master/neps/nep-0245.md) | Multi Token Standard | @zcstarr @riqi @jriemann @marcos.sun | Draft | +|[0245](https://github.com/near/NEPs/blob/master/neps/nep-0245.md) | Multi Token Standard | @zcstarr @riqi @jriemann @marcos.sun | Review | |[0297](https://github.com/near/NEPs/blob/master/neps/nep-0297.md) | Contract Events Standard | @telezhnaya | Final | |[0330](https://github.com/near/NEPs/blob/master/neps/nep-0330.md) | Contract Metadata | @BenKurrek | Review | From f7741689f259ee847421d75a43de3d6eb603eba3 Mon Sep 17 00:00:00 2001 From: Jay Logelin Date: Mon, 4 Apr 2022 17:56:09 -0300 Subject: [PATCH 031/150] Renamed NEP-330 contract source metadata Renamed NEP-330 contract source metadata to avoid confusion with generic contract metadata. --- neps/nep-0330.md | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/neps/nep-0330.md b/neps/nep-0330.md index 34c305e15..6d0bf5678 100644 --- a/neps/nep-0330.md +++ b/neps/nep-0330.md @@ -1,6 +1,6 @@ --- NEP: 330 -Title: Contract Metadata +Title: Contract Source Metadata Author: Ben Kurrek DiscussionsTo: https://github.com/near/NEPs/discussions/329 Status: Review @@ -11,7 +11,7 @@ Created: 27-Feb-2022 ## Summary -The contract metadata is a standard interface that allows auditing and viewing source code for a deployed smart contract. Implementation of this standard is purely optional but is recommended for developers whose contracts are open source. +The contract source metadata is a standard interface that allows auditing and viewing source code for a deployed smart contract. Implementation of this standard is purely optional but is recommended for developers whose contracts are open source. ## Motivation @@ -32,7 +32,7 @@ The metadata will include two optional fields: - `link`: a string that references the link to the open-source code. This can be anything such as Github or a CID to somewhere on IPFS. ```ts -type ContractMetadata = { +type ContractSourceMetadata = { version: string|null, // optional, commit hash being used for the currently deployed wasm. If the contract is not open-sourced, this could also be a numbering system for internal organization / tracking such as "1.0.0" and "2.1.0". link: string|null, //optional, link to open source code such as a Github repository or a CID to somewhere on IPFS. } @@ -41,7 +41,7 @@ type ContractMetadata = { In order to view this information, contracts must include a getter which will return the struct. ```ts -function contract_metadata(): ContractMetadata {} +function contract_source_metadata(): ContractSourceMetadata {} ``` ## Reference Implementation @@ -49,7 +49,7 @@ function contract_metadata(): ContractMetadata {} As an example, say there was an NFT contract deployed on-chain which was currently using the commit hash `39f2d2646f2f60e18ab53337501370dc02a5661c` and had its open source code located at `https://github.com/near-examples/nft-tutorial`. This contract would then include a struct which has the following fields: ```ts -type ContractMetadata = { +type ContractSourceMetadata = { version: "39f2d2646f2f60e18ab53337501370dc02a5661c" link: "https://github.com/near-examples/nft-tutorial" } @@ -70,25 +70,25 @@ An example implementation can be seen below. /// Simple Implementation #[near_bindgen] pub struct Contract { - pub contract_metadata: ContractMetadata + pub contract_metadata: ContractSourceMetadata } /// Contract metadata structure -pub struct ContractMetadata { +pub struct ContractSourceMetadata { pub version: String, pub link: String, } /// Minimum Viable Interface -pub trait ContractMetadataTrait { - fn contract_metadata(&self) -> ContractMetadata; +pub trait ContractSourceMetadataTrait { + fn contract_source_metadata(&self) -> ContractMetadata; } /// Implementation of the view function #[near_bindgen] -impl ContractMetadataTrait for Contract { - fn contract_metadata(&self) -> ContractMetadata { - self.contract_metadata.get().unwrap() +impl ContractSourceMetadataTrait for Contract { + fn contract_source_metadata(&self) -> ContractSourceMetadata { + self.contract_source_metadata.get().unwrap() } } ``` From 110053e997226c4649e4f268c2fb19390663079c Mon Sep 17 00:00:00 2001 From: Jay Logelin Date: Mon, 4 Apr 2022 17:56:32 -0300 Subject: [PATCH 032/150] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 081109a2d..185918639 100644 --- a/README.md +++ b/README.md @@ -25,7 +25,7 @@ Changes to the protocol specification and standards are called NEAR Enhancement |[0199](https://github.com/near/NEPs/blob/master/neps/nep-0199.md) | Non Fungible Token Royalties and Payouts | @thor314 @mattlockyer | Final | |[0245](https://github.com/near/NEPs/blob/master/neps/nep-0245.md) | Multi Token Standard | @zcstarr @riqi @jriemann @marcos.sun | Review | |[0297](https://github.com/near/NEPs/blob/master/neps/nep-0297.md) | Contract Events Standard | @telezhnaya | Final | -|[0330](https://github.com/near/NEPs/blob/master/neps/nep-0330.md) | Contract Metadata | @BenKurrek | Review | +|[0330](https://github.com/near/NEPs/blob/master/neps/nep-0330.md) | Contract Source Metadata | @BenKurrek | Review | From 49f3b207569e5fcdf1abd3f8720ed5597d8362e5 Mon Sep 17 00:00:00 2001 From: Jay Logelin Date: Mon, 4 Apr 2022 18:03:24 -0300 Subject: [PATCH 033/150] Renamed NEP-330 Standard to Source Metadata --- README.md | 4 +-- neps/nep-0330.md | 2 +- specs/Standards/Appendix/README.md | 15 +++++++++++ specs/Standards/Appendix/_category_.json | 5 ++++ ...{ContractMetadata.md => SourceMetadata.md} | 26 +++++++++---------- 5 files changed, 36 insertions(+), 16 deletions(-) create mode 100644 specs/Standards/Appendix/README.md create mode 100644 specs/Standards/Appendix/_category_.json rename specs/Standards/{ContractMetadata.md => SourceMetadata.md} (77%) diff --git a/README.md b/README.md index 185918639..59f645d19 100644 --- a/README.md +++ b/README.md @@ -24,8 +24,8 @@ Changes to the protocol specification and standards are called NEAR Enhancement |[0181](https://github.com/near/NEPs/blob/master/neps/nep-0181.md) | Non Fungible Token Enumeration | @chadoh @thor314 | Final | |[0199](https://github.com/near/NEPs/blob/master/neps/nep-0199.md) | Non Fungible Token Royalties and Payouts | @thor314 @mattlockyer | Final | |[0245](https://github.com/near/NEPs/blob/master/neps/nep-0245.md) | Multi Token Standard | @zcstarr @riqi @jriemann @marcos.sun | Review | -|[0297](https://github.com/near/NEPs/blob/master/neps/nep-0297.md) | Contract Events Standard | @telezhnaya | Final | -|[0330](https://github.com/near/NEPs/blob/master/neps/nep-0330.md) | Contract Source Metadata | @BenKurrek | Review | +|[0297](https://github.com/near/NEPs/blob/master/neps/nep-0297.md) | Events Standard | @telezhnaya | Final | +|[0330](https://github.com/near/NEPs/blob/master/neps/nep-0330.md) | Source Metadata | @BenKurrek | Review | diff --git a/neps/nep-0330.md b/neps/nep-0330.md index 6d0bf5678..ed8840a26 100644 --- a/neps/nep-0330.md +++ b/neps/nep-0330.md @@ -1,6 +1,6 @@ --- NEP: 330 -Title: Contract Source Metadata +Title: Source Metadata Author: Ben Kurrek DiscussionsTo: https://github.com/near/NEPs/discussions/329 Status: Review diff --git a/specs/Standards/Appendix/README.md b/specs/Standards/Appendix/README.md new file mode 100644 index 000000000..1183d404d --- /dev/null +++ b/specs/Standards/Appendix/README.md @@ -0,0 +1,15 @@ +# Appendix + +|NEP # | Title | Author | Status | +|---|---|---|---| +|[0001](https://github.com/near/NEPs/blob/master/neps/nep-0001.md) | FIP Purpose and Guidelines | @jlogelin | Active | +|[0021](https://github.com/near/NEPs/blob/master/neps/nep-0021.md) | Fungible Token Standard (Deprecated) | @aevgenykuzyakov | Final | +|[0141](https://github.com/near/NEPs/blob/master/neps/nep-0141.md) | Fungible Token Standard | @aevgenykuzyakov @oysterpack | Final | +|[0145](https://github.com/near/NEPs/blob/master/neps/nep-0145.md) | Storage Management | @aevgenykuzyakov | Final | +|[0148](https://github.com/near/NEPs/blob/master/neps/nep-0148.md) | Fungible Token Metadata | @robert-zaremba @aevgenykuzyakov @oysterpack | Final | +|[0171](https://github.com/near/NEPs/blob/master/neps/nep-0171.md) | Non Fungible Token Standard | @mikedotexe @aevgenykuzyakov @oysterpack | Final | +|[0177](https://github.com/near/NEPs/blob/master/neps/nep-0177.md) | Non Fungible Token Metadata | @chadoh @mikedotexe | Final | +|[0178](https://github.com/near/NEPs/blob/master/neps/nep-0178.md) | Non Fungible Token Approval Management | @chadoh @thor314 | Final | +|[0181](https://github.com/near/NEPs/blob/master/neps/nep-0181.md) | Non Fungible Token Enumeration | @chadoh @thor314 | Final | +|[0199](https://github.com/near/NEPs/blob/master/neps/nep-0199.md) | Non Fungible Token Royalties and Payouts | @thor314 @mattlockyer | Final | +|[0297](https://github.com/near/NEPs/blob/master/neps/nep-0297.md) | Non Fungible Token Royalties and Payouts | @telezhnaya | Final | diff --git a/specs/Standards/Appendix/_category_.json b/specs/Standards/Appendix/_category_.json new file mode 100644 index 000000000..ce989280e --- /dev/null +++ b/specs/Standards/Appendix/_category_.json @@ -0,0 +1,5 @@ +{ + "label": "Appendix", + "collapsible": true, + "collapsed": true, +} \ No newline at end of file diff --git a/specs/Standards/ContractMetadata.md b/specs/Standards/SourceMetadata.md similarity index 77% rename from specs/Standards/ContractMetadata.md rename to specs/Standards/SourceMetadata.md index 6411b30b6..8da02aec7 100644 --- a/specs/Standards/ContractMetadata.md +++ b/specs/Standards/SourceMetadata.md @@ -1,4 +1,4 @@ -# Contract Metadata +# Source Metadata ## [NEP-330](https://github.com/near/NEPs/blob/master/neps/nep-0330.md) @@ -10,7 +10,7 @@ Version `1.0.0` ## Summary -The contract metadata is a standard interface that allows auditing and viewing source code for a deployed smart contract. Implementation of this standard is purely optional but is recommended for developers whose contracts are open source. +The contract source metadata is a standard interface that allows auditing and viewing source code for a deployed smart contract. Implementation of this standard is purely optional but is recommended for developers whose contracts are open source. ## Motivation @@ -24,14 +24,14 @@ There is a lot of information that can be held about a contract. Ultimately, we ## Specification -Successful implementations of this standard will introduce a new (`ContractMetadata`) struct that will hold all the necessary information to be queried for. This struct will be kept on the contract level. +Successful implementations of this standard will introduce a new (`ContractSourceMetadata`) struct that will hold all the necessary information to be queried for. This struct will be kept on the contract level. The metadata will include two optional fields: - `version`: a string that references the specific commit hash or version of the code that is currently deployed on-chain. This can be included regardless of whether or not the contract is open-sourced and can also be used for organizational purposes. - `link`: a string that references the link to the open-source code. This can be anything such as Github or a CID to somewhere on IPFS. ```ts -type ContractMetadata = { +type ContractSourceMetadata = { version: string|null, // optional, commit hash being used for the currently deployed wasm. If the contract is not open-sourced, this could also be a numbering system for internal organization / tracking such as "1.0.0" and "2.1.0". link: string|null, //optional, link to open source code such as a Github repository or a CID to somewhere on IPFS. } @@ -40,7 +40,7 @@ type ContractMetadata = { In order to view this information, contracts must include a getter which will return the struct. ```ts -function contract_metadata(): ContractMetadata {} +function contract_source_metadata(): ContractSourceMetadata {} ``` ## Reference Implementation @@ -48,7 +48,7 @@ function contract_metadata(): ContractMetadata {} As an example, say there was an NFT contract deployed on-chain which was currently using the commit hash `39f2d2646f2f60e18ab53337501370dc02a5661c` and had its open source code located at `https://github.com/near-examples/nft-tutorial`. This contract would then include a struct which has the following fields: ```ts -type ContractMetadata = { +type ContractSourceMetadata = { version: "39f2d2646f2f60e18ab53337501370dc02a5661c" link: "https://github.com/near-examples/nft-tutorial" } @@ -69,25 +69,25 @@ An example implementation can be seen below. /// Simple Implementation #[near_bindgen] pub struct Contract { - pub contract_metadata: ContractMetadata + pub contract_metadata: ContractSourceMetadata } /// Contract metadata structure -pub struct ContractMetadata { +pub struct ContractSourceMetadata { pub version: String, pub link: String, } /// Minimum Viable Interface -pub trait ContractMetadataTrait { - fn contract_metadata(&self) -> ContractMetadata; +pub trait ContractSourceMetadataTrait { + fn contract_source_metadata(&self) -> ContractSourceMetadata; } /// Implementation of the view function #[near_bindgen] -impl ContractMetadataTrait for Contract { - fn contract_metadata(&self) -> ContractMetadata { - self.contract_metadata.get().unwrap() +impl ContractSourceMetadataTrait for Contract { + fn contract_source_metadata(&self) -> ContractSourceMetadata { + self.contract_source_metadata.get().unwrap() } } ``` From 6b077ea271e57d319b9be140d60f2de01dd34e1d Mon Sep 17 00:00:00 2001 From: Jay Logelin Date: Wed, 6 Apr 2022 10:05:28 -0300 Subject: [PATCH 034/150] Presentation cleanup --- specs/Standards/{ => Tokens}/FungibleToken/Core.md | 0 specs/Standards/{ => Tokens}/FungibleToken/Event.md | 0 specs/Standards/{ => Tokens}/FungibleToken/Metadata.md | 0 specs/Standards/{ => Tokens}/FungibleToken/README.md | 0 specs/Standards/{ => Tokens}/FungibleToken/_category_.json | 0 specs/Standards/{ => Tokens}/MultiToken/ApprovalManagement.md | 2 +- specs/Standards/{ => Tokens}/MultiToken/Core.md | 2 +- specs/Standards/{ => Tokens}/MultiToken/Enumeration.md | 2 +- specs/Standards/{ => Tokens}/MultiToken/Events.md | 2 +- specs/Standards/{ => Tokens}/MultiToken/Metadata.md | 2 +- specs/Standards/{ => Tokens}/MultiToken/README.md | 0 .../{ => Tokens}/NonFungibleToken/ApprovalManagement.md | 0 specs/Standards/{ => Tokens}/NonFungibleToken/Core.md | 0 specs/Standards/{ => Tokens}/NonFungibleToken/Enumeration.md | 0 specs/Standards/{ => Tokens}/NonFungibleToken/Event.md | 0 specs/Standards/{ => Tokens}/NonFungibleToken/Metadata.md | 0 specs/Standards/{ => Tokens}/NonFungibleToken/Payout.md | 0 specs/Standards/{ => Tokens}/NonFungibleToken/README.md | 0 specs/Standards/{ => Tokens}/NonFungibleToken/_category_.json | 0 19 files changed, 5 insertions(+), 5 deletions(-) rename specs/Standards/{ => Tokens}/FungibleToken/Core.md (100%) rename specs/Standards/{ => Tokens}/FungibleToken/Event.md (100%) rename specs/Standards/{ => Tokens}/FungibleToken/Metadata.md (100%) rename specs/Standards/{ => Tokens}/FungibleToken/README.md (100%) rename specs/Standards/{ => Tokens}/FungibleToken/_category_.json (100%) rename specs/Standards/{ => Tokens}/MultiToken/ApprovalManagement.md (99%) rename specs/Standards/{ => Tokens}/MultiToken/Core.md (99%) rename specs/Standards/{ => Tokens}/MultiToken/Enumeration.md (97%) rename specs/Standards/{ => Tokens}/MultiToken/Events.md (98%) rename specs/Standards/{ => Tokens}/MultiToken/Metadata.md (99%) rename specs/Standards/{ => Tokens}/MultiToken/README.md (100%) rename specs/Standards/{ => Tokens}/NonFungibleToken/ApprovalManagement.md (100%) rename specs/Standards/{ => Tokens}/NonFungibleToken/Core.md (100%) rename specs/Standards/{ => Tokens}/NonFungibleToken/Enumeration.md (100%) rename specs/Standards/{ => Tokens}/NonFungibleToken/Event.md (100%) rename specs/Standards/{ => Tokens}/NonFungibleToken/Metadata.md (100%) rename specs/Standards/{ => Tokens}/NonFungibleToken/Payout.md (100%) rename specs/Standards/{ => Tokens}/NonFungibleToken/README.md (100%) rename specs/Standards/{ => Tokens}/NonFungibleToken/_category_.json (100%) diff --git a/specs/Standards/FungibleToken/Core.md b/specs/Standards/Tokens/FungibleToken/Core.md similarity index 100% rename from specs/Standards/FungibleToken/Core.md rename to specs/Standards/Tokens/FungibleToken/Core.md diff --git a/specs/Standards/FungibleToken/Event.md b/specs/Standards/Tokens/FungibleToken/Event.md similarity index 100% rename from specs/Standards/FungibleToken/Event.md rename to specs/Standards/Tokens/FungibleToken/Event.md diff --git a/specs/Standards/FungibleToken/Metadata.md b/specs/Standards/Tokens/FungibleToken/Metadata.md similarity index 100% rename from specs/Standards/FungibleToken/Metadata.md rename to specs/Standards/Tokens/FungibleToken/Metadata.md diff --git a/specs/Standards/FungibleToken/README.md b/specs/Standards/Tokens/FungibleToken/README.md similarity index 100% rename from specs/Standards/FungibleToken/README.md rename to specs/Standards/Tokens/FungibleToken/README.md diff --git a/specs/Standards/FungibleToken/_category_.json b/specs/Standards/Tokens/FungibleToken/_category_.json similarity index 100% rename from specs/Standards/FungibleToken/_category_.json rename to specs/Standards/Tokens/FungibleToken/_category_.json diff --git a/specs/Standards/MultiToken/ApprovalManagement.md b/specs/Standards/Tokens/MultiToken/ApprovalManagement.md similarity index 99% rename from specs/Standards/MultiToken/ApprovalManagement.md rename to specs/Standards/Tokens/MultiToken/ApprovalManagement.md index 11420f76e..0efda50a5 100644 --- a/specs/Standards/MultiToken/ApprovalManagement.md +++ b/specs/Standards/Tokens/MultiToken/ApprovalManagement.md @@ -1,4 +1,4 @@ -# Multi Token Standard Approval Management([NEP-245](https://github.com/near/NEPs/discussions/246)) +# Multi Token Standard Approval Management :::caution This is part of the proposed spec [NEP-245](https://github.com/near/NEPs/blob/master/neps/nep-0245.md) and is subject to change. diff --git a/specs/Standards/MultiToken/Core.md b/specs/Standards/Tokens/MultiToken/Core.md similarity index 99% rename from specs/Standards/MultiToken/Core.md rename to specs/Standards/Tokens/MultiToken/Core.md index 8a1770d83..539f32902 100644 --- a/specs/Standards/MultiToken/Core.md +++ b/specs/Standards/Tokens/MultiToken/Core.md @@ -1,4 +1,4 @@ -# Multi Token ([NEP-245](https://github.com/near/NEPs/discussions/246)) +# Multi Token :::caution This is part of the proposed spec [NEP-245](https://github.com/near/NEPs/blob/master/neps/nep-0245.md) and is subject to change. diff --git a/specs/Standards/MultiToken/Enumeration.md b/specs/Standards/Tokens/MultiToken/Enumeration.md similarity index 97% rename from specs/Standards/MultiToken/Enumeration.md rename to specs/Standards/Tokens/MultiToken/Enumeration.md index 7a0b560ba..3ad56a843 100644 --- a/specs/Standards/MultiToken/Enumeration.md +++ b/specs/Standards/Tokens/MultiToken/Enumeration.md @@ -1,4 +1,4 @@ -# Multi Token Enumeration([NEP-245](https://github.com/near/NEPs/discussions/246)) +# Multi Token Enumeration :::caution This is part of the proposed spec [NEP-245](https://github.com/near/NEPs/blob/master/neps/nep-0245.md) and is subject to change. diff --git a/specs/Standards/MultiToken/Events.md b/specs/Standards/Tokens/MultiToken/Events.md similarity index 98% rename from specs/Standards/MultiToken/Events.md rename to specs/Standards/Tokens/MultiToken/Events.md index 3076b5b85..34ef691d8 100644 --- a/specs/Standards/MultiToken/Events.md +++ b/specs/Standards/Tokens/MultiToken/Events.md @@ -1,4 +1,4 @@ -# Multi Token Event([NEP-245](https://github.com/near/NEPs/discussions/246)) +# Multi Token Event :::caution This is part of the proposed spec [NEP-245](https://github.com/near/NEPs/blob/master/neps/nep-0245.md) and is subject to change. diff --git a/specs/Standards/MultiToken/Metadata.md b/specs/Standards/Tokens/MultiToken/Metadata.md similarity index 99% rename from specs/Standards/MultiToken/Metadata.md rename to specs/Standards/Tokens/MultiToken/Metadata.md index 09b6237ea..713a02e0e 100644 --- a/specs/Standards/MultiToken/Metadata.md +++ b/specs/Standards/Tokens/MultiToken/Metadata.md @@ -1,4 +1,4 @@ -# Multi Token Metadata([NEP-245](https://github.com/near/NEPs/discussions/246)) +# Multi Token Metadata :::caution This is part of the proposed spec [NEP-245](https://github.com/near/NEPs/blob/master/neps/nep-0245.md) and is subject to change. diff --git a/specs/Standards/MultiToken/README.md b/specs/Standards/Tokens/MultiToken/README.md similarity index 100% rename from specs/Standards/MultiToken/README.md rename to specs/Standards/Tokens/MultiToken/README.md diff --git a/specs/Standards/NonFungibleToken/ApprovalManagement.md b/specs/Standards/Tokens/NonFungibleToken/ApprovalManagement.md similarity index 100% rename from specs/Standards/NonFungibleToken/ApprovalManagement.md rename to specs/Standards/Tokens/NonFungibleToken/ApprovalManagement.md diff --git a/specs/Standards/NonFungibleToken/Core.md b/specs/Standards/Tokens/NonFungibleToken/Core.md similarity index 100% rename from specs/Standards/NonFungibleToken/Core.md rename to specs/Standards/Tokens/NonFungibleToken/Core.md diff --git a/specs/Standards/NonFungibleToken/Enumeration.md b/specs/Standards/Tokens/NonFungibleToken/Enumeration.md similarity index 100% rename from specs/Standards/NonFungibleToken/Enumeration.md rename to specs/Standards/Tokens/NonFungibleToken/Enumeration.md diff --git a/specs/Standards/NonFungibleToken/Event.md b/specs/Standards/Tokens/NonFungibleToken/Event.md similarity index 100% rename from specs/Standards/NonFungibleToken/Event.md rename to specs/Standards/Tokens/NonFungibleToken/Event.md diff --git a/specs/Standards/NonFungibleToken/Metadata.md b/specs/Standards/Tokens/NonFungibleToken/Metadata.md similarity index 100% rename from specs/Standards/NonFungibleToken/Metadata.md rename to specs/Standards/Tokens/NonFungibleToken/Metadata.md diff --git a/specs/Standards/NonFungibleToken/Payout.md b/specs/Standards/Tokens/NonFungibleToken/Payout.md similarity index 100% rename from specs/Standards/NonFungibleToken/Payout.md rename to specs/Standards/Tokens/NonFungibleToken/Payout.md diff --git a/specs/Standards/NonFungibleToken/README.md b/specs/Standards/Tokens/NonFungibleToken/README.md similarity index 100% rename from specs/Standards/NonFungibleToken/README.md rename to specs/Standards/Tokens/NonFungibleToken/README.md diff --git a/specs/Standards/NonFungibleToken/_category_.json b/specs/Standards/Tokens/NonFungibleToken/_category_.json similarity index 100% rename from specs/Standards/NonFungibleToken/_category_.json rename to specs/Standards/Tokens/NonFungibleToken/_category_.json From 6f3ae3969a1f822a27af05e43af20b068ff3c965 Mon Sep 17 00:00:00 2001 From: Jay Logelin Date: Wed, 6 Apr 2022 10:47:49 -0300 Subject: [PATCH 035/150] fixed broken links --- specs/Standards/README.md | 22 +++++++++---------- specs/Standards/StorageManagement.md | 4 ++-- specs/Standards/Tokens/FungibleToken/Core.md | 6 ++--- specs/Standards/Tokens/FungibleToken/Event.md | 2 +- .../Tokens/MultiToken/ApprovalManagement.md | 2 +- specs/Standards/Tokens/MultiToken/Core.md | 2 +- specs/Standards/Tokens/MultiToken/Events.md | 2 +- .../NonFungibleToken/ApprovalManagement.md | 2 +- .../Standards/Tokens/NonFungibleToken/Core.md | 2 +- .../Tokens/NonFungibleToken/Event.md | 2 +- 10 files changed, 23 insertions(+), 23 deletions(-) diff --git a/specs/Standards/README.md b/specs/Standards/README.md index cb3083bd2..b7edfc09f 100644 --- a/specs/Standards/README.md +++ b/specs/Standards/README.md @@ -7,16 +7,16 @@ import {useCurrentSidebarCategory} from '@docusaurus/theme-common'; ## Table of Contents -- [Fungible Token](FungibleToken/README.md) - - [Core Standard](FungibleToken/Core.md) - - [Metadata](FungibleToken/Metadata.md) - - [Events](FungibleToken/Event.md) -- [Non-Fungible Token](NonFungibleToken/README.md) - - [Core Standard](NonFungibleToken/Core.md) - - [Metadata](NonFungibleToken/Metadata.md) - - [Approval Management](NonFungibleToken/ApprovalManagement.md) - - [Enumeration](NonFungibleToken/Enumeration.md) - - [Royalty Payout](NonFungibleToken/Payout.md) - - [Events](NonFungibleToken/Event.md) +- [Fungible Token](Tokens/FungibleToken/README.md) + - [Core Standard](Tokens/FungibleToken/Core.md) + - [Metadata](Tokens/FungibleToken/Metadata.md) + - [Events](Tokens/FungibleToken/Event.md) +- [Non-Fungible Token](Tokens/NonFungibleToken/README.md) + - [Core Standard](Tokens/NonFungibleToken/Core.md) + - [Metadata](Tokens/NonFungibleToken/Metadata.md) + - [Approval Management](Tokens/NonFungibleToken/ApprovalManagement.md) + - [Enumeration](Tokens/NonFungibleToken/Enumeration.md) + - [Royalty Payout](Tokens/NonFungibleToken/Payout.md) + - [Events](Tokens/NonFungibleToken/Event.md) - [Storage Management](StorageManagement.md) - [Events Format](EventsFormat.md) diff --git a/specs/Standards/StorageManagement.md b/specs/Standards/StorageManagement.md index 5a506ba5d..466934489 100644 --- a/specs/Standards/StorageManagement.md +++ b/specs/Standards/StorageManagement.md @@ -36,7 +36,7 @@ To show the flexibility and power of this standard, let's walk through two examp ### Example 1: Fungible Token Contract -Imagine a [fungible token](FungibleToken/Core.md) contract deployed at `ft`. Let's say this contract saves all user balances to a Map data structure internally, and adding a key for a new user requires 0.00235Ⓝ. This contract therefore uses the Storage Management standard to pass this cost onto users, so that a new user must effectively pay a registration fee to interact with this contract of 0.00235Ⓝ, or 2350000000000000000000 yoctoⓃ ([yocto](https://www.metricconversion.us/prefixes.htm) = 10-24). +Imagine a [fungible token](Tokens/FungibleToken/Core.md) contract deployed at `ft`. Let's say this contract saves all user balances to a Map data structure internally, and adding a key for a new user requires 0.00235Ⓝ. This contract therefore uses the Storage Management standard to pass this cost onto users, so that a new user must effectively pay a registration fee to interact with this contract of 0.00235Ⓝ, or 2350000000000000000000 yoctoⓃ ([yocto](https://www.metricconversion.us/prefixes.htm) = 10-24). For this contract, `storage_balance_bounds` will be: @@ -170,7 +170,7 @@ Bob wants to close his account, but has a non-zero balance of `ft` tokens. It fails with a message like "Cannot gracefully close account with positive remaining balance; bob has balance N" -2. Bob transfers his tokens to a friend using `ft_transfer` from the [Fungible Token Core](FungibleToken/Core.md) standard. +2. Bob transfers his tokens to a friend using `ft_transfer` from the [Fungible Token Core](Tokens/FungibleToken/Core.md) standard. 3. Bob tries the call from Step 1 again. It works. diff --git a/specs/Standards/Tokens/FungibleToken/Core.md b/specs/Standards/Tokens/FungibleToken/Core.md index ccfcf08c8..440236398 100644 --- a/specs/Standards/Tokens/FungibleToken/Core.md +++ b/specs/Standards/Tokens/FungibleToken/Core.md @@ -6,7 +6,7 @@ Version `1.0.0` ## Summary -A standard interface for fungible tokens that allows for a normal transfer as well as a transfer and method call in a single transaction. The [storage standard](../StorageManagement.md) addresses the needs (and security) of storage staking. +A standard interface for fungible tokens that allows for a normal transfer as well as a transfer and method call in a single transaction. The [storage standard](../../StorageManagement.md) addresses the needs (and security) of storage staking. The [fungible token metadata standard](Metadata.md) provides the fields needed for ergonomics across dApps and marketplaces. ## Motivation @@ -52,7 +52,7 @@ There are a few concepts in the scenarios above: Note that precision (the number of decimal places supported by a given token) is not part of this core standard, since it's not required to perform actions. The minimum value is always 1 token. See the [Fungible Token Metadata Standard](Metadata.md) to learn how to support precision/decimals in a standardized way. -Given that multiple users will use a Fungible Token contract, and their activity will result in an increased [storage staking](https://docs.near.org/docs/concepts/storage-staking) burden for the contract's account, this standard is designed to interoperate nicely with [the Account Storage standard](../StorageManagement.md) for storage deposits and refunds. +Given that multiple users will use a Fungible Token contract, and their activity will result in an increased [storage staking](https://docs.near.org/docs/concepts/storage-staking) burden for the contract's account, this standard is designed to interoperate nicely with [the Account Storage standard](../../StorageManagement.md) for storage deposits and refunds. ### Example scenarios @@ -177,7 +177,7 @@ Altogether then, Alice may take two steps, though the first may be a background - All amounts, balances and allowance are limited by `U128` (max value `2**128 - 1`). - Token standard uses JSON for serialization of arguments and results. - Amounts in arguments and results have are serialized as Base-10 strings, e.g. `"100"`. This is done to avoid JSON limitation of max integer value of `2**53`. -- The contract must track the change in storage when adding to and removing from collections. This is not included in this core fungible token standard but instead in the [Storage Standard](../StorageManagement.md). +- The contract must track the change in storage when adding to and removing from collections. This is not included in this core fungible token standard but instead in the [Storage Standard](../../StorageManagement.md). - To prevent the deployed contract from being modified or deleted, it should not have any access keys on its account. **Interface**: diff --git a/specs/Standards/Tokens/FungibleToken/Event.md b/specs/Standards/Tokens/FungibleToken/Event.md index 36970fae8..c6e2fc398 100644 --- a/specs/Standards/Tokens/FungibleToken/Event.md +++ b/specs/Standards/Tokens/FungibleToken/Event.md @@ -5,7 +5,7 @@ Version `1.0.0` ## Summary Standard interfaces for FT contract actions. -Extension of [NEP-297](../EventsFormat.md) +Extension of [NEP-297](../../EventsFormat.md) ## Motivation diff --git a/specs/Standards/Tokens/MultiToken/ApprovalManagement.md b/specs/Standards/Tokens/MultiToken/ApprovalManagement.md index 0efda50a5..8a24ed713 100644 --- a/specs/Standards/Tokens/MultiToken/ApprovalManagement.md +++ b/specs/Standards/Tokens/MultiToken/ApprovalManagement.md @@ -36,7 +36,7 @@ Let's consider some examples. Our cast of characters & apps: * Market: a contract with account `market` which sells tokens from `mt` as well as other token contracts * Bazaar: similar to Market, but implemented differently (spoiler alert: has no `mt_on_approve` function!), has account `bazaar` -Alice and Bob are already [registered](../StorageManagement.md) with MT, Market, and Bazaar, and Alice owns a token on the MT contract with ID=`"1"` and a fungible style token with ID =`"2"` and AMOUNT =`"100"`. +Alice and Bob are already [registered](../../StorageManagement.md) with MT, Market, and Bazaar, and Alice owns a token on the MT contract with ID=`"1"` and a fungible style token with ID =`"2"` and AMOUNT =`"100"`. Let's examine the technical calls through the following scenarios: diff --git a/specs/Standards/Tokens/MultiToken/Core.md b/specs/Standards/Tokens/MultiToken/Core.md index 539f32902..c737133f0 100644 --- a/specs/Standards/Tokens/MultiToken/Core.md +++ b/specs/Standards/Tokens/MultiToken/Core.md @@ -50,7 +50,7 @@ To recap, we choose to create this standard, to improve interoperability, develo - All amounts, balances and allowance are limited by `U128` (max value `2**128 - 1`). - Token standard uses JSON for serialization of arguments and results. - Amounts in arguments and results are serialized as Base-10 strings, e.g. `"100"`. This is done to avoid JSON limitation of max integer value of `2**53`. -- The contract must track the change in storage when adding to and removing from collections. This is not included in this core multi token standard but instead in the [Storage Standard](../StorageManagement.md). +- The contract must track the change in storage when adding to and removing from collections. This is not included in this core multi token standard but instead in the [Storage Standard](../../StorageManagement.md). - To prevent the deployed contract from being modified or deleted, it should not have any access keys on its account. ### MT Interface diff --git a/specs/Standards/Tokens/MultiToken/Events.md b/specs/Standards/Tokens/MultiToken/Events.md index 34ef691d8..69f3fbef8 100644 --- a/specs/Standards/Tokens/MultiToken/Events.md +++ b/specs/Standards/Tokens/MultiToken/Events.md @@ -9,7 +9,7 @@ Version `1.0.0` ## Summary Standard interfaces for Multi Token Contract actions. -Extension of [NEP-297](../EventsFormat.md) +Extension of [NEP-297](../../EventsFormat.md) ## Motivation diff --git a/specs/Standards/Tokens/NonFungibleToken/ApprovalManagement.md b/specs/Standards/Tokens/NonFungibleToken/ApprovalManagement.md index bdd2cecb6..5067f12e4 100644 --- a/specs/Standards/Tokens/NonFungibleToken/ApprovalManagement.md +++ b/specs/Standards/Tokens/NonFungibleToken/ApprovalManagement.md @@ -33,7 +33,7 @@ Let's consider some examples. Our cast of characters & apps: * Market: a contract with account `market` which sells tokens from `nft` as well as other NFT contracts * Bazaar: similar to Market, but implemented differently (spoiler alert: has no `nft_on_approve` function!), has account `bazaar` -Alice and Bob are already [registered](../StorageManagement.md) with NFT, Market, and Bazaar, and Alice owns a token on the NFT contract with ID=`"1"`. +Alice and Bob are already [registered](../../StorageManagement.md) with NFT, Market, and Bazaar, and Alice owns a token on the NFT contract with ID=`"1"`. Let's examine the technical calls through the following scenarios: diff --git a/specs/Standards/Tokens/NonFungibleToken/Core.md b/specs/Standards/Tokens/NonFungibleToken/Core.md index 605345d34..f16aead6e 100644 --- a/specs/Standards/Tokens/NonFungibleToken/Core.md +++ b/specs/Standards/Tokens/NonFungibleToken/Core.md @@ -37,7 +37,7 @@ Prior art: - All amounts, balances and allowance are limited by `U128` (max value `2**128 - 1`). - Token standard uses JSON for serialization of arguments and results. - Amounts in arguments and results are serialized as Base-10 strings, e.g. `"100"`. This is done to avoid JSON limitation of max integer value of `2**53`. -- The contract must track the change in storage when adding to and removing from collections. This is not included in this core fungible token standard but instead in the [Storage Standard](../StorageManagement.md). +- The contract must track the change in storage when adding to and removing from collections. This is not included in this core fungible token standard but instead in the [Storage Standard](../../StorageManagement.md). - To prevent the deployed contract from being modified or deleted, it should not have any access keys on its account. ### NFT Interface diff --git a/specs/Standards/Tokens/NonFungibleToken/Event.md b/specs/Standards/Tokens/NonFungibleToken/Event.md index b472ada2c..f4bd968f3 100644 --- a/specs/Standards/Tokens/NonFungibleToken/Event.md +++ b/specs/Standards/Tokens/NonFungibleToken/Event.md @@ -5,7 +5,7 @@ Version `1.0.0` ## Summary Standard interface for NFT contract actions. -Extension of [NEP-297](../EventsFormat.md) +Extension of [NEP-297](../../EventsFormat.md) ## Motivation From c40f87d7262802ad493187649c3a77a836a15077 Mon Sep 17 00:00:00 2001 From: Jay Logelin Date: Wed, 6 Apr 2022 11:02:15 -0300 Subject: [PATCH 036/150] Fix broken links --- specs/Standards/Tokens/NonFungibleToken/Payout.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/specs/Standards/Tokens/NonFungibleToken/Payout.md b/specs/Standards/Tokens/NonFungibleToken/Payout.md index f7012de2b..225599159 100644 --- a/specs/Standards/Tokens/NonFungibleToken/Payout.md +++ b/specs/Standards/Tokens/NonFungibleToken/Payout.md @@ -5,7 +5,7 @@ Version `2.0.0`. This standard assumes the NFT contract has implemented -[NEP-171](https://github.com/near/NEPs/blob/master/specs/Standards/NonFungibleToken/Core.md) (Core) and [NEP-178](https://github.com/near/NEPs/blob/master/specs/Standards/NonFungibleToken/ApprovalManagement.md) (Approval Management). +[NEP-171](https://github.com/near/NEPs/blob/master/specs/Standards/Tokens/NonFungibleToken/Core.md) (Core) and [NEP-178](https://github.com/near/NEPs/blob/master/specs/Standards/Tokens/NonFungibleToken/ApprovalManagement.md) (Approval Management). ## Summary An interface allowing non-fungible token contracts to request that financial contracts pay-out multiple receivers, enabling flexible royalty implementations. @@ -107,4 +107,4 @@ In the future, the NFT contract itself may be able to place an NFT transfer is a ## Errata -Version `2.0.0` contains the intended `approval_id` of `u64` instead of the stringified `U64` version. This was an oversight, but since the standard was live for a few months before noticing, the team thought it best to bump the major version. \ No newline at end of file +Version `2.0.0` contains the intended `approval_id` of `u64` instead of the stringified `U64` version. This was an oversight, but since the standard was live for a few months before noticing, the team thought it best to bump the major version. From 6b1b2a690c154aa1cc7f402bd7ae32b8d60e17ea Mon Sep 17 00:00:00 2001 From: Jay Logelin Date: Thu, 7 Apr 2022 09:14:06 -0300 Subject: [PATCH 037/150] Add files via upload --- neps/assets/nep-0001/NEP-flow.png | Bin 0 -> 36695 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 neps/assets/nep-0001/NEP-flow.png diff --git a/neps/assets/nep-0001/NEP-flow.png b/neps/assets/nep-0001/NEP-flow.png new file mode 100644 index 0000000000000000000000000000000000000000..cf2ce0eeef4b6119dfbd339be01dacf73f9be390 GIT binary patch literal 36695 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 Date: Thu, 7 Apr 2022 09:14:57 -0300 Subject: [PATCH 038/150] Update nep-0001.md --- neps/nep-0001.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/neps/nep-0001.md b/neps/nep-0001.md index e966d17e2..05cd1baff 100644 --- a/neps/nep-0001.md +++ b/neps/nep-0001.md @@ -165,7 +165,7 @@ Standards track NEP's are no longer modified after they have reached the Final s The following is the standardization process for all NEPs in all tracks: -![NEP Status Diagram](assets/nep-0001/NEP-states.png) +![NEP Status Flow Diagram](assets/nep-0001/NEP-flow.png) **Idea** - An idea that is pre-draft. This is not tracked within the NEP Repository. From baa59a50bab75152873596c430020ac3730b7f8d Mon Sep 17 00:00:00 2001 From: Jay Logelin Date: Fri, 8 Apr 2022 06:53:27 -0300 Subject: [PATCH 039/150] Fixed broken links --- specs/Standards/Tokens/MultiToken/Events.md | 4 ++-- specs/Standards/Tokens/MultiToken/Metadata.md | 2 +- specs/Standards/Tokens/NonFungibleToken/ApprovalManagement.md | 2 +- specs/Standards/Tokens/NonFungibleToken/Event.md | 4 ++-- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/specs/Standards/Tokens/MultiToken/Events.md b/specs/Standards/Tokens/MultiToken/Events.md index 69f3fbef8..9554ec07a 100644 --- a/specs/Standards/Tokens/MultiToken/Events.md +++ b/specs/Standards/Tokens/MultiToken/Events.md @@ -173,9 +173,9 @@ EVENT_JSON:{ Note that the example events covered above cover two different kinds of events: 1. Events that are not specified in the MT Standard (`mt_mint`, `mt_burn`) -2. An event that is covered in the [Multi Token Core Standard](https://nomicon.io/Standards/MultiToken/Core.html#mt-interface). (`mt_transfer`) +2. An event that is covered in the [Multi Token Core Standard](Core.md). (`mt_transfer`) -This event standard also applies beyond the three events highlighted here, where future events follow the same convention of as the second type. For instance, if an MT contract uses the [approval management standard](https://nomicon.io/Standards/MultiToken/ApprovalManagement.html), it may emit an event for `mt_approve` if that's deemed as important by the developer community. +This event standard also applies beyond the three events highlighted here, where future events follow the same convention of as the second type. For instance, if an MT contract uses the [approval management standard](ApprovalManagement.md), it may emit an event for `mt_approve` if that's deemed as important by the developer community. Please feel free to open pull requests for extending the events standard detailed here as needs arise. diff --git a/specs/Standards/Tokens/MultiToken/Metadata.md b/specs/Standards/Tokens/MultiToken/Metadata.md index 713a02e0e..7c2a640de 100644 --- a/specs/Standards/Tokens/MultiToken/Metadata.md +++ b/specs/Standards/Tokens/MultiToken/Metadata.md @@ -104,7 +104,7 @@ For `MTBaseTokenMetadata`: For `MTBaseTokenMetadata`: - `symbol`: the abbreviated symbol of the contract, like MOCHI or MV3 - `icon`: a small image associated with this contract. Encouraged to be a [data URL](https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/Data_URIs), to help consumers display it quickly while protecting user data. Recommendation: use [optimized SVG](https://codepen.io/tigt/post/optimizing-svgs-in-data-uris), which can result in high-resolution images with only 100s of bytes of [storage cost](https://docs.near.org/docs/concepts/storage-staking). (Note that these storage costs are incurred to the contract deployer, but that querying these icons is a very cheap & cacheable read operation for all consumers of the contract and the RPC nodes that serve the data.) Recommendation: create icons that will work well with both light-mode and dark-mode websites by either using middle-tone color schemes, or by [embedding `media` queries in the SVG](https://timkadlec.com/2013/04/media-queries-within-svg/). -- `reference`: a link to a valid JSON file containing various keys offering supplementary details on the token. Example: "/ipfs/QmdmQXB2mzChmMeKY47C43LxUdg1NDJ5MWcKMKxDu7RgQm", "https://example.com/token.json", etc. If the information given in this document conflicts with the on-chain attributes, the values in `reference` shall be considered the source of truth. +- `reference`: a link to a valid JSON file containing various keys offering supplementary details on the token. Example: "/ipfs/QmdmQXB2mzChmMeKY47C43LxUdg1NDJ5MWcKMKxDu7RgQm", etc. If the information given in this document conflicts with the on-chain attributes, the values in `reference` shall be considered the source of truth. - `reference_hash`: the base64-encoded sha256 hash of the JSON file contained in the `reference` field. This is to guard against off-chain tampering. - `copies`: The number of tokens with this set of metadata or `media` known to exist at time of minting. Supply is a more accurate current reflection. diff --git a/specs/Standards/Tokens/NonFungibleToken/ApprovalManagement.md b/specs/Standards/Tokens/NonFungibleToken/ApprovalManagement.md index 5067f12e4..2288cbc73 100644 --- a/specs/Standards/Tokens/NonFungibleToken/ApprovalManagement.md +++ b/specs/Standards/Tokens/NonFungibleToken/ApprovalManagement.md @@ -293,7 +293,7 @@ This is a unique number given to each approval that allows well-intentioned mark 4. The original owner approves the token for the second marketplace again to list at a new price. But for some reason the second marketplace still lists the token at the previous price and is unaware of the transfers happening. 5. The second marketplace, operating from old information, attempts to again sell the token at the old price. -Note that while this describes an honest mistake, the possibility of such a bug can also be taken advantage of by malicious parties via [front-running](https://defi.cx/front-running-ethereum/). +Note that while this describes an honest mistake, the possibility of such a bug can also be taken advantage of by malicious parties via [front-running](https://users.encs.concordia.ca/~clark/papers/2019_wtsc_front.pdf). To avoid this possibility, the NFT contract generates a unique approval ID each time it approves an account. Then when calling `nft_transfer` or `nft_transfer_call`, the approved account passes `approval_id` with this value to make sure the underlying state of the token hasn't changed from what the approved account expects. diff --git a/specs/Standards/Tokens/NonFungibleToken/Event.md b/specs/Standards/Tokens/NonFungibleToken/Event.md index f4bd968f3..b9a50d3a7 100644 --- a/specs/Standards/Tokens/NonFungibleToken/Event.md +++ b/specs/Standards/Tokens/NonFungibleToken/Event.md @@ -138,8 +138,8 @@ EVENT_JSON:{ Note that the example events covered above cover two different kinds of events: 1. Events that are not specified in the NFT Standard (`nft_mint`, `nft_burn`) -2. An event that is covered in the [NFT Core Standard](https://nomicon.io/Standards/NonFungibleToken/Core.html#nft-interface). (`nft_transfer`) +2. An event that is covered in the [NFT Core Standard](Core.md). (`nft_transfer`) -This event standard also applies beyond the three events highlighted here, where future events follow the same convention of as the second type. For instance, if an NFT contract uses the [approval management standard](https://nomicon.io/Standards/NonFungibleToken/ApprovalManagement.html), it may emit an event for `nft_approve` if that's deemed as important by the developer community. +This event standard also applies beyond the three events highlighted here, where future events follow the same convention of as the second type. For instance, if an NFT contract uses the [approval management standard](ApprovalManagement.md), it may emit an event for `nft_approve` if that's deemed as important by the developer community. Please feel free to open pull requests for extending the events standard detailed here as needs arise. From f7b9f22b8666cf9fae6ecc4922b8c19f4858be6a Mon Sep 17 00:00:00 2001 From: Jay Logelin Date: Fri, 8 Apr 2022 06:57:54 -0300 Subject: [PATCH 040/150] Fixed broken links --- neps/nep-0178.md | 2 +- specs/Standards/Tokens/MultiToken/ApprovalManagement.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/neps/nep-0178.md b/neps/nep-0178.md index cde0ea2c6..9e9eea805 100644 --- a/neps/nep-0178.md +++ b/neps/nep-0178.md @@ -277,7 +277,7 @@ This is a unique number given to each approval that allows well-intentioned mark 4. The original owner approves the token for the second marketplace again to list at a new price. But for some reason the second marketplace still lists the token at the previous price and is unaware of the transfers happening. 5. The second marketplace, operating from old information, attempts to again sell the token at the old price. -Note that while this describes an honest mistake, the possibility of such a bug can also be taken advantage of by malicious parties via [front-running](https://defi.cx/front-running-ethereum/). +Note that while this describes an honest mistake, the possibility of such a bug can also be taken advantage of by malicious parties via [front-running](https://users.encs.concordia.ca/~clark/papers/2019_wtsc_front.pdf). To avoid this possibility, the NFT contract generates a unique approval ID each time it approves an account. Then when calling `nft_transfer` or `nft_transfer_call`, the approved account passes `approval_id` with this value to make sure the underlying state of the token hasn't changed from what the approved account expects. diff --git a/specs/Standards/Tokens/MultiToken/ApprovalManagement.md b/specs/Standards/Tokens/MultiToken/ApprovalManagement.md index 8a24ed713..5c503db01 100644 --- a/specs/Standards/Tokens/MultiToken/ApprovalManagement.md +++ b/specs/Standards/Tokens/MultiToken/ApprovalManagement.md @@ -269,7 +269,7 @@ This is a unique number given to each approval that allows well-intentioned mark 4. The original owner approves the token for the second marketplace again to list at a new price. But for some reason the second marketplace still lists the token at the previous price and is unaware of the transfers happening. 5. The second marketplace, operating from old information, attempts to again sell the token at the old price. -Note that while this describes an honest mistake, the possibility of such a bug can also be taken advantage of by malicious parties via [front-running](https://defi.cx/front-running-ethereum/). +Note that while this describes an honest mistake, the possibility of such a bug can also be taken advantage of by malicious parties via [front-running](https://users.encs.concordia.ca/~clark/papers/2019_wtsc_front.pdf). To avoid this possibility, the MT contract generates a unique approval ID each time it approves an account. Then when calling `mt_transfer`, `mt_transfer_call`, `mt_batch_transfer`, or `mt_batch_transfer_call` the approved account passes `approval_id` or `approval_ids` with this value to make sure the underlying state of the token(s) hasn't changed from what the approved account expects. From 0017abf6d44e85fd5079675da16e22ca4bf240b1 Mon Sep 17 00:00:00 2001 From: Jay Logelin Date: Fri, 8 Apr 2022 08:28:14 -0300 Subject: [PATCH 041/150] fixed multi-token presentation issue --- specs/Standards/Tokens/MultiToken/README.md | 11 +++++------ specs/Standards/Tokens/MultiToken/_category_.json | 5 +++++ 2 files changed, 10 insertions(+), 6 deletions(-) create mode 100644 specs/Standards/Tokens/MultiToken/_category_.json diff --git a/specs/Standards/Tokens/MultiToken/README.md b/specs/Standards/Tokens/MultiToken/README.md index a593d3907..f6e03e171 100644 --- a/specs/Standards/Tokens/MultiToken/README.md +++ b/specs/Standards/Tokens/MultiToken/README.md @@ -1,7 +1,6 @@ -## Multi Token Standard +import DocCardList from '@theme/DocCardList'; +import {useCurrentSidebarCategory} from '@docusaurus/theme-common'; -- [Multi Token Core](Core.md) -- [Multi Token Metadata](Metadata.md) -- [Multi Token Approval Management](ApprovalManagement.md) -- [Multi Token Enumeration](Enumeration.md) -- [Multi Token Events](Events.md) +# Multi Token Standard + + diff --git a/specs/Standards/Tokens/MultiToken/_category_.json b/specs/Standards/Tokens/MultiToken/_category_.json new file mode 100644 index 000000000..76660bb1c --- /dev/null +++ b/specs/Standards/Tokens/MultiToken/_category_.json @@ -0,0 +1,5 @@ +{ + "label": "MultiToken", + "collapsible": true, + "collapsed": true, +} From 6800b879c146f901849d45c57c28d02c5fb82a1b Mon Sep 17 00:00:00 2001 From: Jay Logelin Date: Thu, 14 Apr 2022 11:37:48 -0300 Subject: [PATCH 042/150] Update README.md --- README.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 59f645d19..315643f23 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,6 @@ # NEAR Protocol Specifications and Standards [![project chat](https://img.shields.io/badge/zulip-join_chat-brightgreen.svg)](https://near.zulipchat.com/#narrow/stream/320497-nep-standards) -[![Discord](https://img.shields.io/discord/490367152054992913.svg)](http://near.chat) [![CI](https://github.com/near/NEPs/actions/workflows/build.yml/badge.svg)](https://github.com/near/NEPs/actions/workflows/build.yml) This repository hosts the current NEAR Protocol specification and standards. @@ -51,8 +50,8 @@ Ideas presented ultimately as NEPs will need to be driven by the author through Spec changes are ultimately done via pull requests to this repository (formalized process [here](neps/nep-0001.md)). In an effort to keep the pull request clean and readable, please follow these instructions to flesh out an idea. -1. Sign up for the [governance site](https://gov.near.org/) and make a post to the appropriate section. For instance, during the ideation phase of a standard, one might start a new conversation in the [Development » Standards section](https://gov.near.org/c/dev/standards/29). The other suggested category in the governance forum is the [Development » Proposals section](https://gov.near.org/c/dev/proposals/68). -2. The forum has comment threading which allows the community and NEAR Collective to ideate, ask questions, wrestle with approaches, etc. If more immediate responses are desired, consider bringing the conversation to [Zulip](https://near.zulipchat.com/#narrow/stream/320497-nep-standards) or [Discord](https://near.chat). +1. Sign up for the [governance site](https://gov.near.org/) and make a post to the appropriate section. For instance, during the ideation phase of a standard, one might start a new conversation in the [Development » Standards section](https://gov.near.org/c/dev/standards/29) or the [NEP Discussions Forum](https://github.com/near/NEPs/discussions). +2. The forum has comment threading which allows the community and NEAR Collective to ideate, ask questions, wrestle with approaches, etc. If more immediate responses are desired, consider bringing the conversation to [Zulip](https://near.zulipchat.com/#narrow/stream/320497-nep-standards). 3. When the governance conversations have reached a point where a clear plan is evident, create a pull request, using the instructions below. * Clone this repository and create a branch with "my-feature". From f046523a84ce1f986e432ff5f1a8940d0234626d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Gaspard?= Date: Thu, 28 Apr 2022 17:41:37 +0200 Subject: [PATCH 043/150] Disambiguate which elements count in the 1M globals limit (#354) --- specs/RuntimeSpec/Preparation.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/specs/RuntimeSpec/Preparation.md b/specs/RuntimeSpec/Preparation.md index 4b0b230cb..a52660b58 100644 --- a/specs/RuntimeSpec/Preparation.md +++ b/specs/RuntimeSpec/Preparation.md @@ -46,7 +46,7 @@ A number of limits are imposed on the WebAssembly module that is being parsed: * `1_000_000` function imports and local function definitions; * `100_000` imports; * `100_000` exports; - * `1_000_000` global definitions and imports; + * `1_000_000` global imports and module-local global definitions; * `100_000` data segments; * `1` table; * `1` memory; From 0210940992d5b50b6d5e0a6c74445ef026bbd5b1 Mon Sep 17 00:00:00 2001 From: Michal Nazarewicz Date: Mon, 23 May 2022 17:22:57 +0100 Subject: [PATCH 044/150] Update information about transaction_validity_period (#357) The transaction validity period has been configured via genesis for years. Even before the date listed in the document. Update information on the validity period. --- .../Scenarios/FinancialTransaction.md | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/specs/RuntimeSpec/Scenarios/FinancialTransaction.md b/specs/RuntimeSpec/Scenarios/FinancialTransaction.md index a4256996e..0913b6256 100644 --- a/specs/RuntimeSpec/Scenarios/FinancialTransaction.md +++ b/specs/RuntimeSpec/Scenarios/FinancialTransaction.md @@ -51,11 +51,17 @@ succession) which should be strictly increasing with each transaction. Unlike in the entire accounts, so several users using the same account through different access keys need not to worry about accidentally reusing each other's nonces. -The block hash is used to calculate the transaction "freshness". It is used to make sure the transaction does -not get lost (let's say somewhere in the network) and then arrive hours, days, or years later when it is not longer relevant -or would be undesirable to execute. The transaction does not need to arrive at the specific block, instead it is required to -arrive within certain number of blocks from the bock identified by the `block_hash` (as of 2019-10-27 the constant is 10 blocks). -Any transaction arriving outside this threshold is considered to be invalid. +The block hash is used to calculate the transaction "freshness". It +is used to make sure the transaction does not get lost (let's say +somewhere in the network) and then arrive days, weeks or years later +when it is not longer relevant or would be undesirable to execute. +The transaction does not need to arrive at the specific block, instead +it is required to arrive within certain number of blocks from the bock +identified by the `block_hash`. Any transaction arriving outside this +threshold is considered to be invalid. Allowed delay is defined by +`transaction_validity_period` option in chain’s genesis file. On +mainnet the value is 86400 (which corresponds to roughly a day) while +on testnet it’s 100. near-shell or other tool that Alice uses then signs this transaction, by: computing the hash of the transaction and signing it with the secret key, resulting in a `SignedTransaction` object. From a67df2dd6743dca229a30dd4c3b1cefaf58b3eb5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mehmet=20Efe=20Ak=C3=A7a?= Date: Tue, 24 May 2022 15:33:17 +0300 Subject: [PATCH 045/150] Respect system preference for theme in website (#353) --- website/docusaurus.config.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/website/docusaurus.config.js b/website/docusaurus.config.js index bf1c32f64..9f74cc7f4 100644 --- a/website/docusaurus.config.js +++ b/website/docusaurus.config.js @@ -64,6 +64,9 @@ const config = { themeConfig: /** @type {import('@docusaurus/preset-classic').ThemeConfig} */ ({ + colorMode: { + respectPrefersColorScheme: true + }, navbar: { title: 'Nomicon', logo: { From bd2fb271092836c6da8c30c0e06f5ed3b497edca Mon Sep 17 00:00:00 2001 From: Akhilesh Singhania Date: Tue, 24 May 2022 14:35:33 +0200 Subject: [PATCH 046/150] Fix minor typo (#356) Fixed a minor typo --- specs/RuntimeSpec/Scenarios/FinancialTransaction.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/specs/RuntimeSpec/Scenarios/FinancialTransaction.md b/specs/RuntimeSpec/Scenarios/FinancialTransaction.md index 0913b6256..6ac045f4c 100644 --- a/specs/RuntimeSpec/Scenarios/FinancialTransaction.md +++ b/specs/RuntimeSpec/Scenarios/FinancialTransaction.md @@ -18,7 +18,7 @@ Suppose Alice has account `alice_near` and Bob has account `bob_near`. Also, som each of them has created a public-secret key-pair, saved the secret key somewhere (e.g. in a wallet application) and created a full access key with the public key for the account. -We also need to assume that both Alice and Bob has some number of tokens on their accounts. Alice needs >100 tokens on the account +We also need to assume that both Alice and Bob have some number of tokens on their accounts. Alice needs >100 tokens on the account so that she could transfer 100 tokens to Bob, but also Alice and Bob need to have some tokens to pay for the _rent_ of their account -- which is essentially the cost of the storage occupied by the account in the Near Protocol network. From 6950fbe03d50bab43c4f32e8708b6d6b372f325d Mon Sep 17 00:00:00 2001 From: Austin Abell Date: Tue, 31 May 2022 06:28:07 -0400 Subject: [PATCH 047/150] fix: make versioning consistent from #315 (#325) Co-authored-by: Damian Parrino --- specs/Standards/Tokens/NonFungibleToken/Core.md | 2 +- specs/Standards/Tokens/NonFungibleToken/Metadata.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/specs/Standards/Tokens/NonFungibleToken/Core.md b/specs/Standards/Tokens/NonFungibleToken/Core.md index f16aead6e..3e9948c38 100644 --- a/specs/Standards/Tokens/NonFungibleToken/Core.md +++ b/specs/Standards/Tokens/NonFungibleToken/Core.md @@ -2,7 +2,7 @@ ## [NEP-171](https://github.com/near/NEPs/blob/master/neps/nep-0171.md) -Version `1.0.2` +Version `1.1.0` ## Summary diff --git a/specs/Standards/Tokens/NonFungibleToken/Metadata.md b/specs/Standards/Tokens/NonFungibleToken/Metadata.md index 38daa9b52..ed11c9e84 100644 --- a/specs/Standards/Tokens/NonFungibleToken/Metadata.md +++ b/specs/Standards/Tokens/NonFungibleToken/Metadata.md @@ -2,7 +2,7 @@ ## [NEP-177](https://github.com/near/NEPs/blob/master/neps/nep-0177.md) -Version `2.0.1` +Version `2.1.0` ## Summary From 51ad3650d352f37f225c2d2eb21be82db0f8266b Mon Sep 17 00:00:00 2001 From: Rijul Gulati Date: Sun, 19 Jun 2022 22:32:36 +0530 Subject: [PATCH 048/150] Corrected Transaction ordering text (#355) --- specs/ChainSpec/Transactions.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/specs/ChainSpec/Transactions.md b/specs/ChainSpec/Transactions.md index 10172cd08..de7402a6c 100644 --- a/specs/ChainSpec/Transactions.md +++ b/specs/ChainSpec/Transactions.md @@ -18,7 +18,7 @@ Transactions within a group are not ordered. The valid order of the transactions in a chunk is the following: - transactions are ordered in batches. -- within a batch all transactions keys should have different. +- within a batch all transactions keys should be different. - a set of transaction keys in each subsequent batch should be a sub-set of keys from the previous batch. - transactions with the same key should be ordered in strictly increasing order of their corresponding nonces. From d77cb9bd73506d9cd35ccf05c01843b7f400f304 Mon Sep 17 00:00:00 2001 From: Lyudmil Ivanov <55487633+flmel@users.noreply.github.com> Date: Fri, 22 Jul 2022 21:19:21 +0300 Subject: [PATCH 049/150] Update urls on NEPs (#362) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * update urls on nep-0141 * update urls on nep-0171 * fixed typos * updated nep-0141 and nep-0145 * update urls on nep-0148, move refs on nep-0171 * update urls on nep-0177 and nep-0178 * update urls on nep-0181 and nep-0245 * Update neps/nep-0297.md Co-authored-by: Damián Parrino --- neps/nep-0001.md | 4 ++-- neps/nep-0141.md | 22 +++++++++++++--------- neps/nep-0145.md | 8 +++++--- neps/nep-0148.md | 6 ++++-- neps/nep-0171.md | 25 ++++++++++++++----------- neps/nep-0177.md | 9 ++++++--- neps/nep-0178.md | 19 +++++++++++-------- neps/nep-0181.md | 9 ++++----- neps/nep-0245.md | 38 ++++++++++++++++++++------------------ neps/nep-0297.md | 2 +- 10 files changed, 80 insertions(+), 62 deletions(-) diff --git a/neps/nep-0001.md b/neps/nep-0001.md index 05cd1baff..fbe1e8539 100644 --- a/neps/nep-0001.md +++ b/neps/nep-0001.md @@ -16,7 +16,7 @@ a new feature for the Near protocol, Smart Contract standards, or it's environme The NEP should provide a concise technical specification of the feature and a rationale for the feature. -NEPs are intented to be the primary mechanism for proposing new features, interfacing +NEPs are intended to be the primary mechanism for proposing new features, interfacing with the community on an issue and documenting design decisions that have been integrated into Near's runtime or Smart Contract ecosystem. @@ -274,7 +274,7 @@ header preamble. The headers must appear in the following order. ``` NEP: Title: - Author: + Author: DiscussionsTo: Status: Type: diff --git a/neps/nep-0141.md b/neps/nep-0141.md index 0aafb889d..609258da1 100644 --- a/neps/nep-0141.md +++ b/neps/nep-0141.md @@ -13,8 +13,8 @@ Requires: 297 ## Summary -A standard interface for fungible tokens that allows for a normal transfer as well as a transfer and method call in a single transaction. The [storage standard](../StorageManagement.md) addresses the needs (and security) of storage staking. -The [fungible token metadata standard](Metadata.md) provides the fields needed for ergonomics across dApps and marketplaces. +A standard interface for fungible tokens that allows for a normal transfer as well as a transfer and method call in a single transaction. The [storage standard][Storage Management] addresses the needs (and security) of storage staking. +The [fungible token metadata standard][FT Metadata] provides the fields needed for ergonomics across dApps and marketplaces. ## Motivation @@ -37,7 +37,7 @@ Prior art: Learn about NEP-141: -- [Figment Learning Pathway](https://learn.figment.io/network-documentation/near/tutorials/1-project_overview/2-fungible-token) +- [Figment Learning Pathway](https://learn.figment.io/tutorials/stake-fungible-token) ## Specification @@ -59,9 +59,9 @@ There are a few concepts in the scenarios above: - **Transfer and call**: an action that moves some amount from one account to a contract account where the receiver calls a method. - **Storage amount**: the amount of storage used for an account to be "registered" in the fungible token. This amount is denominated in Ⓝ, not bytes, and represents the [storage staked](https://docs.near.org/docs/concepts/storage-staking). -Note that precision (the number of decimal places supported by a given token) is not part of this core standard, since it's not required to perform actions. The minimum value is always 1 token. See the [Fungible Token Metadata Standard](Metadata.md) to learn how to support precision/decimals in a standardized way. +Note that precision (the number of decimal places supported by a given token) is not part of this core standard, since it's not required to perform actions. The minimum value is always 1 token. See the [Fungible Token Metadata Standard][FT Metadata] to learn how to support precision/decimals in a standardized way. -Given that multiple users will use a Fungible Token contract, and their activity will result in an increased [storage staking](https://docs.near.org/docs/concepts/storage-staking) burden for the contract's account, this standard is designed to interoperate nicely with [the Account Storage standard](../StorageManagement.md) for storage deposits and refunds. +Given that multiple users will use a Fungible Token contract, and their activity will result in an increased [storage staking](https://docs.near.org/docs/concepts/storage-staking) burden for the contract's account, this standard is designed to interoperate nicely with [the Account Storage standard][Storage Management] for storage deposits and refunds. #### Example scenarios @@ -186,7 +186,7 @@ Altogether then, Alice may take two steps, though the first may be a background - All amounts, balances and allowance are limited by `U128` (max value `2**128 - 1`). - Token standard uses JSON for serialization of arguments and results. - Amounts in arguments and results have are serialized as Base-10 strings, e.g. `"100"`. This is done to avoid JSON limitation of max integer value of `2**53`. -- The contract must track the change in storage when adding to and removing from collections. This is not included in this core fungible token standard but instead in the [Storage Standard](../StorageManagement.md). +- The contract must track the change in storage when adding to and removing from collections. This is not included in this core fungible token standard but instead in the [Storage Standard][Storage Management]. - To prevent the deployed contract from being modified or deleted, it should not have any access keys on its account. #### Interface: @@ -331,7 +331,7 @@ Standard interfaces for FT contract actions that extend [NEP-297](nep-0297.md) NEAR and third-party applications need to track `mint`, `transfer`, `burn` events for all FT-driven apps consistently. This extension addresses that. -Keep in mind that applications, including NEAR Wallet, could require implementing additional methods, such as [`ft_metadata`](Metadata.md), to display the FTs correctly. +Keep in mind that applications, including NEAR Wallet, could require implementing additional methods, such as [`ft_metadata`][FT Metadata], to display the FTs correctly. ### Event Interface @@ -435,7 +435,7 @@ EVENT_JSON:{ Note that the example events covered above cover two different kinds of events: 1. Events that are not specified in the FT Standard (`ft_mint`, `ft_burn`) -2. An event that is covered in the [FT Core Standard](Core.md). (`ft_transfer`) +2. An event that is covered in the [FT Core Standard][FT Core]. (`ft_transfer`) Please feel free to open pull requests for extending the events standard detailed here as needs arise. @@ -467,4 +467,8 @@ See also the discussions: ## Copyright -Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). \ No newline at end of file +Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). + +[Storage Management]: ../specs/Standards/StorageManagement.md +[FT Metadata]: ../specs/Standards/Tokens/FungibleToken/Metadata.md +[FT Core]: ../specs/Standards/Tokens/FungibleToken/Core.md \ No newline at end of file diff --git a/neps/nep-0145.md b/neps/nep-0145.md index 781e06d6d..ccf309c40 100644 --- a/neps/nep-0145.md +++ b/neps/nep-0145.md @@ -49,7 +49,7 @@ To show the flexibility and power of this standard, let's walk through two examp ### Example 1: Fungible Token Contract -Imagine a [fungible token](FungibleToken/Core.md) contract deployed at `ft`. Let's say this contract saves all user balances to a Map data structure internally, and adding a key for a new user requires 0.00235Ⓝ. This contract therefore uses the Storage Management standard to pass this cost onto users, so that a new user must effectively pay a registration fee to interact with this contract of 0.00235Ⓝ, or 2350000000000000000000 yoctoⓃ ([yocto](https://www.metricconversion.us/prefixes.htm) = 10-24). +Imagine a [fungible token][FT Core] contract deployed at `ft`. Let's say this contract saves all user balances to a Map data structure internally, and adding a key for a new user requires 0.00235Ⓝ. This contract therefore uses the Storage Management standard to pass this cost onto users, so that a new user must effectively pay a registration fee to interact with this contract of 0.00235Ⓝ, or 2350000000000000000000 yoctoⓃ ([yocto](https://www.metricconversion.us/prefixes.htm) = 10-24). For this contract, `storage_balance_bounds` will be: @@ -183,7 +183,7 @@ Bob wants to close his account, but has a non-zero balance of `ft` tokens. It fails with a message like "Cannot gracefully close account with positive remaining balance; bob has balance N" -2. Bob transfers his tokens to a friend using `ft_transfer` from the [Fungible Token Core](FungibleToken/Core.md) standard. +2. Bob transfers his tokens to a friend using `ft_transfer` from the [Fungible Token Core][FT Core] standard. 3. Bob tries the call from Step 1 again. It works. @@ -451,4 +451,6 @@ The `near-contract-standards` cargo package of the [Near Rust SDK](https://githu ## Copyright [copyright]: #copyright -Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). \ No newline at end of file +Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). + +[FT Core]: ../specs/Standards/Tokens/FungibleToken/Core.md \ No newline at end of file diff --git a/neps/nep-0148.md b/neps/nep-0148.md index bd2254db3..d4f2ba027 100644 --- a/neps/nep-0148.md +++ b/neps/nep-0148.md @@ -88,7 +88,7 @@ type FungibleTokenMetadata = { **An implementing contract MUST include the following fields on-chain** -- `spec`: a string. Should be `ft-1.0.0` to indicate that a Fungible Token contract adheres to the current versions of this Metadata and the [Fungible Token Core](./Core.md) specs. This will allow consumers of the Fungible Token to know if they support the features of a given contract. +- `spec`: a string. Should be `ft-1.0.0` to indicate that a Fungible Token contract adheres to the current versions of this Metadata and the [Fungible Token Core][FT Core] specs. This will allow consumers of the Fungible Token to know if they support the features of a given contract. - `name`: the human-readable name of the token. - `symbol`: the abbreviation, like wETH or AMPL. - `decimals`: used in frontends to show the proper significant digits of a token. This concept is explained well in this [OpenZeppelin post](https://docs.openzeppelin.com/contracts/3.x/erc20#a-note-on-decimals). @@ -118,4 +118,6 @@ The `near-contract-standards` cargo package of the [Near Rust SDK](https://githu ## Copyright [copyright]: #copyright -Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). \ No newline at end of file +Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). + +[FT Core]: ../specs/Standards/Tokens/FungibleToken/Core.md \ No newline at end of file diff --git a/neps/nep-0171.md b/neps/nep-0171.md index 582cf6ab5..18fcf6b62 100644 --- a/neps/nep-0171.md +++ b/neps/nep-0171.md @@ -35,7 +35,7 @@ Prior art: - [ERC-721] - [EIP-1155 for multi-tokens](https://eips.ethereum.org/EIPS/eip-1155#non-fungible-tokens) -- [NEAR's Fungible Token Standard](../FungibleToken/Core.md), which first pioneered the "transfer and call" technique +- [NEAR's Fungible Token Standard][FT Core], which first pioneered the "transfer and call" technique ## Rationale and alternatives @@ -51,7 +51,7 @@ Prior art: - All amounts, balances and allowance are limited by `U128` (max value `2**128 - 1`). - Token standard uses JSON for serialization of arguments and results. - Amounts in arguments and results are serialized as Base-10 strings, e.g. `"100"`. This is done to avoid JSON limitation of max integer value of `2**53`. -- The contract must track the change in storage when adding to and removing from collections. This is not included in this core fungible token standard but instead in the [Storage Standard](../StorageManagement.md). +- The contract must track the change in storage when adding to and removing from collections. This is not included in this core fungible token standard but instead in the [Storage Standard][Storage Management]. - To prevent the deployed contract from being modified or deleted, it should not have any access keys on its account. ### NFT Interface @@ -219,11 +219,11 @@ function nft_on_transfer( NEAR and third-party applications need to track `mint`, `transfer`, `burn` events for all NFT-driven apps consistently. This extension addresses that. -Keep in mind that applications, including NEAR Wallet, could require implementing additional methods to display the NFTs correctly, such as [`nft_metadata`](Metadata.md) and [`nft_tokens_for_owner`](Enumeration.md). +Keep in mind that applications, including NEAR Wallet, could require implementing additional methods to display the NFTs correctly, such as [`nft_metadata`][Metadata] and [`nft_tokens_for_owner`][NFT Enumeration]). ### Events Interface -Non-Fungible Token Events MUST have `standard` set to `"nep171"`, standard version set to `"1.0.0"`, `event` value is one of `nft_mint`, `nft_burn`, `nft_transfer`, and `data` must be of one of the following relavant types: `NftMintLog[] | NftTransferLog[] | NftBurnLog[]`: +Non-Fungible Token Events MUST have `standard` set to `"nep171"`, standard version set to `"1.0.0"`, `event` value is one of `nft_mint`, `nft_burn`, `nft_transfer`, and `data` must be of one of the following relevant types: `NftMintLog[] | NftTransferLog[] | NftBurnLog[]`: ```ts interface NftEventLogData { @@ -364,13 +364,16 @@ Please feel free to open pull requests for extending the events standard detaile * **2021-12-20**: updated `nft_resolve_transfer` argument `approved_account_ids` to be type `null|Record` instead of `null|string[]`. This gives contracts a way to restore the original approved accounts and their approval IDs. More information can be found in [this](https://github.com/near/NEPs/issues/301) discussion. * **2021-07-16**: updated `nft_transfer_call` argument `approval_id` to be type `number|null` instead of `string|null`. As stated, approval IDs are not expected to exceed the JSON limit of 2^53. - [ERC-721]: https://eips.ethereum.org/EIPS/eip-721 - [storage staking]: https://docs.near.org/docs/concepts/storage-staking - [gas]: https://docs.near.org/docs/concepts/gas - [Metadata]: Metadata.md - [Approval Management]: ApprovalManagement.md - ## Copyright [copyright]: #copyright -Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). \ No newline at end of file +Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). + +[ERC-721]: https://eips.ethereum.org/EIPS/eip-721 +[storage staking]: https://docs.near.org/docs/concepts/storage-staking +[gas]: https://docs.near.org/docs/concepts/gas +[Metadata]: ../specs/Standards/Tokens/NonFungibleToken/Metadata.md +[Approval Management]: ../specs/Standards/Tokens/NonFungibleToken/ApprovalManagement.md +[FT core]: ../specs/Standards/Tokens/FungibleToken/Core.md +[Storage Management]: ../specs/Standards/StorageManagement.md +[NFT Enumeration]: ../specs/Standards/Tokens/NonFungibleToken/Enumeration.md \ No newline at end of file diff --git a/neps/nep-0177.md b/neps/nep-0177.md index 0e06091df..1682f0d25 100644 --- a/neps/nep-0177.md +++ b/neps/nep-0177.md @@ -16,7 +16,7 @@ An interface for a non-fungible token's metadata. The goal is to keep the metada ## Motivation -The primary value of non-fungible tokens comes from their metadata. While the [core standard](Core.md) provides the minimum interface that can be considered a non-fungible token, most artists, developers, and dApps will want to associate more data with each NFT, and will want a predictable way to interact with any NFT's metadata. +The primary value of non-fungible tokens comes from their metadata. While the [core standard][NFT Core] provides the minimum interface that can be considered a non-fungible token, most artists, developers, and dApps will want to associate more data with each NFT, and will want a predictable way to interact with any NFT's metadata. ## Rationale and alternatives @@ -26,7 +26,7 @@ This standard also provides a `spec` version. This makes it easy for consumers o Prior art: -- NEAR's [Fungible Token Metadata Standard](../FungibleToken/Metadata.md) +- NEAR's [Fungible Token Metadata Standard][FT Metadata] - Discussion about NEAR's complete NFT standard: #171 ## Specification @@ -151,4 +151,7 @@ It gave those fields the type `string|null` but it was unclear whether it should ## Copyright [copyright]: #copyright -Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). \ No newline at end of file +Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). + +[NFT Core]: ../specs/Standards/Tokens/NonFungibleToken/Core.md +[FT Metadata]: ../specs/Standards/Tokens/FungibleToken/Metadata.md \ No newline at end of file diff --git a/neps/nep-0178.md b/neps/nep-0178.md index 9e9eea805..e4b4655b5 100644 --- a/neps/nep-0178.md +++ b/neps/nep-0178.md @@ -14,15 +14,13 @@ Requires: 171 A system for allowing a set of users or contracts to transfer specific Non-Fungible Tokens on behalf of an owner. Similar to approval management systems in standards like [ERC-721]. - [ERC-721]: https://eips.ethereum.org/EIPS/eip-721 - ## Motivation People familiar with [ERC-721] may expect to need an approval management system for basic transfers, where a simple transfer from Alice to Bob requires that Alice first _approve_ Bob to spend one of her tokens, after which Bob can call `transfer_from` to actually transfer the token to himself. ## Rationale and alternatives -NEAR's [core Non-Fungible Token standard](Core.md) includes good support for safe atomic transfers without such complexity. It even provides "transfer and call" functionality (`nft_transfer_call`) which allows a specific token to be "attached" to a call to a separate contract. For many Non-Fungible Token workflows, these options may circumvent the need for a full-blown Approval Managament system. +NEAR's [core Non-Fungible Token standard][NFT Core] includes good support for safe atomic transfers without such complexity. It even provides "transfer and call" functionality (`nft_transfer_call`) which allows a specific token to be "attached" to a call to a separate contract. For many Non-Fungible Token workflows, these options may circumvent the need for a full-blown Approval Management system. However, some Non-Fungible Token developers, marketplaces, dApps, or artists may require greater control. This standard provides a uniform interface allowing token owners to approve other NEAR accounts, whether individuals or contracts, to transfer specific tokens on the owner's behalf. @@ -39,11 +37,11 @@ Let's consider some examples. Our cast of characters & apps: * Alice: has account `alice` with no contract deployed to it * Bob: has account `bob` with no contract deployed to it -* NFT: a contract with account `nft`, implementing only the [Core NFT standard](Core.md) with this Approval Management extension +* NFT: a contract with account `nft`, implementing only the [Core NFT standard][NFT Core] with this Approval Management extension * Market: a contract with account `market` which sells tokens from `nft` as well as other NFT contracts * Bazaar: similar to Market, but implemented differently (spoiler alert: has no `nft_on_approve` function!), has account `bazaar` -Alice and Bob are already [registered](../StorageManagement.md) with NFT, Market, and Bazaar, and Alice owns a token on the NFT contract with ID=`"1"`. +Alice and Bob are already [registered][Storage Management] with NFT, Market, and Bazaar, and Alice owns a token on the NFT contract with ID=`"1"`. Let's examine the technical calls through the following scenarios: @@ -179,7 +177,7 @@ Not to worry, though, she checks `nft_is_approved` and sees that she did success ### 4. Approval IDs -Bob buys Alice's token via Market. Bob probably does this via Market's frontend, which will probably initiate the transfer via a call to `ft_transfer_call` on the nDAI contract to transfer 100 nDAI to `market`. Like the NFT standard's "transfer and call" function, [Fungible Token](../FungibleToken/Core.md)'s `ft_transfer_call` takes a `msg` which `market` can use to pass along information it will need to pay Alice and actually transfer the NFT. The actual transfer of the NFT is the only part we care about here. +Bob buys Alice's token via Market. Bob probably does this via Market's frontend, which will probably initiate the transfer via a call to `ft_transfer_call` on the nDAI contract to transfer 100 nDAI to `market`. Like the NFT standard's "transfer and call" function, [Fungible Token][FT Core]'s `ft_transfer_call` takes a `msg` which `market` can use to pass along information it will need to pay Alice and actually transfer the NFT. The actual transfer of the NFT is the only part we care about here. **High-level explanation** @@ -226,7 +224,7 @@ Using near-cli: "token_id": "1", }' --accountId alice --depositYocto 1 -Note that `market` will not get a cross-contract call in this case. The implementors of the Market app should implement [cron](https://en.wikipedia.org/wiki/Cron)-type functionality to intermittently check that Market still has the access they expect. +Note that `market` will not get a cross-contract call in this case. The implementers of the Market app should implement [cron](https://en.wikipedia.org/wiki/Cron)-type functionality to intermittently check that Market still has the access they expect. ### 7. Revoke all @@ -468,4 +466,9 @@ NFT contracts should be implemented in a way to avoid extra gas fees for seriali ## Copyright [copyright]: #copyright -Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). \ No newline at end of file +Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). + +[ERC-721]: https://eips.ethereum.org/EIPS/eip-721 +[NFT Core]: ../specs/Standards/Tokens/NonFungibleToken/Core.md +[Storage Management]: ../specs/Standards/StorageManagement.md +[FT Core]: ../specs/Standards/Tokens/FungibleToken/Core.md \ No newline at end of file diff --git a/neps/nep-0181.md b/neps/nep-0181.md index 2ba0cd862..bd81c3d1d 100644 --- a/neps/nep-0181.md +++ b/neps/nep-0181.md @@ -80,10 +80,6 @@ function nft_tokens_for_owner( At the time of this writing, the specialized collections in the `near-sdk` Rust crate are iterable, but not all of them have implemented an `iter_from` solution. There may be efficiency gains for large collections and contract developers are encouraged to test their data structures with a large amount of entries. - [ERC-721]: https://eips.ethereum.org/EIPS/eip-721 - [storage]: https://docs.near.org/docs/concepts/storage-staking - - ## Reference Implementation [Minimum Viable Interface](https://github.com/near/near-sdk-rs/blob/master/near-contract-standards/src/non_fungible_token/enumeration/mod.rs) @@ -93,4 +89,7 @@ At the time of this writing, the specialized collections in the `near-sdk` Rust ## Copyright [copyright]: #copyright -Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). \ No newline at end of file +Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). + +[ERC-721]: https://eips.ethereum.org/EIPS/eip-721 +[storage]: https://docs.near.org/docs/concepts/storage-staking diff --git a/neps/nep-0245.md b/neps/nep-0245.md index a92df5aa8..f49863c92 100644 --- a/neps/nep-0245.md +++ b/neps/nep-0245.md @@ -21,7 +21,7 @@ In the three years since [ERC-1155] was ratified by the Ethereum Community, Mult Having a single contract represent NFTs, FTs, and tokens that sit inbetween greatly improves efficiency. The standard also introduced the ability to make batch requests with multiple asset classes reducing complexity. This standard allows operations that currently require _many_ transactions to be completed in a single transaction that can transfer not only NFTs and FTs, but any tokens that are a part of same token contract. -With this standard, we have sought to take advantage of the ability of the NEAR blockchain to scale. Its sharded runtime, and [storage staking] model that decouples [gas] fees from storage demand, enables ultra low transaction fees and greater on chain storage ( see [Metadata] extension). +With this standard, we have sought to take advantage of the ability of the NEAR blockchain to scale. Its sharded runtime, and [storage staking] model that decouples [gas] fees from storage demand, enables ultra low transaction fees and greater on chain storage (see [Metadata][MT Metadata] extension). With the aforementioned, it is noteworthy to mention that like the [NFT] standard the Multi Token standard, implements `mt_transfer_call`, which allows, a user to attach many tokens to a call to a separate contract. Additionally, this standard includes an optional [Approval Management] extension. The extension allows marketplaces to trade on behalf of a user, providing additional flexibility for dApps. @@ -30,8 +30,8 @@ Prior art: - [ERC-721] - [ERC-1155] -- [NEAR Fungible Token Standard][FT], which first pioneered the "transfer and call" technique -- [NEAR Non-Fungible Token Standard][NFT] +- [NEAR Fungible Token Standard][FT Core], which first pioneered the "transfer and call" technique +- [NEAR Non-Fungible Token Standard][NFT Core] ## Rationale and alternatives @@ -43,9 +43,9 @@ The decision to not use FT and NFT as explicit token types was taken to allow th The issues with this in general is a problem with defining what metadata means and how is that interpreted. We have chosen to follow the pattern that is currently in use on Ethereum in the [ERC-1155] standard. That pattern relies on people to make extensions or to make signals as to how they want the metadata to be represented for their use case. -One of the areas that has broad sweeping implications from the [ERC-1155] standard is the lack of direct access to metadata. With Near's sharding we are able to have a [Metadata Extension](Metadata.md) for the standard that exists on chain. So developers and users are not required to use an indexer to understand, how to interact or interpret tokens, via token identifiers that they receive. +One of the areas that has broad sweeping implications from the [ERC-1155] standard is the lack of direct access to metadata. With Near's sharding we are able to have a [Metadata Extension][MT Metadata] for the standard that exists on chain. So developers and users are not required to use an indexer to understand, how to interact or interpret tokens, via token identifiers that they receive. -Another extension that we made was to provide an explicit ability for developers and users to group or link together series of NFTs/FTs or any combination of tokens. This provides additional flexiblity that the [ERC-1155] standard only has loose guidelines on. This was chosen to make it easy for consumers to understand the relationship between tokens within the contract. +Another extension that we made was to provide an explicit ability for developers and users to group or link together series of NFTs/FTs or any combination of tokens. This provides additional flexibility that the [ERC-1155] standard only has loose guidelines on. This was chosen to make it easy for consumers to understand the relationship between tokens within the contract. To recap, we choose to create this standard, to improve interoperability, developer ease of use, and to extend token representability beyond what was available directly in the FT or NFT standards. We believe this to be another tool in the developer's toolkit. It makes it possible to represent many types of tokens and to enable exchanges of many tokens within a single `transaction`. @@ -55,7 +55,7 @@ To recap, we choose to create this standard, to improve interoperability, develo - All amounts, balances and allowance are limited by `U128` (max value `2**128 - 1`). - Token standard uses JSON for serialization of arguments and results. - Amounts in arguments and results are serialized as Base-10 strings, e.g. `"100"`. This is done to avoid JSON limitation of max integer value of `2**53`. -- The contract must track the change in storage when adding to and removing from collections. This is not included in this core multi token standard but instead in the [Storage Standard](../StorageManagement.md). +- The contract must track the change in storage when adding to and removing from collections. This is not included in this core multi token standard but instead in the [Storage Standard][Storage Management]. - To prevent the deployed contract from being modified or deleted, it should not have any access keys on its account. ### MT Interface @@ -397,10 +397,10 @@ function mt_on_transfer( NEAR and third-party applications need to track `mint`, `burn`, `transfer` events for all MT-driven apps consistently. This exension addresses that. -Note that applications, including NEAR Wallet, could require implementing additional methods to display tokens correctly such as [`mt_metadata`](Metadata.md) and [`mt_tokens_for_owner`](Enumeration.md). +Note that applications, including NEAR Wallet, could require implementing additional methods to display tokens correctly such as [`mt_metadata`][MT Metadata] and [`mt_tokens_for_owner`][MT Enumeration]. ### Events Interface -Multi Token Events MUST have `standard` set to `"nep245"`, standard version set to `"1.0.0"`, `event` value is one of `mt_mint`, `mt_burn`, `mt_transfer`, and `data` must be of one of the following relavant types: `MtMintLog[] | MtBurnLog[] | MtTransferLog[]`: +Multi Token Events MUST have `standard` set to `"nep245"`, standard version set to `"1.0.0"`, `event` value is one of `mt_mint`, `mt_burn`, `mt_transfer`, and `data` must be of one of the following relevant types: `MtMintLog[] | MtBurnLog[] | MtTransferLog[]`: @@ -554,9 +554,9 @@ EVENT_JSON:{ Note that the example events covered above cover two different kinds of events: 1. Events that are not specified in the MT Standard (`mt_mint`, `mt_burn`) -2. An event that is covered in the [Multi Token Core Standard](https://nomicon.io/Standards/MultiToken/Core.html#mt-interface). (`mt_transfer`) +2. An event that is covered in the [Multi Token Core Standard](https://nomicon.io/Standards/Tokens/MultiToken/Core#mt-interface). (`mt_transfer`) -This event standard also applies beyond the three events highlighted here, where future events follow the same convention of as the second type. For instance, if an MT contract uses the [approval management standard](https://nomicon.io/Standards/MultiToken/ApprovalManagement.html), it may emit an event for `mt_approve` if that's deemed as important by the developer community. +This event standard also applies beyond the three events highlighted here, where future events follow the same convention of as the second type. For instance, if an MT contract uses the [approval management standard](https://nomicon.io/Standards/Tokens/MultiToken/ApprovalManagement), it may emit an event for `mt_approve` if that's deemed as important by the developer community. Please feel free to open pull requests for extending the events standard detailed here as needs arise. @@ -573,11 +573,13 @@ Please feel free to open pull requests for extending the events standard detaile Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). - [ERC-721]: https://eips.ethereum.org/EIPS/eip-721 - [ERC-1155]: https://eips.ethereum.org/EIPS/eip-1155 - [storage staking]: https://docs.near.org/docs/concepts/storage-staking - [gas]: https://docs.near.org/docs/concepts/gas - [Metadata]: ../specs/Standards/MultiToken/Metadata.md - [NFT]: ../specs/Standards/NonFungibleToken/Core.md - [Approval Management]: ../specs/Standards/MultiToken/ApprovalManagement.md - [FT]: ../specs/Standards/FungibleToken/Core.md +[ERC-721]: https://eips.ethereum.org/EIPS/eip-721 +[ERC-1155]: https://eips.ethereum.org/EIPS/eip-1155 +[storage staking]: https://docs.near.org/docs/concepts/storage-staking +[gas]: https://docs.near.org/docs/concepts/gas +[MT Metadata]: ../specs/Standards/Tokens/MultiToken/Metadata.md +[NFT Core]: ../specs/Standards/Tokens/NonFungibleToken/Core.md +[Approval Management]: ../specs/Standards/MultiToken/ApprovalManagement.md +[FT Core]: ../specs/Standards/Tokens/FungibleToken/Core.md +[Storage Management]: ../specs/Standards/StorageManagement.md +[MT Enumeration]: ../specs/Standards/Tokens/MultiToken/Enumeration.md diff --git a/neps/nep-0297.md b/neps/nep-0297.md index 7be93307c..e7ad4fde1 100644 --- a/neps/nep-0297.md +++ b/neps/nep-0297.md @@ -60,7 +60,7 @@ interface EventLogData { } ``` -Thus, to emit an event, you only need to log a string following the rules above. Here is a barebones example using Rust SDK `near_sdk::log!` macro (security note: prefer using `serde_json` or alternatives to serialize the JSON string to avoid potential injections and corrupted events): +Thus, to emit an event, you only need to log a string following the rules above. Here is a bare-bones example using Rust SDK `near_sdk::log!` macro (security note: prefer using `serde_json` or alternatives to serialize the JSON string to avoid potential injections and corrupted events): ```rust use near_sdk::log; From 82503105d64e828b3c3a19bfa63d00661be57b08 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dami=C3=A1n=20Parrino?= Date: Tue, 26 Jul 2022 14:54:54 -0300 Subject: [PATCH 050/150] Update links (#375) * Update nep-0177.md * Update Metadata.md * Update nep-0148.md * Update nep-0148.md --- neps/nep-0148.md | 6 +++--- neps/nep-0177.md | 6 +++--- specs/Standards/Tokens/FungibleToken/Metadata.md | 4 ++-- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/neps/nep-0148.md b/neps/nep-0148.md index d4f2ba027..ff2a68357 100644 --- a/neps/nep-0148.md +++ b/neps/nep-0148.md @@ -48,7 +48,7 @@ Alice issues a transaction to deploy and initialize the fungible token contract, **Technical calls** -1. `alice` deploys a contract and calls `wbtc::new` with all metadata. If this deploy and initialization were done using [NEAR CLI](https://docs.near.org/docs/tools/near-cli) the command would be: +1. `alice` deploys a contract and calls `wbtc::new` with all metadata. If this deploy and initialization were done using [NEAR CLI](https://docs.near.org/tools/near-cli) the command would be: near deploy wbtc --wasmFile res/ft.wasm --initFunction new --initArgs '{ "owner_id": "wbtc", @@ -95,7 +95,7 @@ type FungibleTokenMetadata = { **An implementing contract MAY include the following fields on-chain** -- `icon`: a small image associated with this token. Must be a [data URL](https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/Data_URIs), to help consumers display it quickly while protecting user data. Recommendation: use [optimized SVG](https://codepen.io/tigt/post/optimizing-svgs-in-data-uris), which can result in high-resolution images with only 100s of bytes of [storage cost](https://docs.near.org/docs/concepts/storage-staking). (Note that these storage costs are incurred to the token owner/deployer, but that querying these icons is a very cheap & cacheable read operation for all consumers of the contract and the RPC nodes that serve the data.) Recommendation: create icons that will work well with both light-mode and dark-mode websites by either using middle-tone color schemes, or by [embedding `media` queries in the SVG](https://timkadlec.com/2013/04/media-queries-within-svg/). +- `icon`: a small image associated with this token. Must be a [data URL](https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/Data_URIs), to help consumers display it quickly while protecting user data. Recommendation: use [optimized SVG](https://codepen.io/tigt/post/optimizing-svgs-in-data-uris), which can result in high-resolution images with only 100s of bytes of [storage cost](https://docs.near.org/concepts/storage/storage-staking). (Note that these storage costs are incurred to the token owner/deployer, but that querying these icons is a very cheap & cacheable read operation for all consumers of the contract and the RPC nodes that serve the data.) Recommendation: create icons that will work well with both light-mode and dark-mode websites by either using middle-tone color schemes, or by [embedding `media` queries in the SVG](https://timkadlec.com/2013/04/media-queries-within-svg/). - `reference`: a link to a valid JSON file containing various keys offering supplementary details on the token. Example: "/ipfs/QmdmQXB2mzChmMeKY47C43LxUdg1NDJ5MWcKMKxDu7RgQm", "https://example.com/token.json", etc. If the information given in this document conflicts with the on-chain attributes, the values in `reference` shall be considered the source of truth. - `reference_hash`: the base64-encoded sha256 hash of the JSON file contained in the `reference` field. This is to guard against off-chain tampering. @@ -120,4 +120,4 @@ The `near-contract-standards` cargo package of the [Near Rust SDK](https://githu Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). -[FT Core]: ../specs/Standards/Tokens/FungibleToken/Core.md \ No newline at end of file +[FT Core]: ../specs/Standards/Tokens/FungibleToken/Core.md diff --git a/neps/nep-0177.md b/neps/nep-0177.md index 1682f0d25..b223eb558 100644 --- a/neps/nep-0177.md +++ b/neps/nep-0177.md @@ -20,7 +20,7 @@ The primary value of non-fungible tokens comes from their metadata. While the [c ## Rationale and alternatives -NEAR's unique [storage staking](https://docs.near.org/docs/concepts/storage-staking) approach makes it feasible to store more data on-chain than other blockchains. This standard leverages this strength for common metadata attributes, and provides a standard way to link to additional offchain data to support rapid community experimentation. +NEAR's unique [storage staking](https://docs.near.org/concepts/storage/storage-staking) approach makes it feasible to store more data on-chain than other blockchains. This standard leverages this strength for common metadata attributes, and provides a standard way to link to additional offchain data to support rapid community experimentation. This standard also provides a `spec` version. This makes it easy for consumers of NFTs, such as marketplaces, to know if they support all the features of a given token. @@ -89,7 +89,7 @@ A new attribute MUST be added to each `Token` struct: For `NFTContractMetadata`: -- `icon`: a small image associated with this contract. Encouraged to be a [data URL](https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/Data_URIs), to help consumers display it quickly while protecting user data. Recommendation: use [optimized SVG](https://codepen.io/tigt/post/optimizing-svgs-in-data-uris), which can result in high-resolution images with only 100s of bytes of [storage cost](https://docs.near.org/docs/concepts/storage-staking). (Note that these storage costs are incurred to the contract deployer, but that querying these icons is a very cheap & cacheable read operation for all consumers of the contract and the RPC nodes that serve the data.) Recommendation: create icons that will work well with both light-mode and dark-mode websites by either using middle-tone color schemes, or by [embedding `media` queries in the SVG](https://timkadlec.com/2013/04/media-queries-within-svg/). +- `icon`: a small image associated with this contract. Encouraged to be a [data URL](https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/Data_URIs), to help consumers display it quickly while protecting user data. Recommendation: use [optimized SVG](https://codepen.io/tigt/post/optimizing-svgs-in-data-uris), which can result in high-resolution images with only 100s of bytes of [storage cost](https://docs.near.org/concepts/storage/storage-staking). (Note that these storage costs are incurred to the contract deployer, but that querying these icons is a very cheap & cacheable read operation for all consumers of the contract and the RPC nodes that serve the data.) Recommendation: create icons that will work well with both light-mode and dark-mode websites by either using middle-tone color schemes, or by [embedding `media` queries in the SVG](https://timkadlec.com/2013/04/media-queries-within-svg/). - `reference`: a link to a valid JSON file containing various keys offering supplementary details on the token. Example: "/ipfs/QmdmQXB2mzChmMeKY47C43LxUdg1NDJ5MWcKMKxDu7RgQm", "https://example.com/token.json", etc. If the information given in this document conflicts with the on-chain attributes, the values in `reference` shall be considered the source of truth. - `reference_hash`: the base64-encoded sha256 hash of the JSON file contained in the `reference` field. This is to guard against off-chain tampering. @@ -154,4 +154,4 @@ It gave those fields the type `string|null` but it was unclear whether it should Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). [NFT Core]: ../specs/Standards/Tokens/NonFungibleToken/Core.md -[FT Metadata]: ../specs/Standards/Tokens/FungibleToken/Metadata.md \ No newline at end of file +[FT Metadata]: ../specs/Standards/Tokens/FungibleToken/Metadata.md diff --git a/specs/Standards/Tokens/FungibleToken/Metadata.md b/specs/Standards/Tokens/FungibleToken/Metadata.md index 8ba698980..81f1a0496 100644 --- a/specs/Standards/Tokens/FungibleToken/Metadata.md +++ b/specs/Standards/Tokens/FungibleToken/Metadata.md @@ -42,7 +42,7 @@ Alice issues a transaction to deploy and initialize the fungible token contract, **Technical calls** -1. `alice` deploys a contract and calls `wbtc::new` with all metadata. If this deploy and initialization were done using [NEAR CLI](https://docs.near.org/docs/tools/near-cli) the command would be: +1. `alice` deploys a contract and calls `wbtc::new` with all metadata. If this deploy and initialization were done using [NEAR CLI](https://docs.near.org/tools/near-cli) the command would be: ```sh near deploy wbtc --wasmFile res/ft.wasm --initFunction new --initArgs '{ @@ -91,7 +91,7 @@ type FungibleTokenMetadata = { **An implementing contract MAY include the following fields on-chain** -- `icon`: a small image associated with this token. Must be a [data URL](https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/Data_URIs), to help consumers display it quickly while protecting user data. Recommendation: use [optimized SVG](https://codepen.io/tigt/post/optimizing-svgs-in-data-uris), which can result in high-resolution images with only 100s of bytes of [storage cost](https://docs.near.org/docs/concepts/storage-staking). (Note that these storage costs are incurred to the token owner/deployer, but that querying these icons is a very cheap & cacheable read operation for all consumers of the contract and the RPC nodes that serve the data.) Recommendation: create icons that will work well with both light-mode and dark-mode websites by either using middle-tone color schemes, or by [embedding `media` queries in the SVG](https://timkadlec.com/2013/04/media-queries-within-svg/). +- `icon`: a small image associated with this token. Must be a [data URL](https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/Data_URIs), to help consumers display it quickly while protecting user data. Recommendation: use [optimized SVG](https://codepen.io/tigt/post/optimizing-svgs-in-data-uris), which can result in high-resolution images with only 100s of bytes of [storage cost](https://docs.near.org/concepts/storage/storage-staking). (Note that these storage costs are incurred to the token owner/deployer, but that querying these icons is a very cheap & cacheable read operation for all consumers of the contract and the RPC nodes that serve the data.) Recommendation: create icons that will work well with both light-mode and dark-mode websites by either using middle-tone color schemes, or by [embedding `media` queries in the SVG](https://timkadlec.com/2013/04/media-queries-within-svg/). - `reference`: a link to a valid JSON file containing various keys offering supplementary details on the token. Example: `/ipfs/QmdmQXB2mzChmMeKY47C43LxUdg1NDJ5MWcKMKxDu7RgQm`, `https://example.com/token.json`, etc. If the information given in this document conflicts with the on-chain attributes, the values in `reference` shall be considered the source of truth. - `reference_hash`: the base64-encoded sha256 hash of the JSON file contained in the `reference` field. This is to guard against off-chain tampering. From 1a3141077341334f8ce18cdf759431e583c39bb5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dami=C3=A1n=20Parrino?= Date: Thu, 28 Jul 2022 11:31:16 -0300 Subject: [PATCH 051/150] Update links (#376) * Update Metadata.md * Update Metadata.md * Update Enumeration.md * Update nep-0178.md * Update ApprovalManagement.md * Update nep-0145.md * Update StorageManagement.md * Update Core.md * Update Enumeration.md * Update ApprovalManagement.md * Update nep-0181.md * Update Core.md * Update nep-0171.md * Update Core.md * Update nep-0245.md --- neps/nep-0145.md | 6 +++--- neps/nep-0171.md | 6 +++--- neps/nep-0178.md | 6 +++--- neps/nep-0181.md | 2 +- neps/nep-0245.md | 4 ++-- specs/Standards/StorageManagement.md | 4 ++-- specs/Standards/Tokens/FungibleToken/Core.md | 4 ++-- specs/Standards/Tokens/MultiToken/ApprovalManagement.md | 6 +++--- specs/Standards/Tokens/MultiToken/Core.md | 4 ++-- specs/Standards/Tokens/MultiToken/Enumeration.md | 2 +- specs/Standards/Tokens/MultiToken/Metadata.md | 4 ++-- .../Standards/Tokens/NonFungibleToken/ApprovalManagement.md | 4 ++-- specs/Standards/Tokens/NonFungibleToken/Core.md | 4 ++-- specs/Standards/Tokens/NonFungibleToken/Enumeration.md | 2 +- specs/Standards/Tokens/NonFungibleToken/Metadata.md | 4 ++-- 15 files changed, 31 insertions(+), 31 deletions(-) diff --git a/neps/nep-0145.md b/neps/nep-0145.md index ccf309c40..478d18338 100644 --- a/neps/nep-0145.md +++ b/neps/nep-0145.md @@ -23,7 +23,7 @@ It allows accounts and contracts to: 4. Withdraw some storage deposit by removing associated account data from the contract and then making a call to remove unused deposit. 5. Unregister an account to recover full storage balance. - [storage staking]: https://docs.near.org/docs/concepts/storage-staking + [storage staking]: https://docs.near.org/concepts/storage/storage-staking ## Rationale and alternatives @@ -80,7 +80,7 @@ Let's follow two users, Alice with account `alice` and Bob with account `bob`, a **Technical calls** -1. Alice queries a view-only method to determine if she already has storage on this contract with `ft::storage_balance_of({"account_id": "alice"})`. Using [NEAR CLI](https://docs.near.org/docs/tools/near-cli) to make this view call, the command would be: +1. Alice queries a view-only method to determine if she already has storage on this contract with `ft::storage_balance_of({"account_id": "alice"})`. Using [NEAR CLI](https://docs.near.org/tools/near-cli) to make this view call, the command would be: near view ft storage_balance_of '{"account_id": "alice"}' @@ -453,4 +453,4 @@ The `near-contract-standards` cargo package of the [Near Rust SDK](https://githu Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). -[FT Core]: ../specs/Standards/Tokens/FungibleToken/Core.md \ No newline at end of file +[FT Core]: ../specs/Standards/Tokens/FungibleToken/Core.md diff --git a/neps/nep-0171.md b/neps/nep-0171.md index 18fcf6b62..400df70bc 100644 --- a/neps/nep-0171.md +++ b/neps/nep-0171.md @@ -370,10 +370,10 @@ Please feel free to open pull requests for extending the events standard detaile Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). [ERC-721]: https://eips.ethereum.org/EIPS/eip-721 -[storage staking]: https://docs.near.org/docs/concepts/storage-staking -[gas]: https://docs.near.org/docs/concepts/gas +[storage staking]: https://docs.near.org/concepts/storage/storage-staking +[gas]: https://docs.near.org/concepts/basics/transactions/gas [Metadata]: ../specs/Standards/Tokens/NonFungibleToken/Metadata.md [Approval Management]: ../specs/Standards/Tokens/NonFungibleToken/ApprovalManagement.md [FT core]: ../specs/Standards/Tokens/FungibleToken/Core.md [Storage Management]: ../specs/Standards/StorageManagement.md -[NFT Enumeration]: ../specs/Standards/Tokens/NonFungibleToken/Enumeration.md \ No newline at end of file +[NFT Enumeration]: ../specs/Standards/Tokens/NonFungibleToken/Enumeration.md diff --git a/neps/nep-0178.md b/neps/nep-0178.md index e4b4655b5..9ff177cef 100644 --- a/neps/nep-0178.md +++ b/neps/nep-0178.md @@ -65,7 +65,7 @@ Alice approves Bob to transfer her token. **Technical calls** -1. Alice calls `nft::nft_approve({ "token_id": "1", "account_id": "bob" })`. She attaches 1 yoctoⓃ, (.000000000000000000000001Ⓝ). Using [NEAR CLI](https://docs.near.org/docs/tools/near-cli) to make this call, the command would be: +1. Alice calls `nft::nft_approve({ "token_id": "1", "account_id": "bob" })`. She attaches 1 yoctoⓃ, (.000000000000000000000001Ⓝ). Using [NEAR CLI](https://docs.near.org/tools/near-cli) to make this call, the command would be: near call nft nft_approve \ '{ "token_id": "1", "account_id": "bob" }' \ @@ -119,7 +119,7 @@ Alice approves Market to transfer one of her tokens and passes `msg` so that NFT "msg": "{\"action\": \"list\", \"price\": \"100\", \"token\": \"nDAI\" }" }' --accountId alice --depositYocto 1 - At this point, near-cli will hang until the cross-contract call chain fully resolves, which would also be true if Alice used a Market frontend using [near-api-js](https://docs.near.org/docs/develop/front-end/near-api-js). Alice's part is done, though. The rest happens behind the scenes. + At this point, near-cli will hang until the cross-contract call chain fully resolves, which would also be true if Alice used a Market frontend using [near-api-js](https://docs.near.org/tools/near-api-js/quick-reference). Alice's part is done, though. The rest happens behind the scenes. 2. `nft` schedules a call to `nft_on_approve` on `market`. Using near-cli notation for easy cross-reference with the above, this would look like: @@ -471,4 +471,4 @@ Copyright and related rights waived via [CC0](https://creativecommons.org/public [ERC-721]: https://eips.ethereum.org/EIPS/eip-721 [NFT Core]: ../specs/Standards/Tokens/NonFungibleToken/Core.md [Storage Management]: ../specs/Standards/StorageManagement.md -[FT Core]: ../specs/Standards/Tokens/FungibleToken/Core.md \ No newline at end of file +[FT Core]: ../specs/Standards/Tokens/FungibleToken/Core.md diff --git a/neps/nep-0181.md b/neps/nep-0181.md index bd81c3d1d..cc1e990c4 100644 --- a/neps/nep-0181.md +++ b/neps/nep-0181.md @@ -92,4 +92,4 @@ At the time of this writing, the specialized collections in the `near-sdk` Rust Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). [ERC-721]: https://eips.ethereum.org/EIPS/eip-721 -[storage]: https://docs.near.org/docs/concepts/storage-staking +[storage]: https://docs.near.org/concepts/storage/storage-staking diff --git a/neps/nep-0245.md b/neps/nep-0245.md index f49863c92..8713bcf99 100644 --- a/neps/nep-0245.md +++ b/neps/nep-0245.md @@ -575,8 +575,8 @@ Copyright and related rights waived via [CC0](https://creativecommons.org/public [ERC-721]: https://eips.ethereum.org/EIPS/eip-721 [ERC-1155]: https://eips.ethereum.org/EIPS/eip-1155 -[storage staking]: https://docs.near.org/docs/concepts/storage-staking -[gas]: https://docs.near.org/docs/concepts/gas +[storage staking]: https://docs.near.org/concepts/storage/storage-staking +[gas]: https://docs.near.org/concepts/basics/transactions/gas [MT Metadata]: ../specs/Standards/Tokens/MultiToken/Metadata.md [NFT Core]: ../specs/Standards/Tokens/NonFungibleToken/Core.md [Approval Management]: ../specs/Standards/MultiToken/ApprovalManagement.md diff --git a/specs/Standards/StorageManagement.md b/specs/Standards/StorageManagement.md index 466934489..712ab73f9 100644 --- a/specs/Standards/StorageManagement.md +++ b/specs/Standards/StorageManagement.md @@ -12,7 +12,7 @@ NEAR uses [storage staking] which means that a contract account must have suffic 4. Withdraw some storage deposit by removing associated account data from the contract and then making a call to remove unused deposit. 5. Unregister an account to recover full storage balance. - [storage staking]: https://docs.near.org/docs/concepts/storage-staking + [storage staking]: https://docs.near.org/concepts/storage/storage-staking Prior art: @@ -67,7 +67,7 @@ Let's follow two users, Alice with account `alice` and Bob with account `bob`, a **Technical calls** -1. Alice queries a view-only method to determine if she already has storage on this contract with `ft::storage_balance_of({"account_id": "alice"})`. Using [NEAR CLI](https://docs.near.org/docs/tools/near-cli) to make this view call, the command would be: +1. Alice queries a view-only method to determine if she already has storage on this contract with `ft::storage_balance_of({"account_id": "alice"})`. Using [NEAR CLI](https://docs.near.org/tools/near-cli) to make this view call, the command would be: near view ft storage_balance_of '{"account_id": "alice"}' diff --git a/specs/Standards/Tokens/FungibleToken/Core.md b/specs/Standards/Tokens/FungibleToken/Core.md index 440236398..72fe77c0e 100644 --- a/specs/Standards/Tokens/FungibleToken/Core.md +++ b/specs/Standards/Tokens/FungibleToken/Core.md @@ -48,11 +48,11 @@ There are a few concepts in the scenarios above: - **Balance**: an amount of tokens. - **Transfer**: an action that moves some amount from one account to another account, either an externally owned account or a contract account. - **Transfer and call**: an action that moves some amount from one account to a contract account where the receiver calls a method. -- **Storage amount**: the amount of storage used for an account to be "registered" in the fungible token. This amount is denominated in Ⓝ, not bytes, and represents the [storage staked](https://docs.near.org/docs/concepts/storage-staking). +- **Storage amount**: the amount of storage used for an account to be "registered" in the fungible token. This amount is denominated in Ⓝ, not bytes, and represents the [storage staked](https://docs.near.org/concepts/storage/storage-staking). Note that precision (the number of decimal places supported by a given token) is not part of this core standard, since it's not required to perform actions. The minimum value is always 1 token. See the [Fungible Token Metadata Standard](Metadata.md) to learn how to support precision/decimals in a standardized way. -Given that multiple users will use a Fungible Token contract, and their activity will result in an increased [storage staking](https://docs.near.org/docs/concepts/storage-staking) burden for the contract's account, this standard is designed to interoperate nicely with [the Account Storage standard](../../StorageManagement.md) for storage deposits and refunds. +Given that multiple users will use a Fungible Token contract, and their activity will result in an increased [storage staking](https://docs.near.org/concepts/storage/storage-staking) burden for the contract's account, this standard is designed to interoperate nicely with [the Account Storage standard](../../StorageManagement.md) for storage deposits and refunds. ### Example scenarios diff --git a/specs/Standards/Tokens/MultiToken/ApprovalManagement.md b/specs/Standards/Tokens/MultiToken/ApprovalManagement.md index 5c503db01..6ecf60e00 100644 --- a/specs/Standards/Tokens/MultiToken/ApprovalManagement.md +++ b/specs/Standards/Tokens/MultiToken/ApprovalManagement.md @@ -59,7 +59,7 @@ Alice approves Bob to transfer her tokens. **Technical calls** -1. Alice calls `mt::mt_approve({ "token_ids": ["1","2"], amounts:["1","100"], "account_id": "bob" })`. She attaches 1 yoctoⓃ, (.000000000000000000000001Ⓝ). Using [NEAR CLI](https://docs.near.org/docs/tools/near-cli) to make this call, the command would be: +1. Alice calls `mt::mt_approve({ "token_ids": ["1","2"], amounts:["1","100"], "account_id": "bob" })`. She attaches 1 yoctoⓃ, (.000000000000000000000001Ⓝ). Using [NEAR CLI](https://docs.near.org/tools/near-cli) to make this call, the command would be: near call mt mt_approve \ '{ "token_ids": ["1","2"], amounts: ["1","100"], "account_id": "bob" }' \ @@ -98,7 +98,7 @@ Alice approves Market to transfer some of her tokens and passes `msg` so that MT "msg": "{\"action\": \"list\", \"price\": [\"100\",\"50\"],\"token\": \"nDAI\" }" }' --accountId alice --amount .000000000000000000000001 - At this point, near-cli will hang until the cross-contract call chain fully resolves, which would also be true if Alice used a Market frontend using [near-api-js](https://docs.near.org/docs/develop/front-end/near-api-js). Alice's part is done, though. The rest happens behind the scenes. + At this point, near-cli will hang until the cross-contract call chain fully resolves, which would also be true if Alice used a Market frontend using [near-api-js](https://docs.near.org/tools/near-api-js/quick-reference). Alice's part is done, though. The rest happens behind the scenes. 2. `mt` schedules a call to `mt_on_approve` on `market`. Using near-cli notation for easy cross-reference with the above, this would look like: @@ -500,4 +500,4 @@ Further note that there is no parallel `mt_on_revoke` when revoking either a sin ### No incurred cost for core MT behavior -MT contracts should be implemented in a way to avoid extra gas fees for serialization & deserialization of `approved_account_ids` for calls to `mt_*` methods other than `mt_tokens`. See `near-contract-standards` [implementation of `ft_metadata` using `LazyOption`](https://github.com/near/near-sdk-rs/blob/c2771af7fdfe01a4e8414046752ee16fb0d29d39/examples/fungible-token/ft/src/lib.rs#L71) as a reference example. \ No newline at end of file +MT contracts should be implemented in a way to avoid extra gas fees for serialization & deserialization of `approved_account_ids` for calls to `mt_*` methods other than `mt_tokens`. See `near-contract-standards` [implementation of `ft_metadata` using `LazyOption`](https://github.com/near/near-sdk-rs/blob/c2771af7fdfe01a4e8414046752ee16fb0d29d39/examples/fungible-token/ft/src/lib.rs#L71) as a reference example. diff --git a/specs/Standards/Tokens/MultiToken/Core.md b/specs/Standards/Tokens/MultiToken/Core.md index c737133f0..4d3bf3686 100644 --- a/specs/Standards/Tokens/MultiToken/Core.md +++ b/specs/Standards/Tokens/MultiToken/Core.md @@ -390,8 +390,8 @@ function mt_on_transfer( [ERC-721]: https://eips.ethereum.org/EIPS/eip-721 [ERC-1155]: https://eips.ethereum.org/EIPS/eip-1155 - [storage staking]: https://docs.near.org/docs/concepts/storage-staking - [gas]: https://docs.near.org/docs/concepts/gas + [storage staking]: https://docs.near.org/concepts/storage/storage-staking + [gas]: https://docs.near.org/concepts/basics/transactions/gas [Metadata]: Metadata.md [NFT]: ../NonFungibleToken/Core.md [Approval Management]: ApprovalManagement.md diff --git a/specs/Standards/Tokens/MultiToken/Enumeration.md b/specs/Standards/Tokens/MultiToken/Enumeration.md index 3ad56a843..d019732e8 100644 --- a/specs/Standards/Tokens/MultiToken/Enumeration.md +++ b/specs/Standards/Tokens/MultiToken/Enumeration.md @@ -81,4 +81,4 @@ function mt_tokens_base_metadata_all( At the time of this writing, the specialized collections in the `near-sdk` Rust crate are iterable, but not all of them have implemented an `iter_from` solution. There may be efficiency gains for large collections and contract developers are encouraged to test their data structures with a large amount of entries. [ERC-721]: https://eips.ethereum.org/EIPS/eip-721 - [storage]: https://docs.near.org/docs/concepts/storage-staking + [storage]: https://docs.near.org/concepts/storage/storage-staking diff --git a/specs/Standards/Tokens/MultiToken/Metadata.md b/specs/Standards/Tokens/MultiToken/Metadata.md index 7c2a640de..33668ba93 100644 --- a/specs/Standards/Tokens/MultiToken/Metadata.md +++ b/specs/Standards/Tokens/MultiToken/Metadata.md @@ -14,7 +14,7 @@ An interface for a multi token's metadata. The goal is to keep the metadata futu The primary value of tokens comes from their metadata. While the [core standard](Core.md) provides the minimum interface that can be considered a multi token, most artists, developers, and dApps will want to associate more data with each token, and will want a predictable way to interact with any MT's metadata. -NEAR's unique [storage staking](https://docs.near.org/docs/concepts/storage-staking) approach makes it feasible to store more data on-chain than other blockchains. This standard leverages this strength for common metadata attributes, and provides a standard way to link to additional offchain data to support rapid community experimentation. +NEAR's unique [storage staking](https://docs.near.org/concepts/storage/storage-staking) approach makes it feasible to store more data on-chain than other blockchains. This standard leverages this strength for common metadata attributes, and provides a standard way to link to additional offchain data to support rapid community experimentation. This standard also provides a `spec` version. This makes it easy for consumers of Multi Tokens, such as marketplaces, to know if they support all the features of a given token. @@ -103,7 +103,7 @@ For `MTBaseTokenMetadata`: ### An implementing contract MAY include the following fields on-chain For `MTBaseTokenMetadata`: - `symbol`: the abbreviated symbol of the contract, like MOCHI or MV3 -- `icon`: a small image associated with this contract. Encouraged to be a [data URL](https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/Data_URIs), to help consumers display it quickly while protecting user data. Recommendation: use [optimized SVG](https://codepen.io/tigt/post/optimizing-svgs-in-data-uris), which can result in high-resolution images with only 100s of bytes of [storage cost](https://docs.near.org/docs/concepts/storage-staking). (Note that these storage costs are incurred to the contract deployer, but that querying these icons is a very cheap & cacheable read operation for all consumers of the contract and the RPC nodes that serve the data.) Recommendation: create icons that will work well with both light-mode and dark-mode websites by either using middle-tone color schemes, or by [embedding `media` queries in the SVG](https://timkadlec.com/2013/04/media-queries-within-svg/). +- `icon`: a small image associated with this contract. Encouraged to be a [data URL](https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/Data_URIs), to help consumers display it quickly while protecting user data. Recommendation: use [optimized SVG](https://codepen.io/tigt/post/optimizing-svgs-in-data-uris), which can result in high-resolution images with only 100s of bytes of [storage cost](https://docs.near.org/concepts/storage/storage-staking). (Note that these storage costs are incurred to the contract deployer, but that querying these icons is a very cheap & cacheable read operation for all consumers of the contract and the RPC nodes that serve the data.) Recommendation: create icons that will work well with both light-mode and dark-mode websites by either using middle-tone color schemes, or by [embedding `media` queries in the SVG](https://timkadlec.com/2013/04/media-queries-within-svg/). - `reference`: a link to a valid JSON file containing various keys offering supplementary details on the token. Example: "/ipfs/QmdmQXB2mzChmMeKY47C43LxUdg1NDJ5MWcKMKxDu7RgQm", etc. If the information given in this document conflicts with the on-chain attributes, the values in `reference` shall be considered the source of truth. - `reference_hash`: the base64-encoded sha256 hash of the JSON file contained in the `reference` field. This is to guard against off-chain tampering. - `copies`: The number of tokens with this set of metadata or `media` known to exist at time of minting. Supply is a more accurate current reflection. diff --git a/specs/Standards/Tokens/NonFungibleToken/ApprovalManagement.md b/specs/Standards/Tokens/NonFungibleToken/ApprovalManagement.md index 2288cbc73..e7219dd96 100644 --- a/specs/Standards/Tokens/NonFungibleToken/ApprovalManagement.md +++ b/specs/Standards/Tokens/NonFungibleToken/ApprovalManagement.md @@ -57,7 +57,7 @@ Alice approves Bob to transfer her token. **Technical calls** -1. Alice calls `nft::nft_approve({ "token_id": "1", "account_id": "bob" })`. She attaches 1 yoctoⓃ, (.000000000000000000000001Ⓝ). Using [NEAR CLI](https://docs.near.org/docs/tools/near-cli) to make this call, the command would be: +1. Alice calls `nft::nft_approve({ "token_id": "1", "account_id": "bob" })`. She attaches 1 yoctoⓃ, (.000000000000000000000001Ⓝ). Using [NEAR CLI](https://docs.near.org/tools/near-cli) to make this call, the command would be: ```bash near call nft nft_approve \ @@ -121,7 +121,7 @@ Alice approves Market to transfer one of her tokens and passes `msg` so that NFT }' --accountId alice --depositYocto 1 ``` - At this point, near-cli will hang until the cross-contract call chain fully resolves, which would also be true if Alice used a Market frontend using [near-api-js](https://docs.near.org/docs/develop/front-end/near-api-js). Alice's part is done, though. The rest happens behind the scenes. + At this point, near-cli will hang until the cross-contract call chain fully resolves, which would also be true if Alice used a Market frontend using [near-api-js](https://docs.near.org/tools/near-api-js/quick-reference). Alice's part is done, though. The rest happens behind the scenes. 2. `nft` schedules a call to `nft_on_approve` on `market`. Using near-cli notation for easy cross-reference with the above, this would look like: diff --git a/specs/Standards/Tokens/NonFungibleToken/Core.md b/specs/Standards/Tokens/NonFungibleToken/Core.md index 3e9948c38..749773e89 100644 --- a/specs/Standards/Tokens/NonFungibleToken/Core.md +++ b/specs/Standards/Tokens/NonFungibleToken/Core.md @@ -208,8 +208,8 @@ function nft_on_transfer( * **2021-07-16**: updated `nft_transfer_call` argument `approval_id` to be type `number|null` instead of `string|null`. As stated, approval IDs are not expected to exceed the JSON limit of 2^53. [ERC-721]: https://eips.ethereum.org/EIPS/eip-721 - [storage staking]: https://docs.near.org/docs/concepts/storage-staking - [gas]: https://docs.near.org/docs/concepts/gas + [storage staking]: https://docs.near.org/concepts/storage/storage-staking + [gas]: https://docs.near.org/concepts/basics/transactions/gas [Metadata]: Metadata.md [Approval Management]: ApprovalManagement.md diff --git a/specs/Standards/Tokens/NonFungibleToken/Enumeration.md b/specs/Standards/Tokens/NonFungibleToken/Enumeration.md index 43910a5db..47374522f 100644 --- a/specs/Standards/Tokens/NonFungibleToken/Enumeration.md +++ b/specs/Standards/Tokens/NonFungibleToken/Enumeration.md @@ -73,4 +73,4 @@ function nft_tokens_for_owner( At the time of this writing, the specialized collections in the `near-sdk` Rust crate are iterable, but not all of them have implemented an `iter_from` solution. There may be efficiency gains for large collections and contract developers are encouraged to test their data structures with a large amount of entries. [ERC-721]: https://eips.ethereum.org/EIPS/eip-721 - [storage]: https://docs.near.org/docs/concepts/storage-staking + [storage]: https://docs.near.org/concepts/storage/storage-staking diff --git a/specs/Standards/Tokens/NonFungibleToken/Metadata.md b/specs/Standards/Tokens/NonFungibleToken/Metadata.md index ed11c9e84..2e324e2e6 100644 --- a/specs/Standards/Tokens/NonFungibleToken/Metadata.md +++ b/specs/Standards/Tokens/NonFungibleToken/Metadata.md @@ -12,7 +12,7 @@ An interface for a non-fungible token's metadata. The goal is to keep the metada The primary value of non-fungible tokens comes from their metadata. While the [core standard](Core.md) provides the minimum interface that can be considered a non-fungible token, most artists, developers, and dApps will want to associate more data with each NFT, and will want a predictable way to interact with any NFT's metadata. -NEAR's unique [storage staking](https://docs.near.org/docs/concepts/storage-staking) approach makes it feasible to store more data on-chain than other blockchains. This standard leverages this strength for common metadata attributes, and provides a standard way to link to additional offchain data to support rapid community experimentation. +NEAR's unique [storage staking](https://docs.near.org/concepts/storage/storage-staking) approach makes it feasible to store more data on-chain than other blockchains. This standard leverages this strength for common metadata attributes, and provides a standard way to link to additional offchain data to support rapid community experimentation. This standard also provides a `spec` version. This makes it easy for consumers of NFTs, such as marketplaces, to know if they support all the features of a given token. @@ -79,7 +79,7 @@ A new attribute MUST be added to each `Token` struct: For `NFTContractMetadata`: -- `icon`: a small image associated with this contract. Encouraged to be a [data URL](https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/Data_URIs), to help consumers display it quickly while protecting user data. Recommendation: use [optimized SVG](https://codepen.io/tigt/post/optimizing-svgs-in-data-uris), which can result in high-resolution images with only 100s of bytes of [storage cost](https://docs.near.org/docs/concepts/storage-staking). (Note that these storage costs are incurred to the contract deployer, but that querying these icons is a very cheap & cacheable read operation for all consumers of the contract and the RPC nodes that serve the data.) Recommendation: create icons that will work well with both light-mode and dark-mode websites by either using middle-tone color schemes, or by [embedding `media` queries in the SVG](https://timkadlec.com/2013/04/media-queries-within-svg/). +- `icon`: a small image associated with this contract. Encouraged to be a [data URL](https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/Data_URIs), to help consumers display it quickly while protecting user data. Recommendation: use [optimized SVG](https://codepen.io/tigt/post/optimizing-svgs-in-data-uris), which can result in high-resolution images with only 100s of bytes of [storage cost](https://docs.near.org/concepts/storage/storage-staking). (Note that these storage costs are incurred to the contract deployer, but that querying these icons is a very cheap & cacheable read operation for all consumers of the contract and the RPC nodes that serve the data.) Recommendation: create icons that will work well with both light-mode and dark-mode websites by either using middle-tone color schemes, or by [embedding `media` queries in the SVG](https://timkadlec.com/2013/04/media-queries-within-svg/). - `reference`: a link to a valid JSON file containing various keys offering supplementary details on the token. Example: `/ipfs/QmdmQXB2mzChmMeKY47C43LxUdg1NDJ5MWcKMKxDu7RgQm`, `https://example.com/token.json`, etc. If the information given in this document conflicts with the on-chain attributes, the values in `reference` shall be considered the source of truth. - `reference_hash`: the base64-encoded sha256 hash of the JSON file contained in the `reference` field. This is to guard against off-chain tampering. From 6cfc0e15a0e8846c535617ccc63ea55702b9052f Mon Sep 17 00:00:00 2001 From: ori-near <110252255+ori-near@users.noreply.github.com> Date: Fri, 29 Jul 2022 11:00:26 -0700 Subject: [PATCH 052/150] Update nep-0001.md (#377) Updated NEP-001 with more details about the process, roles & responsibilities, and the NEP templates. --- neps/nep-0001.md | 425 +++++++++++++---------------------------------- 1 file changed, 117 insertions(+), 308 deletions(-) diff --git a/neps/nep-0001.md b/neps/nep-0001.md index fbe1e8539..d8b2ac37f 100644 --- a/neps/nep-0001.md +++ b/neps/nep-0001.md @@ -1,395 +1,204 @@ --- NEP: 1 -Title: NEP Purpose and Guidelines -Author: Jay Logelin +Title: NEP Purpose and Guideline +Authors: Bowen W. ; Austin Baggio ; Ori A. ; DiscussionsTo: https://github.com/near/NEPs/pull/333 Status: Living Type: Process Created: 03-Mar-2022 --- -## What is an NEP? -NEP stands for Near Enhancement Proposal. An NEP is a design -document providing information to the Near community, or describing -a new feature for the Near protocol, Smart Contract standards, or it's environment. -The NEP should provide a concise technical specification of the feature and a -rationale for the feature. +## What is a NEAR Enhancement Proposal (NEP)? +A NEP is a design document for providing information to the NEAR community or describing a new feature for the NEAR protocol or Smart Contract standards. NEP’s should provide a concise technical specification and a rationale for the feature. -NEPs are intended to be the primary mechanism for proposing new features, interfacing -with the community on an issue and documenting design decisions that have -been integrated into Near's runtime or Smart Contract ecosystem. +NEPs are intended to be the primary mechanism for proposing new features, coordinating formal feedback, and documenting design decisions that were integrated into NEAR’s runtime or Smart Contract ecosystem. -As such, the NEP author is responsible for building consensus within the community and documenting dissenting opinions. +As such, A NEP’s author is responsible for building consensus within the community and documenting dissenting opinions. -## NEP Audience +## NEP Participants +Everyone in the community is welcome to propose, discuss, and review ideas to improve the NEAR protocol and standards.The typical primary audience for NEPs are the core developers of the NEAR reference implementations and NEAR Smart Contract developers. -The typical primary audience for NEPs are the core developers of the Near -reference implementations, and Near Smart Contract developers. - -However, other parts of the Near community may also choose to use the process -(particularly for Informational NEPs) to document expected API conventions and -to manage complex design coordination problems that require collaboration across -multiple projects. +The NEAR working groups are responsible for coordinating the public review of NEPs and have the authority to accept or reject changes. ## NEP Types +There are two kinds of NEPs: -There are three kinds of NEP: - -1. A **Standards Track** NEP describes a new feature or implementation - for the Near protocol or Near Smart Contract implementation standards. - -2. An **Informational** NEP describes a Near design issue, or - provides general guidelines or information to the Near community, - but does not propose a new feature. Informational NEPs do not - necessarily represent a Near community consensus or - recommendation, so users and implementers can ignore - Informational NEPs or follow their advice. - -3. A **Process** NEP describes a process surrounding Near, or - proposes a change to (or an event in) a process. Process NEPs are - like Standards Track NEPs but apply to areas other than the Near - platform itself. They may propose an implementation, but not to - Near's codebase; they often require community consensus; unlike - Informational NEPs, they are more than recommendations, and users - are typically not free to ignore them. Examples include - procedures, guidelines, changes to the decision-making process, and - changes to the tools or environment used in Near development. - Any meta-NEP is also considered a Process NEP. +1. A **Standards** NEP describes a new NEAR Smart Contract implementation standard. +2. A **Protocol** NEP describes a new feature for the NEAR protocol. ## NEP Workflow +### Start with an idea for NEAR +The NEP process begins with a new idea for the NEAR ecosystem. A single NEP should contain a single key proposal or new idea. -### Start with an idea for Near - -The NEP process begins with a new idea for the Near ecosystem. It is -recommended that a single NEP contain a single key proposal or new -idea. - -Each NEP must have a torch-bearer: someone who writes the NEP using the style -and format described below, shepherds the discussions in the appropriate -forums, and attempts to build community consensus around the idea. This NEP Author -should first attempt to ascertain whether the idea is -NEP-able. - -Vetting an idea publicly before going as far as writing an NEP is meant -to save the potential author time. Many ideas have been brought -forward for changing Near that have been rejected for various -reasons. Asking the Near community first if an idea is original -helps prevent too much time being spent on something that is -guaranteed to be rejected based on prior discussions. It also helps to make sure -the idea is applicable to the entire community and not just the author. -Just because an idea sounds good to the author does not -mean it will work for most people in most areas where Near is used. - -In general the process is: - -* Sign up for the [governance site](https://gov.near.org/) and make a post to the -appropriate section. For instance, during the ideation phase of a standard, one might -start a new conversation in the -[Development » Standards section](https://gov.near.org/c/dev/standards/29). -The other suggested category in the governance forum is the -[Development » Proposals section](https://gov.near.org/c/dev/proposals/68). - -* The forum has comment threading which allows the community and NEAR Collective -to ideate, ask questions, wrestle with approaches, etc. If more immediate responses -are desired, consider bringing the conversation [to Discord](https://near.chat). - -Once the torch-bearer has asked the Near community as to whether an -idea has any chance of acceptance, a draft NEP should be presented to -the appropriate venue mentioned above. This gives the author a chance to flesh out the draft -NEP to make properly formatted, of high quality, and to address -initial concerns about the proposal. +Each NEP must have an author: someone who writes the NEP using the style and format described below, shepherds the discussions in the appropriate forums, and attempts to build community consensus around the idea. +Before submitting a NEP, the author should first attempt to ascertain whether the idea is NEP-able. Vetting an idea publicly before writing a NEP saves the potential author time. Asking the NEAR community first if an idea is original helps prevent effort on something that is guaranteed to be rejected based on prior discussions. It also helps ensure the idea is applicable to the entire community. Just because an idea sounds good to the author does not mean it will work for most people in most use cases. -## Submitting an NEP +In general, the process to socialize an idea is: -Following the above initial discussions, the workflow, the proposal should be -submitted as a `draft` NEP via a GitHub pull request. The draft must be written -in NEP style as described below, else it will fail review immediately (although -minor errors may be corrected by the editors). +- **Check prior proposals:** Many ideas for changing NEAR come up frequently. Please search the [governance](https://gov.near.org/)[ ](https://gov.near.org/)[site](https://gov.near.org/) forums and NEPs in this repo before proposing something new. +- **Share the idea:** Join the [governance](https://gov.near.org/)[ ](https://gov.near.org/)[site](https://gov.near.org/) and make a post to the appropriate section. For instance, during the ideation phase of a standard, one might start a new conversation in the [Development](https://gov.near.org/c/dev/standards/29)[ » ](https://gov.near.org/c/dev/standards/29)[Standards](https://gov.near.org/c/dev/standards/29)[ ](https://gov.near.org/c/dev/standards/29)[section](https://gov.near.org/c/dev/standards/29). Similarly, during the ideation phase of a proposal to change the protocol, one might start a new conversation in the [Development](https://gov.near.org/c/dev/proposals/68)[ » ](https://gov.near.org/c/dev/proposals/68)[Proposals](https://gov.near.org/c/dev/proposals/68)[ ](https://gov.near.org/c/dev/proposals/68)[section](https://gov.near.org/c/dev/proposals/68). +- **Get feedback:** The forum has comment threading which allows the community and NEAR Collective to ideate, ask questions, wrestle with approaches, etc. If more immediate responses are desired, consider bringing the conversation [to](https://near.chat/)[ ](https://near.chat/)[Discord](https://near.chat/). -The standard NEP workflow is: +### Submit a NEP +Following the above initial discussions, the author should submit a draft NEP via a GitHub pull request. The draft must follow the NEP style as described below, else it will fail review immediately (although the moderators may correct minor errors). -* You, the NEP author, fork the `NEPs repository`, and create a file named - ``neps/nep-9999.md`` that contains your new NEP. Use "9999" as your draft NEP - number. +The NEP workflow is: -* Your first update will be to change the nep filename to match the Pull Request - number. For example, if the PR is `305`, the NEP should be `neps/nep-0305.md`. - -* In the "Type:" header field, enter "Standards Track", - "Informational", or "Process" as appropriate, and for the "Status:" - field enter "Draft". For full details, see `NEP Header Preamble`. - -* Push this to your GitHub fork and submit a pull request. - -* The NEP editors review your PR for structure, formatting, and other - errors. For a markdown-formatted NEP, `nep-template.md` is provided as a template. +- You, the NEP author, fork the NEPs repository, and create a file named neps/nep-9999.md that contains your new NEP. Use “9999” as your draft NEP number. +- Your first update is to change the nep filename to match the Pull Request number. For example, if the PR is 305, the NEP should be neps/nep-0305.md. +- In the “Type:” header field, enter “Standards” or “Protocol” as appropriate, and for the “Status:” field enter “Draft”. For full details, see NEP Header Preamble. +- Push this to your GitHub fork and submit a pull request. +- The NEP moderators review your PR for structure, formatting, and other errors. For a markdown-formatted NEP, nep-template.md is provided as a template. Approval criteria are: + - The content is sound and complete. The ideas must make technical sense. The moderators do not consider whether they seem likely for acceptance. + - The title accurately describes the content. + - The language (spelling, grammar, sentence structure, etc.) and code style are correct and conformant. +- If the NEP is not ready for approval, a moderator will send it back to the author for revision, with specific instructions in the pull request. The review by NEP moderators is expected to finish within one week. +- Once the NEP moderators agree that the PR is ready for review, the moderators notify the Approver (Community Working Group) to assign a team of at least two reviewers (subject matter experts) to review the NEP. The reviewers will review the technical details of the proposal and assess its merits. They may ask clarification questions, request changes, or reject the proposal. The author of the proposal is free to revise the proposal and re-request reviews from reviewers. +- If a proposal is in the review stage for more than two months, it is automatically rejected. To re-open the proposal, the author must start over with the NEP process again. +- Once the reviewers agree that the proposal is overall beneficial for the NEAR ecosystem, they will ask the author to present the proposal to the working group, where it can enter the final voting stage. If the vote passes, then the proposal is considered accepted. - * It is sound and complete. The ideas must make technical sense. The - editors do not consider whether they seem likely to be accepted. - * The title accurately describes the content. - * The NEP's language (spelling, grammar, sentence structure, etc.) - and code style should be correct and conformant. - - If the NEP isn't ready for approval, an editor will send it back to - the author for revision, with specific instructions in the pull request. +### NEP Maintenance +In general, NEPs are no longer modified after they have reached the Final state. -Once the review process is complete, and the NEP editors approve it (note that -this is *not* the same as accepting your NEP!), they will squash commit your -pull request onto main. +## NEP Life Cycle -The NEP editors will not unreasonably deny publication of an NEP. Reasons for -denying NEP status include duplication of effort, being technically unsound, -not providing proper motivation or addressing backwards compatibility, or not -in keeping with the NEAR philosophy. +![NEP Process](https://user-images.githubusercontent.com/110252255/181816298-9945206e-4041-4499-85f7-51e3d1e493d0.png) -As updates are necessary, the NEP author can check in new versions if they -(or a collaborating developer) have write access to the `NEP repository`. -Standards Track NEPs consist of two parts, a design document and a -reference implementation. It is generally recommended that at least a -prototype implementation be co-developed with the NEP, as ideas that sound -good in principle sometimes turn out to be impractical when subjected to the -test of implementation. +A given NEP can have one of the following states: -## NEP Maintenance +- **Draft**: The first formally tracked stage of a NEP in development. A NEP is merged by a NEP Moderator into the NEP repository when properly formatted. +- **Review**: A NEP moderator marks a NEP as ready for Subject Matter Experts Review. + - If the NEP is not approved within two months, it is automatically rejected. +- **Voting**: This is the final voting period for a NEP. The working group will vote on whether to accept or reject the NEP. This period is limited to two weeks. If during this period necessary normative changes are required, the NEP will revert back to Review. +- **Approved:** If the working group votes to approve, they will move the NEP to Approved. Once approved, Standards NEPs exist in a state of finality and should only be updated to correct errata and add non-normative clarifications. +- **Rejected:** If the working group votes to reject, they will move the NEP to Rejected. +- **Living** - A special status for NEPs that are designed to be continually updated and not reach a state of finality. This includes most notably NEP-0001. -Informational and Process NEPs may be updated over time to reflect changes to -development practices and other details. The precise process followed in these -cases will depend on the nature and purpose of the NEP being updated. In general, -Standards track NEP's are no longer modified after they have reached the Final state. +## NEP Roles and Responsibilities +The NEP process has various roles and responsibilities. -## NEP Process State -The following is the standardization process for all NEPs in all tracks: +![author](https://user-images.githubusercontent.com/110252255/181816534-2f92b073-79e2-4e8d-b5b9-b10824958acd.png) +**Author** +*Anyone can participate* -![NEP Status Flow Diagram](assets/nep-0001/NEP-flow.png) +- Writes proposal following the standards +- Submits proposal with prototype when ready for review and changes the status to “Draft” +- Addresses comments +- Presents to working group and incorporates necessary changes +- Executes implementation once approved +- Provides reference implementation and documentation once approved -**Idea** - An idea that is pre-draft. This is not tracked within the NEP Repository. +![Moderator](https://user-images.githubusercontent.com/110252255/181816650-b1610c0e-6d32-4d2a-a34e-877c702139bd.png) +**Moderator** +*Assigned by working group* -**Draft** - The first formally tracked stage of an NEP in development. An NEP is merged by an NEP Editor into the NEP repository when properly formatted. +- Ensures proposal meets standards + - If proposal needs revisions, provides comments on improvements and keeps status as “Draft” + - If proposal does not meet standards, changes status to “Rejected” + - If proposal is ready for review, changes status to “Review” +- Coordinates working group to assign reviewers and review proposals +- Does not assess the technical feasibility or writes any parts of the proposal -**Review** - An NEP Author marks an NEP as ready for and requesting Peer Review. +![Reviewer](https://user-images.githubusercontent.com/110252255/181816664-a9485ea6-e774-4999-b11d-dc8be6b08f87.png) +**Reviewer** (Subject Matter Experts) +*Assigned by working group* -**Last Call** - This is the final review window for an NEP before moving to `Final`. An NEP editor will assign `Last Call` status and set a review end date (`last-call-deadline`), typically 14 days later. +- Gives feedback on proposals +- Assesses technical feasibility of proposals +- Has rejecting voting power +- Does not have the ability to approve proposal -If this period results in necessary normative changes it will revert the NEP to `Review`. +![Approver](https://user-images.githubusercontent.com/110252255/181816752-521dd147-f56f-4c5c-84de-567b109f21d6.png) +**Approver** (Community Working Groups) +*Appointed by Pagoda* -**Final** - This NEP represents the final standard. A Final NEP exists in a state of finality and should only be updated to correct errata and add non-normative clarifications. - -**Living** - A special status for NEPs that are designed to be continually updated and not reach a state of finality. This includes most notably NEP-0001. +- Attends working group meetings to review proposals +- Assigns reviewers to proposals +- Votes to approve or reject proposals ## What does a successful NEP look like? - Each NEP should have the following parts/sections: -1. Preamble - [RFC 822](https://www.ietf.org/rfc/rfc822.txt) style headers - containing meta-data about the NEP, including the NEP number, a short descriptive - title, the names, and optionally the contact info for each author, etc. - -2. Summary - a short (~200 word) description of the technical issue being addressed. - -3. Motivation - The motivation section should - clearly explain why the existing contract ecosystem is - inadequate to address the problem that the NEP solves. This can - include collecting documented support for the NEP from important - projects in the Near ecosystem. NEP submissions without - sufficient motivation may be rejected. - -4. Rationale and alternatives - The rationale fleshes out the specification by - describing why particular design decisions were made. It should - describe alternate designs that were considered and related work, - e.g. how the feature is supported in other platforms. - -5. Specification - The technical specification should describe the - syntax and semantics of the contract or protocol feature. The - specification should be detailed enough to allow competing, - interoperable implementations for at least the current major Near - version. - -6. Reference Implementation - The reference implementation must be - completed before any `Standards Track` in the `Contract` category NEP - is given status "Final", but it need not be completed before the NEP - is accepted. For other Categories, this section is optional. - - While there is merit to the approach of reaching consensus on the - specification and rationale before writing code, the principle of - "rough consensus and running code" is still useful when it comes - to resolving many discussions of API details. - - The final implementation must include test code and documentation - appropriate in a Near-compatible contract language. - - Appropriate judgement should be used when defining the reference - implementation, which can be included inline or reference an - external github repository. - - Where possible, include a `Minimum Viable Interface` expressing the - required behavior and types in a target Near Contract language. - (ie. traits and structs for rust, interfaces and classes for javascript, - function signatures and structs for c, etc.) Expressions of such - interfaces helps define the link between contract standardization - and implementation. - -7. Security Implications - If there are security concerns in relation - to the NEP, those concerns should be explicitly written out to make - sure reviewers of the NEP are aware of them. - -8. Drawbacks - Throughout the discussion of an NEP, various ideas - will be proposed which are not accepted. Those rejected ideas should - be recorded along with the reasoning as to why they were rejected. - This both helps record the thought process behind the final version - of the NEP as well as preventing people from bringing up the same - rejected idea again in subsequent discussions. - - In a way this section can be thought of as a breakout section of the - Rationale section that is focused specifically on why certain ideas - were not ultimately pursued. - -9. Unresolved Issues - While an NEP is in draft, ideas can come up which - warrant further discussion. Those ideas should be recorded so people - know that they are being thought about but do not have a concrete - resolution. This helps make sure all issues required for the NEP to be - ready for consideration are complete and reduces people duplicating - prior discussion. - -10. Future possibilities - Future possibilities describes any natural extensions - and evolutions to the NEP proposal and how it would affect the project. - Try to use this section as a tool to more fully consider all possible - interactions with the project in your proposal. - Also consider how the this all fits into the roadmap for the project - and of the relevant sub-teams. - -11. Copyright Waiver - All NEPs must be in the public domain. See the bottom - of this NEP for an example copyright waiver. - +1. Preamble - [RFC](https://www.ietf.org/rfc/rfc822.txt)[ 822](https://www.ietf.org/rfc/rfc822.txt) style headers containing meta-data about the NEP, including the NEP number, a short descriptive title, the names, and optionally the contact info for each author, etc. +1. Summary - a short (~200 word) description of the technical issue being addressed. +1. Motivation - The motivation section should clearly explain why the existing contract ecosystem is inadequate to address the problem that the NEP solves. This can include collecting documented support for the NEP from important projects in the NEAR ecosystem. NEP submissions without sufficient motivation may be rejected. +1. Rationale and alternatives - The rationale fleshes out the specification by describing why particular design decisions were made. It should describe alternate designs that were considered and related work, e.g. how the feature is supported in other platforms. +1. Specification - The technical specification should describe the syntax and semantics of the contract or protocol feature. The specification should be detailed enough to allow competing, interoperable implementations for at least the current major NEAR version. +1. Reference Implementation - The reference implementation must be completed before any NEP is given the “Approved” status. + While there is merit to the approach of reaching consensus on the specification and rationale before writing code, the principle of “rough consensus and running code” is still useful when it comes to resolving many discussions of API details. The final implementation must include test code and documentation. +1. Security Implications - If there are security concerns in relation to the NEP, those concerns should be explicitly written out to make sure reviewers of the NEP are aware of them. +1. Drawbacks - Throughout the discussion of a NEP, various ideas will be proposed which are not accepted. Those rejected ideas should be recorded along with the reasoning as to why they were rejected. This both helps record the thought process behind the final version of the NEP as well as preventing people from bringing up the same rejected idea again in subsequent discussions. + In a way this section can be thought of as a breakout section of the Rationale section that is focused specifically on why certain ideas were not ultimately pursued. +1. Unresolved Issues - While a NEP is in draft, ideas can come up which warrant further discussion. Those ideas should be recorded so people know that they are being thought about but do not have a concrete resolution. This helps make sure all issues required for the NEP to be ready for consideration are complete and reduces people duplicating prior discussion. +1. Future possibilities - Future possibilities describes any natural extensions and evolutions to the NEP proposal and how it would affect the project. Try to use this section as a tool to more fully consider all possible interactions with the project in your proposal. Also consider how this all fits into the roadmap for the project and of the relevant sub-teams. +1. Copyright Waiver - All NEPs must be in the public domain. See the bottom of this NEP for an example copyright waiver. ## NEP Header Preamble - -Each NEP must begin with an [RFC 822](https://www.ietf.org/rfc/rfc822.txt) style -header preamble. The headers must appear in the following order. +Each NEP must begin with an [RFC](https://www.ietf.org/rfc/rfc822.txt)[ 822](https://www.ietf.org/rfc/rfc822.txt) style header preamble. The headers must appear in the following order. ``` NEP: Title: - Author: - DiscussionsTo: - Status: - Type: - Category: if Type is "Standards Track" one of + Author: + Status: + DiscussionsTo (Optional): + Type: Requires (Optional): Replaces (Optional): SupersededBy (Optional): Created: ``` + + +`Title`: The NEP title header should not be more than 4-5 words, describing -`Title`: The NEP title header should not be more than 4-5 words, describing +`Author`: The Author header lists the names, and optionally the email addresses of all the authors/owners of the NEP. The format of the Author header value must be -`Author`: The Author header lists the names, and optionally the email addresses -of all the authors/owners of the NEP. The format of the Author header -value must be - - Random J. User + Random J. User ; + Other I. User if the email address is included, and just Random J. User -If there are multiple authors, each should be on a separate line -following [RFC 822](https://www.ietf.org/rfc/rfc822.txt) continuation line conventions. - -`DiscussionsTo`: The DiscussionsTo header provides the URL to the current -canonical discussion thread for the NEP. +`DiscussionsTo`: The DiscussionsTo header provides the URL to the current canonical discussion thread for the NEP. -`Type`: The Type header specifies the type of NEP: Standards Track, -Informational, or Process. +`Type`: The Type header specifies the type of NEP: Standards or Protocol -`Category`: The Category header only exists iff the Type header is `Standards Track`, -one of Protocol, Contract or Runtime. +`Created`: The Created header records the date that the NEP was assigned a number, should be in dd-mmm-yyyy format, e.g. 03-Mar-2022. -`Created`: The Created header records the date that the NEP was assigned a -number, should be in dd-mmm-yyyy format, e.g. 03-Mar-2022. +`Requires`: NEPs may have a Requires header, indicating the NEP numbers that this NEP depends on. -`Requires`: NEPs may have a Requires header, indicating the NEP numbers that this -NEP depends on. +> SupersededBy: NEPs may also have a SupersededBy header indicating that a NEP has been rendered obsolete by a later document; the value is the number of the NEP that replaces the current document. -`SupersededBy`: NEPs may also have a SupersededBy header indicating that an NEP has -been rendered obsolete by a later document; the value is the number of -the NEP that replaces the current document. - -`Replaces`: A newer NEP marked with a SupercededBy header must have a Replaces header -containing the number of the NEP that it rendered obsolete. +`Replaces`: A newer NEP marked with a SupercededBy header must have a Replaces header containing the number of the NEP that it rendered obsolete. ## Auxiliary Files - -Images, diagrams and auxiliary files should be included in a subdirectory of the assets -folder for that NEP as follows: `assets/nep-N` (where N is to be replaced with the NEP number). -When linking to an image in the NEP, use relative links such as ../assets/nep-1/image.png +Images, diagrams and auxiliary files should be included in a subdirectory of the assets folder for that NEP as follows: assets/nep-N (where N is to be replaced with the NEP number). When linking to an image in the NEP, use relative links such as …/assets/nep-1/image.png ## Transferring NEP Ownership +It occasionally becomes necessary to transfer ownership of NEPs to a new author. In general, it is preferable to retain the original author as a co-author of the transferred NEP, but that is up to the original author. A good reason to transfer ownership is because the original author no longer has the time or interest in updating it or following through with the NEP process. A bad reason to transfer ownership is because the author does not agree with the direction of the NEP. One aim of the NEP process is to try to build consensus around a NEP, but if that is not possible, an author can submit a competing NEP. -It occasionally becomes necessary to transfer ownership of NEPs to a -new torch-bearer. In general, it is preferable to retain the original author as -a co-author of the transferred NEP, but that's really up to the -original author. A good reason to transfer ownership is because the -original author no longer has the time or interest in updating it or -following through with the NEP process. A bad -reason to transfer ownership is because the author doesn't agree with the -direction of the NEP. One aim of the NEP process is to try to build -consensus around an NEP, but if that's not possible, an author can -submit a competing NEP. - -If you are interested in assuming ownership of an NEP, you can also do this via -pull request. Fork the `NEP repository`, make your ownership modification, -and submit a pull request. You should mention both the original author and -``@near/nep-editors`` in a comment on the pull request. - -## NEP Editors - -The current NEP Editors are: - * Jay Logelin - @jlogelin - -## NEP Editor Responsibilities & Workflow - -Note that developers with write access to the `NEP repository` may -handle the tasks that would normally be taken care of by the NEP editors. - -For each new NEP that comes in, an editor does the following: - -* Read the NEP to check if it is ready: sound and complete. The ideas must make -technical sense, even if they don't seem likely to get to final status. -* The title should accurately describe the content. -* Check the NEP for language (spelling, grammar, sentence structure, etc.), markup -(GitHub flavored Markdown), code style - -Several NEPs are written and maintained by developers with write access -to the Near codebase. The NEP editors monitor the NEP repository -for changes, and correct any structure, grammar, spelling, or -markup mistakes they see. - -NEP editors don't pass philosophical judgment on NEPs. They merely do the -administrative & editorial part. +If you are interested in assuming ownership of a NEP, you can also do this via pull request. Fork the NEP repository, make your ownership modification, and submit a pull request. You should mention both the original author and @near/nep-editors in a comment on the pull request. ## Style Guide #### NEP numbers - -When referring to an NEP by number, it should be written in the hyphenated -form `NEP-X` where `X` is the NEP's assigned number. +When referring to a NEP by number, it should be written in the hyphenated form NEP-X where Xis the NEP’s assigned number. #### RFC 2119 +NEPs are encouraged to follow [RFC](https://www.ietf.org/rfc/rfc2119.txt)[ 2119](https://www.ietf.org/rfc/rfc2119.txt) for terminology and to insert the following at the beginning of the Specification section: -NEPs are encouraged to follow [RFC 2119](https://www.ietf.org/rfc/rfc2119.txt) for -terminology and to insert the following at the beginning of the Specification section: - -> The key words “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “MAY”, and “OPTIONAL” in this document are to be interpreted as described in RFC 2119. +The key words “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “MAY”, and “OPTIONAL” in this document are to be interpreted as described in RFC 2119. ## References -The content of this document was derived heavily from the PEP, BIP, Rust RFC -and EIP standards boostrap documents: +The content of this document was derived heavily from the PEP, BIP, Rust RFC and EIP standards bootstrap documents: * Klock, F et al. Rust: RFC-0002: RFC Process. https://github.com/rust-lang/rfcs/blob/master/text/0002-rfc-process.md * Taaki, A. et al. Bitcoin Improvement Proposal: BIP:1, BIP Purpose and Guidelines. https://github.com/bitcoin/bips/blob/master/bip-0001.mediawiki From f16b13081910f5224f243f5727abb2d2b5c1e336 Mon Sep 17 00:00:00 2001 From: Bowen Wang Date: Mon, 1 Aug 2022 13:22:32 -0700 Subject: [PATCH 053/150] Update nep-0001.md (#378) --- neps/nep-0001.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/neps/nep-0001.md b/neps/nep-0001.md index d8b2ac37f..fb5f3f593 100644 --- a/neps/nep-0001.md +++ b/neps/nep-0001.md @@ -174,7 +174,7 @@ if the email address is included, and just `Requires`: NEPs may have a Requires header, indicating the NEP numbers that this NEP depends on. -> SupersededBy: NEPs may also have a SupersededBy header indicating that a NEP has been rendered obsolete by a later document; the value is the number of the NEP that replaces the current document. +`SupersededBy`: NEPs may also have a SupersededBy header indicating that a NEP has been rendered obsolete by a later document; the value is the number of the NEP that replaces the current document. `Replaces`: A newer NEP marked with a SupercededBy header must have a Replaces header containing the number of the NEP that it rendered obsolete. From 28e3258d49842e715ba99c320675a4999ce8075c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dami=C3=A1n=20Parrino?= Date: Tue, 2 Aug 2022 09:02:53 -0300 Subject: [PATCH 054/150] Add Gleap widget to Nomicon (#379) --- website/docusaurus.config.js | 3 --- website/package.json | 1 + website/src/theme/Root.js | 16 ++++++++++++++++ website/yarn.lock | 5 +++++ 4 files changed, 22 insertions(+), 3 deletions(-) create mode 100644 website/src/theme/Root.js diff --git a/website/docusaurus.config.js b/website/docusaurus.config.js index 9f74cc7f4..2726aeb8f 100644 --- a/website/docusaurus.config.js +++ b/website/docusaurus.config.js @@ -18,9 +18,6 @@ const config = { favicon: 'img/favicon.ico', organizationName: 'near', // Usually your GitHub org/user name. projectName: 'NEPs', // Usually your repo name. - scripts: [ - "/js/hotjar.js", - ], plugins: [require.resolve('docusaurus-lunr-search')], stylesheets: [ { diff --git a/website/package.json b/website/package.json index 3f8d68fd6..bc53d1421 100644 --- a/website/package.json +++ b/website/package.json @@ -20,6 +20,7 @@ "@mdx-js/react": "^1.6.21", "clsx": "^1.1.1", "docusaurus-lunr-search": "^2.1.15", + "gleap": "^7.0.29", "hast-util-is-element": "1.1.0", "prism-react-renderer": "^1.2.1", "react": "^17.0.1", diff --git a/website/src/theme/Root.js b/website/src/theme/Root.js new file mode 100644 index 000000000..94cd13ac8 --- /dev/null +++ b/website/src/theme/Root.js @@ -0,0 +1,16 @@ +// https://docusaurus.io/docs/swizzling#wrapper-your-site-with-root + +import React from 'react'; +import useIsBrowser from '@docusaurus/useIsBrowser'; // https://docusaurus.io/docs/advanced/ssg#useisbrowser +import Gleap from "gleap"; // See https://gleap.io/docs/javascript/ and https://app.gleap.io/projects/62697858a4f6850036ae2e6a/widget + +const GLEAP_API_KEY = 'K2v3kvAJ5XtPzNYSgk4Ulpe5ptgBkIMv'; + +// Default implementation, that you can customize +export default function Root({ children }) { + const isBrowser = useIsBrowser(); + if (isBrowser) { + Gleap.initialize(GLEAP_API_KEY); + } + return <>{children}; +} diff --git a/website/yarn.lock b/website/yarn.lock index abb23c452..d9430b961 100644 --- a/website/yarn.lock +++ b/website/yarn.lock @@ -4105,6 +4105,11 @@ github-slugger@^1.4.0: resolved "https://registry.yarnpkg.com/github-slugger/-/github-slugger-1.4.0.tgz#206eb96cdb22ee56fdc53a28d5a302338463444e" integrity sha512-w0dzqw/nt51xMVmlaV1+JRzN+oCa1KfcgGEWhxUG16wbdA+Xnt/yoFO8Z8x/V82ZcZ0wy6ln9QDup5avbhiDhQ== +gleap@^7.0.29: + version "7.0.29" + resolved "https://registry.yarnpkg.com/gleap/-/gleap-7.0.29.tgz#d8da12d06aead1b9ef75cb4c7f9778395c188c9c" + integrity sha512-2vRs+ZiRFDtyri1q/VznAE+fTAD1TOWjfY75J/2tDeS8fDg8qiFVQuNS0Lkgll1AOiGPojbG7AZ5ZusCTExhRA== + glob-parent@^5.1.2, glob-parent@~5.1.2: version "5.1.2" resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" From 0e451bf64a36be54c910435b436e0cb600bc6b9c Mon Sep 17 00:00:00 2001 From: Akhilesh Singhania Date: Wed, 3 Aug 2022 00:53:38 +0200 Subject: [PATCH 055/150] Fix minor typos (#380) --- neps/nep-0001.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/neps/nep-0001.md b/neps/nep-0001.md index fb5f3f593..e37ed97de 100644 --- a/neps/nep-0001.md +++ b/neps/nep-0001.md @@ -17,7 +17,7 @@ NEPs are intended to be the primary mechanism for proposing new features, coordi As such, A NEP’s author is responsible for building consensus within the community and documenting dissenting opinions. ## NEP Participants -Everyone in the community is welcome to propose, discuss, and review ideas to improve the NEAR protocol and standards.The typical primary audience for NEPs are the core developers of the NEAR reference implementations and NEAR Smart Contract developers. +Everyone in the community is welcome to propose, discuss, and review ideas to improve the NEAR protocol and standards. The typical primary audience for NEPs are the core developers of the NEAR reference implementations and NEAR Smart Contract developers. The NEAR working groups are responsible for coordinating the public review of NEPs and have the authority to accept or reject changes. @@ -56,7 +56,7 @@ The NEP workflow is: - The title accurately describes the content. - The language (spelling, grammar, sentence structure, etc.) and code style are correct and conformant. - If the NEP is not ready for approval, a moderator will send it back to the author for revision, with specific instructions in the pull request. The review by NEP moderators is expected to finish within one week. -- Once the NEP moderators agree that the PR is ready for review, the moderators notify the Approver (Community Working Group) to assign a team of at least two reviewers (subject matter experts) to review the NEP. The reviewers will review the technical details of the proposal and assess its merits. They may ask clarification questions, request changes, or reject the proposal. The author of the proposal is free to revise the proposal and re-request reviews from reviewers. +- Once the NEP moderators agree that the PR is ready for review, the moderators notify the Approver (Community Working Group) to assign a team of at least two reviewers (subject matter experts) to review the NEP. The reviewers will review the technical details of the proposal and assess its merits. They may ask clarifying questions, request changes, or reject the proposal. The author of the proposal is free to revise the proposal and re-request reviews from reviewers. - If a proposal is in the review stage for more than two months, it is automatically rejected. To re-open the proposal, the author must start over with the NEP process again. - Once the reviewers agree that the proposal is overall beneficial for the NEAR ecosystem, they will ask the author to present the proposal to the working group, where it can enter the final voting stage. If the vote passes, then the proposal is considered accepted. From 05ab2204d0f34319068453761c08b8638c6a8c46 Mon Sep 17 00:00:00 2001 From: ori-near <110252255+ori-near@users.noreply.github.com> Date: Fri, 12 Aug 2022 16:14:41 -0700 Subject: [PATCH 056/150] Update nep-0001.md (#382) Added a motivation section with more information about NEP review process and working groups. Also added a few clarifying sentences and fixed some grammatical errors. --- neps/nep-0001.md | 45 +++++++++++++++++++++++++++------------------ 1 file changed, 27 insertions(+), 18 deletions(-) diff --git a/neps/nep-0001.md b/neps/nep-0001.md index e37ed97de..fa4c1bbfd 100644 --- a/neps/nep-0001.md +++ b/neps/nep-0001.md @@ -10,16 +10,24 @@ Created: 03-Mar-2022 ## What is a NEAR Enhancement Proposal (NEP)? -A NEP is a design document for providing information to the NEAR community or describing a new feature for the NEAR protocol or Smart Contract standards. NEP’s should provide a concise technical specification and a rationale for the feature. +A NEP is a design document for providing information to the NEAR community or describing a new feature for the NEAR protocol or Smart Contract standards. The NEP should provide a concise technical specification and a rationale for the feature. NEPs are intended to be the primary mechanism for proposing new features, coordinating formal feedback, and documenting design decisions that were integrated into NEAR’s runtime or Smart Contract ecosystem. -As such, A NEP’s author is responsible for building consensus within the community and documenting dissenting opinions. +As such, the NEP’s author is responsible for building consensus within the community and documenting dissenting opinions. -## NEP Participants -Everyone in the community is welcome to propose, discuss, and review ideas to improve the NEAR protocol and standards. The typical primary audience for NEPs are the core developers of the NEAR reference implementations and NEAR Smart Contract developers. +Because NEPs are maintained as text files in a versioned repository, their revision history is the historical record of the feature proposal. A list of NEPs is available on [GitHub](https://github.com/near/NEPs/). -The NEAR working groups are responsible for coordinating the public review of NEPs and have the authority to accept or reject changes. +## Motivation + +The purpose of the NEP process is to ensure seamless protocol upgrades and to empower the community to contribute to the development of the NEAR platform. Given the complexity of the protocol and the large number of participants across the ecosystem, the process introduces working groups as a way to operationalize the review of NEPs that builds legitimacy and community support. + +The working groups are responsible for coordinating the public review of NEPs, gauging the viability and community support, and overseeing decisions. Each group will focus on various ecosystem needs, such as the protocol, standards, and tools. + +Pagoda has selected a few leading subject matter experts to help bootstrap the first two groups: Protocols and Contract Standards. Putting these groups into practice will require flexibility. The goal is to iterate and eventually introduce more groups and broader participation. Visit [https://near.org/working-groups](https://near.org/working-groups) to learn more about these groups, their members, and the upcoming meetings. + +## Audience +The typical primary audience for NEPs are the core developers of the NEAR reference implementations and decentralized applications developers ## NEP Types There are two kinds of NEPs: @@ -27,11 +35,13 @@ There are two kinds of NEPs: 1. A **Standards** NEP describes a new NEAR Smart Contract implementation standard. 2. A **Protocol** NEP describes a new feature for the NEAR protocol. +Currently, both types of NEPs follow the same process. + ## NEP Workflow ### Start with an idea for NEAR -The NEP process begins with a new idea for the NEAR ecosystem. A single NEP should contain a single key proposal or new idea. +Everyone in the community is welcome to propose, discuss, and review ideas to improve the NEAR protocol and standards. The NEP process begins with a new idea for the NEAR ecosystem. A single NEP should contain a single key proposal or new idea. -Each NEP must have an author: someone who writes the NEP using the style and format described below, shepherds the discussions in the appropriate forums, and attempts to build community consensus around the idea. +Each NEP must have an author: someone who writes the NEP using the style and format described below. The author, or another champion, shepherds the discussions in the appropriate forums and attempts to build community consensus around the idea to help it progress toward completion. Before submitting a NEP, the author should first attempt to ascertain whether the idea is NEP-able. Vetting an idea publicly before writing a NEP saves the potential author time. Asking the NEAR community first if an idea is original helps prevent effort on something that is guaranteed to be rejected based on prior discussions. It also helps ensure the idea is applicable to the entire community. Just because an idea sounds good to the author does not mean it will work for most people in most use cases. @@ -55,18 +65,17 @@ The NEP workflow is: - The content is sound and complete. The ideas must make technical sense. The moderators do not consider whether they seem likely for acceptance. - The title accurately describes the content. - The language (spelling, grammar, sentence structure, etc.) and code style are correct and conformant. -- If the NEP is not ready for approval, a moderator will send it back to the author for revision, with specific instructions in the pull request. The review by NEP moderators is expected to finish within one week. -- Once the NEP moderators agree that the PR is ready for review, the moderators notify the Approver (Community Working Group) to assign a team of at least two reviewers (subject matter experts) to review the NEP. The reviewers will review the technical details of the proposal and assess its merits. They may ask clarifying questions, request changes, or reject the proposal. The author of the proposal is free to revise the proposal and re-request reviews from reviewers. +- If the NEP is not ready for approval, the moderators will send it back to the author for revision, with specific instructions in the pull request. The review by the moderators is expected to finish within one week. +- Once the moderators agree that the PR is ready for review, the moderators notify the approvers (working groups) to assign a team of at least two reviewers (subject matter experts) to review the NEP. The reviewers will review the technical details of the proposal and assess its merits. They may ask clarification questions, request changes, or reject the proposal. The review by the reviewers is expected to finish within one week. The author of the proposal is free to revise the proposal and re-request reviews from reviewers. - If a proposal is in the review stage for more than two months, it is automatically rejected. To re-open the proposal, the author must start over with the NEP process again. -- Once the reviewers agree that the proposal is overall beneficial for the NEAR ecosystem, they will ask the author to present the proposal to the working group, where it can enter the final voting stage. If the vote passes, then the proposal is considered accepted. +- Once the reviewers agree that the proposal is close to a decision, they will have a final two week review period to add their comments, and then ask the author to present the NEP to the working group in a meeting, where it can enter the final voting stage. If the moderators agree that the NEP is overall beneficial for the NEAR ecosystem and vote to approve it, then the proposal is considered accepted. ### NEP Maintenance In general, NEPs are no longer modified after they have reached the Final state. ## NEP Life Cycle -![NEP Process](https://user-images.githubusercontent.com/110252255/181816298-9945206e-4041-4499-85f7-51e3d1e493d0.png) - +![NEP Process](https://user-images.githubusercontent.com/110252255/184407496-e96b0a96-af43-4694-90ed-58d8bb463958.png) A given NEP can have one of the following states: @@ -83,7 +92,7 @@ The NEP process has various roles and responsibilities. ![author](https://user-images.githubusercontent.com/110252255/181816534-2f92b073-79e2-4e8d-b5b9-b10824958acd.png) -**Author** +**Author**
*Anyone can participate* - Writes proposal following the standards @@ -94,7 +103,7 @@ The NEP process has various roles and responsibilities. - Provides reference implementation and documentation once approved ![Moderator](https://user-images.githubusercontent.com/110252255/181816650-b1610c0e-6d32-4d2a-a34e-877c702139bd.png) -**Moderator** +**Moderator**
*Assigned by working group* - Ensures proposal meets standards @@ -105,7 +114,7 @@ The NEP process has various roles and responsibilities. - Does not assess the technical feasibility or writes any parts of the proposal ![Reviewer](https://user-images.githubusercontent.com/110252255/181816664-a9485ea6-e774-4999-b11d-dc8be6b08f87.png) -**Reviewer** (Subject Matter Experts) +**Reviewer** (Subject Matter Experts)
*Assigned by working group* - Gives feedback on proposals @@ -114,11 +123,11 @@ The NEP process has various roles and responsibilities. - Does not have the ability to approve proposal ![Approver](https://user-images.githubusercontent.com/110252255/181816752-521dd147-f56f-4c5c-84de-567b109f21d6.png) -**Approver** (Community Working Groups) -*Appointed by Pagoda* +**Approver** (Community Working Groups)
+*Appointed by Pagoda in the boostraphing phase* -- Attends working group meetings to review proposals - Assigns reviewers to proposals +- Attends working group meetings to review proposals - Votes to approve or reject proposals ## What does a successful NEP look like? From 07d0fbf429947c52fd685d3b5f36785f681dd01c Mon Sep 17 00:00:00 2001 From: Austin Abell Date: Mon, 5 Sep 2022 01:16:05 -0400 Subject: [PATCH 057/150] Utilization of unspent gas for promise function calls (#264) --- specs/Proposals/0264-promise_gas_ratio.md | 169 ++++++++++++++++++++++ 1 file changed, 169 insertions(+) create mode 100644 specs/Proposals/0264-promise_gas_ratio.md diff --git a/specs/Proposals/0264-promise_gas_ratio.md b/specs/Proposals/0264-promise_gas_ratio.md new file mode 100644 index 000000000..17306bbfa --- /dev/null +++ b/specs/Proposals/0264-promise_gas_ratio.md @@ -0,0 +1,169 @@ +- Proposal Name: `promise_gas_weight` +- Start Date: 2021-09-30 +- NEP PR: [nearprotocol/neps#264](https://github.com/nearprotocol/neps/pull/264) +- Issue(s): https://github.com/near/near-sdk-rs/issues/526 + +# Summary +[summary]: #summary + +This proposal is to introduce a new host function on the NEAR runtime that allows for scheduling cross-contract function calls using a percentage/weight of the remaining gas in addition to the statically defined amount. This will enable async promise execution to use the remaining gas more efficiently by utilizing unspent gas from the current transaction. + +# Motivation +[motivation]: #motivation + +We are proposing this to be able to utilize gas more efficiently but also to improve the devX of cross-contract calls. Currently, developers must guess how much gas will remain after the current transaction finishes and if this value is too little, the transaction will fail, and if it is too large, gas will be wasted. Therefore, these cross-contract calls need a reasonable default of splitting unused gas efficiently for basic cases without sacrificing the ability to configure the gas amount attached at a granular level. Currently, gas is allocated very inefficiently, requiring more prepaid gas or failed transactions when the allocations are imprecise. + +# Guide-level explanation +[guide-level-explanation]: #guide-level-explanation + +This host function is similar to [`promise_batch_action_function_call`](https://github.com/near/nearcore/blob/7d15bbc996282c8ae8f15b8f49d110fc901b84d8/runtime/near-vm-logic/src/logic.rs#L1526), except with an additional parameter that lets you specify how much of the excess gas should be attached to the function call. This parameter is a weight value that determines how much of the excess gas is attached to each function. + +So, for example, if there is 40 gas leftover and three function calls that select weights of 1, 5, and 2, the runtime will add 5, 25, and 10 gas to each function call. A developer can specify whether they want to attach a fixed amount of gas, a weight of remaining gas, or both. If at least one function call uses a weight of remaining gas, then all excess gas will be attached to future calls. This proposal allows developers the ability to utilize prepaid gas more efficiently than currently possible. + +# Reference-level explanation +[reference-level-explanation]: #reference-level-explanation + +This host function would need to be implemented in `nearcore` and parallel [`promise_batch_action_function_call`](https://github.com/near/nearcore/blob/7d15bbc996282c8ae8f15b8f49d110fc901b84d8/runtime/near-vm-logic/src/logic.rs#L1526). Most details of these functions will be consistent, except that there will be additional bookkeeping for keeping track of which functions specified a weight for unused gas. This will not affect or replace any existing host functions, but this will likely require a slightly higher gas cost than the original `promise_batch_action_function_call` host function due to this additional overhead. + +This host function definition would look like this (as a Rust consumer): +```rust + /// Appends `FunctionCall` action to the batch of actions for the given promise pointed by + /// `promise_idx`. This function allows not specifying a specific gas value and allowing the + /// runtime to assign remaining gas based on a weight. + /// + /// # Gas + /// + /// Gas can be specified using a static amount, a weight of remaining prepaid gas, or a mixture + /// of both. To omit a static gas amount, `0` can be passed for the `gas` parameter. + /// To omit assigning remaining gas, `0` can be passed as the `gas_weight` parameter. + /// + /// The gas weight parameter works as the following: + /// + /// All unused prepaid gas from the current function call is split among all function calls + /// which supply this gas weight. The amount attached to each respective call depends on the + /// value of the weight. + /// + /// For example, if 40 gas is leftover from the current method call and three functions specify + /// the weights 1, 5, 2 then 5, 25, 10 gas will be added to each function call respectively, + /// using up all remaining available gas. Any remaining gas will be allocated to the last + /// function call. + /// + /// # Errors + /// + /// <...Ommitted previous errors as they do not change> + /// - If `0` is passed for both `gas` and `gas_weight` parameters + pub fn promise_batch_action_function_call_weight( + promise_index: u64, + method_name_len: u64, + method_name_ptr: u64, + arguments_len: u64, + arguments_ptr: u64, + amount_ptr: u64, + gas: u64, + gas_weight: u64, + ); + +``` + +The only difference from the existing API is `gas_weight` added as another parameter, as an unsigned 64-bit integer. + +As for calculations, the remaining gas at the end of the transaction can be floor divided by the sum of all the weights tracked. Then, after getting this value, just attach that value multiplied by the weight gas to each function call action. + +For example, if there are three weights, `a`, `b`, `c`: +``` +weight_sum = a + b + c +a_gas += remaining_gas * a / weight_sum +b_gas += remaining_gas * b / weight_sum +c_gas += remaining_gas * c / weight_sum +``` + +Any remaining gas that is not allocated to any of these function calls will be attached to the last function call scheduled. + +### SDK changes + +This protocol change will allow cross-contract calls to provide a fixed amount of gas and/or adjust the weight of unused gas to use. If neither is provided, it will default to using a weight of 1 for each and no static amount of gas. If no function modifies this weight, the runtime will split the unused gas evenly among all function calls. + +Currently, the API for a cross-contract call looks like: +```rust +let contract_account_id: AccountId = todo!(); +ext::some_method(/* parameters */, contract_account_id, 0 /* deposit amount */, 5_000_000_000_000 /* static amount of gas to attach */) +``` + +When the intended API should not require thinking about how much gas to attach by default, the API will look something like what's shown in [this PR](https://github.com/near/near-sdk-rs/pull/742), which can look like the following: + +```rust +cross_contract::ext(contract_account_id) + // Optional config + .with_attached_deposit(1 /* default deposit of 0 */) + .with_static_gas(Gas(5_000_000_000_000) /* default of 0 */) + .with_unused_gas_weight(2 /* default 1 */) + + // Then call any method to schedule the function call + .some_method(/* parameters */) +``` + +At a basic level, a developer has only to include the parameters for the function call and specify the account id of the contract being called. Currently, only the amount can be optional because there is no way to set a reasonable default for the amount of gas to use for each function call. + +# Drawbacks +[drawbacks]: #drawbacks + +- Complexity in refactoring to handle assigning remaining gas at the end of a transaction +- Complexity in extra calculations for assigning gas will make the host function slightly more expensive than the base one. It is not easy to create an API on the SDK level that can decide which host function to call if dynamic gas assigning is needed or not. If both are used, the size of the wasm binary is trivially larger by including both host functions +- Adds another host function to the runtime, which can probably never be removed +- Can be confusing to have both static gas and dynamic unused gas and convey what is happening internally to a developer +- If we start utilizing all prepaid gas, this will likely lead to a higher percentage of prepaid gas usage. This could be an unexpected pattern for users and require them to think about how much gas they are attaching to make sure they only attach what they are willing to spend + - Since currently, we are refunding a lot of unused gas, this could be a hidden negative side effect + - Keep in mind that it will also be positive because transactions will generally succeed more often due to gas more efficiently + +# Rationale and alternatives +[rationale-and-alternatives]: #rationale-and-alternatives + +Alternative 1 (fraction parameters): +The primary alternative is using a numerator and denominator to represent a fraction instead of a weight. This alternative would be equivalent to the one listed above except for two u64 additional parameters instead of just the one for weight. I'll list the tradeoff as pros and cons: + +Pros: +- Can under-utilize the gas for the current transaction to limit gas allowed for certain functions +- This could take responsibility away from DApp users because they would not have to worry less about attaching too much prepaid gas +- Thinking in terms of fractions may be more intuitive for some developers +- Might future proof better if we ever need this ability in the future, want to minimize the number of host functions created at all costs + +Cons: +- More complicated logic/edge cases to handle to make sure the percentages don't sum to greater than 100% (or adjusting if they do) +- Precision loss from dividing integers may lead to unexpected results + - To get closer to expected, we could use floats for the division, but this gets messy +- API for specifying a fraction would be messy (need to specify two values rather than just optionally one) +- There isn't a good default for this. Unless there is a special value that indicates a pool of function calls that will split the remaining equally, but this defeats the purpose of this alternative completely +- Slightly larger API (only one u64, can probably safely ignore this point) + +Alternative 2 (handle within contract/SDK): +The other alternative is to handle all of this logic on the contract side, as seen by [this PR](https://github.com/near/near-sdk-rs/pull/523). This is much less feasible/accurate because there is only so much information available within the runtime, and gas costs and internal functionality may not always be the same. As discussed on [the respective issue](https://github.com/near/near-sdk-rs/issues/526), this alternative seems to be very infeasible. + +Pros: +- No protocol change is needed +- Can still have improved API as with protocol change + +Cons: +- Additional bloat to every contract, even ones that don't use the pattern (~5kb in PoC, even with simple estimation logic) +- Still inaccurate gas estimations, because at the point of calculation, we cannot know how much gas will be used for assigning gas values as well as gas consumed after the transaction ends + - This leads to either underutilizing or having transactions fail when using too much gas if trying to estimate how much gas will be left +- Prone to breaking existing contracts on protocol changes that affect gas usage or logic of runtime + +# Unresolved questions +[unresolved-questions]: #unresolved-questions + +What needs to be addressed before this gets merged: +~~- How much refactoring exactly is needed to handle this pattern?~~ + ~~- Can we keep a queue of receipt and action indices with their respective weights and update their gas values after the current method is executed? Is there a cleaner way to handle this while keeping order?~~ +~~- Do we want to attach the gas lost due to precision on division to any function?~~ + - The remaining gas is now attached to the last function call + +What would be addressed in future independently of the solution: +- How many users would expect the ability to refund part of the gas after the initial transaction? (is this worth considering the API difference of using fractions rather than weights) +- Will weights be an intuitive experience for developers? + +# Future possibilities +[future-possibilities]: #future-possibilities + +The future change that would extend from this being implemented is a much cleaner API for the SDKs. As mentioned previously in the alternatives section, the API changes from [the changes tested on the SDK](https://github.com/near/near-sdk-rs/pull/523) will remain, but without the overhead from implementing this on the contract level. Thus, not only can this be implemented in Rust, but it will also allow a consistent API for existing and future SDK languages to build on. + +The primary benefit for SDKs is that it removes the need to specify gas when making cross-contract calls explicitly. Currently, there is no easy way of knowing how many function calls will be made to split prepaid gas without a decent amount of overhead. Even if the developer does this, it's impossible to know how much gas will remain after the transaction from inside the contract. Having this host function available will simplify the DevX for contract developers and make the contracts use gas more efficiently. From b3d877a08c5ba7f487b66ae54b30e4ce99175910 Mon Sep 17 00:00:00 2001 From: Yassine Date: Mon, 5 Sep 2022 07:29:04 +0200 Subject: [PATCH 058/150] fix: Typo in TokenMetadata (#363) --- specs/Standards/Tokens/NonFungibleToken/Metadata.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/specs/Standards/Tokens/NonFungibleToken/Metadata.md b/specs/Standards/Tokens/NonFungibleToken/Metadata.md index 2e324e2e6..80fe3e752 100644 --- a/specs/Standards/Tokens/NonFungibleToken/Metadata.md +++ b/specs/Standards/Tokens/NonFungibleToken/Metadata.md @@ -85,7 +85,7 @@ For `NFTContractMetadata`: For `TokenMetadata`: -- `name`: The name of this specific token. +- `title`: The name of this specific token. - `description`: A longer description of the token. - `media`: URL to associated media. Preferably to decentralized, content-addressed storage. - `media_hash`: the base64-encoded sha256 hash of content referenced by the `media` field. This is to guard against off-chain tampering. From 2f289cfb195caae99ea007733db62a40bbfb8f10 Mon Sep 17 00:00:00 2001 From: CrazyCoder_LJ Date: Mon, 5 Sep 2022 13:35:59 +0800 Subject: [PATCH 059/150] refactor: Add tow links, as [Staking] and [Access keys], and some suggestions (#381) --- specs/DataStructures/Account.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/specs/DataStructures/Account.md b/specs/DataStructures/Account.md index 17289d179..9d653c287 100644 --- a/specs/DataStructures/Account.md +++ b/specs/DataStructures/Account.md @@ -136,7 +136,7 @@ Total account balance consists of unlocked balance and locked balance. Unlocked balance is tokens that the account can use for transaction fees, transfers staking and other operations. Locked balance is the tokens that are currently in use for staking to be a validator or to become a validator. -Locked balance may become unlocked at the beginning of an epoch. See [Staking] for details. +Locked balance may become unlocked at the beginning of an epoch. See [Staking](../BlockchainLayer/EpochManager/Staking) for details. #### Contracts @@ -159,9 +159,9 @@ An access key grants an access to a account. Each access key on the account is i This public key is used to validate signature of transactions. Each access key contains a unique nonce to differentiate or order transactions signed with this access key. -An access keys have a permission associated with it. The permission can be one of two types: +An access key has a permission associated with it. The permission can be one of two types: -- Full permission. It grants full access to the account. -- Function call permission. It grants access to only issue function call transactions. +- `FullAccess` permission. It grants full access to the account. +- `FunctionCall` permission. It grants access to only issued function call transactions. -See [Access Keys] for more details. +See [Access Keys](AccessKey.md) for more details. From ba8d2a9d9691f1901172a5bf1f27375864f8e7db Mon Sep 17 00:00:00 2001 From: lewis-sqa <97291103+lewis-sqa@users.noreply.github.com> Date: Tue, 6 Sep 2022 21:47:22 +0100 Subject: [PATCH 060/150] NEP-368: Bridge Wallet Standard (#368) * Initial commit. * Added connect flow. * Updated sign in flow. * Updated sign out flow. * Updated the flows. * Simplified sections. * Updated descriptions of each method. * Decoupled method interfaces from WalletConnect. * Aligned references to methods. * Minor improvements to motivation and flows. * Improved interop with near-api-js. * Switched to signTransaction(s). * Fixed typo. * Fixed typo. * Initial restructure * Fixed types. * Initial attempt at "Rationale and alternatives" section. * Initial start on the Specification section. * Improved wording. * Added description around connecting. * Added description for various methods. * Initial attempt to detail the differences between the two standards. * Improved wording. * Wording/clarity tweaks * Make spellcheck happy Co-authored-by: Daryl Collins --- specs/Standards/Wallets/BridgeWallets.md | 159 +++++++++++++++++++++++ 1 file changed, 159 insertions(+) create mode 100644 specs/Standards/Wallets/BridgeWallets.md diff --git a/specs/Standards/Wallets/BridgeWallets.md b/specs/Standards/Wallets/BridgeWallets.md new file mode 100644 index 000000000..ef8ed22f4 --- /dev/null +++ b/specs/Standards/Wallets/BridgeWallets.md @@ -0,0 +1,159 @@ +# Bridge Wallets + +## Summary + +Standard interface for bridge wallets. + +## Motivation + +Bridge wallets such as [WalletConnect](https://docs.walletconnect.com/2.0/) and [Nightly Connect](https://connect.nightly.app/) are powerful messaging layers for communicating with various blockchains. Since they lack an opinion on how payloads are structured, without a standard, it can be impossible for dApps and wallets to universally communicate without compatibility problems. + +## Rationale and alternatives + +At its most basic, a wallet manages key pairs which are used to sign messages. The signed messages are typically then submitted by the wallet to the blockchain. This standard aims to define an API (based on our learning from [Wallet Selector](https://github.com/near/wallet-selector)) that achieves this requirement through a number of methods compatible with a relay architecture. + +There have been many iterations of this standard to help inform what we consider the best approach right now for NEAR. You can find more relevant content in the [Injected Wallet Standard](./InjectedWallets.md). + +## Specification + +Bridge wallets use a relay architecture to forward signing requests between dApps and wallets. Requests are typically relayed using a messaging protocol such as WebSockets or by polling a REST API. The concept of a `session` wraps this connection between a dApp and a wallet. When the session is established, the wallet user typically selects which accounts that the dApp should have any awareness of. As the user interacts with the dApp and performs actions that require signing, messages are relayed to the wallet from the dApp, those messages are signed by the wallet and submitted to the blockchain on behalf of the requesting dApp. This relay architecture decouples the 'signing' context (wallet) and the 'requesting' context (dApp, which enables signing to be performed on an entirely different device than the dApp browser is running on. + +To establish a session, the dApp must first pair with the wallet. Pairing often includes a QR code to improve UX. Once both clients are paired, a request to initialize a session is made. During this phase, the wallet user is prompted to select one or more accounts (previously imported) to be visible to the session before approving the request. + +Once a session has been created, the dApp can make requests to sign transactions using either [`signTransaction`](#signtransaction) or [`signTransactions`](#signtransactions). These methods accept encoded [Transactions](https://nomicon.io/RuntimeSpec/Transactions) created with `near-api-js`. Since transactions must know the public key that will be used as the `signerId`, a call to [`getAccounts`](#getaccounts) is required to retrieve a list of the accounts visible to the session along with their associated public key. Requests to both [`signTransaction`](#signtransaction) and [`signTransactions`](#signtransactions) require explicit approval from the user since [`FullAccess`](https://nomicon.io/DataStructures/AccessKey) keys are used. + +For dApps that regularly sign gas-only transactions, Limited [`FunctionCall`](https://nomicon.io/DataStructures/AccessKey#accesskeypermissionfunctioncall) access keys can be added/deleted to one or more accounts by using the [`signIn`](#signin) and [`signOut`](#signout) methods. While the same functionality could be achieved with [`signTransactions`](#signtransactions), that contain actions that add specific access keys with particular permissions to a specific account, by using `signIn`, the wallet receives a direct intention that a user wishes to sign in/out of a dApp's smart contract, which can provide a cleaner UI to the wallet user and allow convenient behavior to be implemented by wallet providers such as 'sign out' automatically deleting the associated limited access key that was created when the user first signed in. + +Although intentionally similar to the [Injected Wallet Standard](./InjectedWallets.md), this standard focuses on the transport layer instead of the high-level abstractions found in injected wallets. Below are the key differences between the standards: + +- [Transactions](https://nomicon.io/RuntimeSpec/Transactions) passed to `signTransaction` and `signTransactions` must be encoded. +- The result of `signTransaction` and `signTransactions` are encoded [SignedTransaction](https://nomicon.io/RuntimeSpec/Transactions#signed-transaction) models. +- Accounts contain only a string representation of public keys. + +### Methods + +#### `signTransaction` + +Sign a transaction. This request should require explicit approval from the user. + +```ts +import { transactions } from "near-api-js"; + +interface SignTransactionParams { + // Encoded Transaction via transactions.Transaction.encode(). + transaction: Uint8Array; +} + +// Encoded SignedTransaction via transactions.SignedTransaction.encode(). +type SignTransactionResponse = Uint8Array; +``` + +#### `signTransactions` + +Sign a list of transactions. This request should require explicit approval from the user. + +```ts +import { providers, transactions } from "near-api-js"; + +interface SignTransactionsParams { + // Encoded Transaction via transactions.Transaction.encode(). + transactions: Array; +} + +// Encoded SignedTransaction via transactions.SignedTransaction.encode(). +type SignTransactionsResponse = Array; +``` + +#### `signIn` + +For dApps that often sign gas-only transactions, `FunctionCall` access keys can be created for one or more accounts to greatly improve the UX. While this could be achieved with `signTransactions`, it suggests a direct intention that a user wishes to sign in to a dApp's smart contract. + +```ts +import { transactions } from "near-api-js"; + +interface Account { + accountId: string; + publicKey: string; +} + +interface SignInParams { + permission: transactions.FunctionCallPermission; + accounts: Array; +} + +type SignInResponse = null; +``` + +#### `signOut` + +Delete one or more `FunctionCall` access keys created with `signIn`. While this could be achieved with `signTransactions`, it suggests a direct intention that a user wishes to sign out from a dApp's smart contract. + +```ts +interface Account { + accountId: string; + publicKey: string; +} + +interface SignOutParams { + accounts: Array; +} + +type SignOutResponse = null; +``` + +#### `getAccounts` + +Retrieve all accounts visible to the session. `publicKey` references the underlying `FullAccess` key linked to each account. + +```ts +interface Account { + accountId: string; + publicKey: string; +} + +interface GetAccountsParams {} + +type GetAccountsResponse = Array; +``` + +## Flows + +**Connect** + +1. dApp initiates pairing via QR modal. +2. wallet establishes pairing and prompts selection of accounts for new session. +3. wallet responds with session (id and accounts). +4. dApp stores reference to session. + +**Sign in (optional)** + +1. dApp generates a key pair for one or more accounts in the session. +2. dApp makes `signIn` request with `permission` and `accounts`. +3. wallet receives request and executes a transaction containing an `AddKey` Action for each account. +4. wallet responds with `null`. +5. dApp stores the newly generated key pairs securely. + +**Sign out (optional)** + +1. dApp makes `signOut` request with `accounts`. +2. wallet receives request and executes a transaction containing a `DeleteKey` Action for each account. +3. wallet responds with `null`. +4. dApp clears stored key pairs. + +**Sign transaction** + +1. dApp makes `signTransaction` request. +2. wallet prompts approval of transaction. +3. wallet signs the transaction. +4. wallet responds with `Uint8Array`. +5. dApp decodes signed transaction. +6. dApp sends signed transaction. + +**Sign transactions** + +1. dApp makes `signTransactions` request. +2. wallet prompts approval of transactions. +3. wallet signs the transactions. +4. wallet responds with `Array`. +5. dApp decodes signed transactions. +6. dApp sends signed transactions. From c48e4601b55cdb879e3c80f6de57b11b1944dbdb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dami=C3=A1n=20Parrino?= Date: Thu, 8 Sep 2022 14:31:07 -0300 Subject: [PATCH 061/150] Fix Docusaurus build (#389) * Update BridgeWallets.md * Update Account.md --- specs/DataStructures/Account.md | 2 +- specs/Standards/Wallets/BridgeWallets.md | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/specs/DataStructures/Account.md b/specs/DataStructures/Account.md index 9d653c287..a8cc3c2e8 100644 --- a/specs/DataStructures/Account.md +++ b/specs/DataStructures/Account.md @@ -136,7 +136,7 @@ Total account balance consists of unlocked balance and locked balance. Unlocked balance is tokens that the account can use for transaction fees, transfers staking and other operations. Locked balance is the tokens that are currently in use for staking to be a validator or to become a validator. -Locked balance may become unlocked at the beginning of an epoch. See [Staking](../BlockchainLayer/EpochManager/Staking) for details. +Locked balance may become unlocked at the beginning of an epoch. See [Staking](../BlockchainLayer/EpochManager/Staking.md) for details. #### Contracts diff --git a/specs/Standards/Wallets/BridgeWallets.md b/specs/Standards/Wallets/BridgeWallets.md index ef8ed22f4..34c88764d 100644 --- a/specs/Standards/Wallets/BridgeWallets.md +++ b/specs/Standards/Wallets/BridgeWallets.md @@ -12,7 +12,7 @@ Bridge wallets such as [WalletConnect](https://docs.walletconnect.com/2.0/) and At its most basic, a wallet manages key pairs which are used to sign messages. The signed messages are typically then submitted by the wallet to the blockchain. This standard aims to define an API (based on our learning from [Wallet Selector](https://github.com/near/wallet-selector)) that achieves this requirement through a number of methods compatible with a relay architecture. -There have been many iterations of this standard to help inform what we consider the best approach right now for NEAR. You can find more relevant content in the [Injected Wallet Standard](./InjectedWallets.md). +There have been many iterations of this standard to help inform what we consider the best approach right now for NEAR. You can find more relevant content in the [Injected Wallet Standard](#). ## Specification @@ -24,7 +24,7 @@ Once a session has been created, the dApp can make requests to sign transactions For dApps that regularly sign gas-only transactions, Limited [`FunctionCall`](https://nomicon.io/DataStructures/AccessKey#accesskeypermissionfunctioncall) access keys can be added/deleted to one or more accounts by using the [`signIn`](#signin) and [`signOut`](#signout) methods. While the same functionality could be achieved with [`signTransactions`](#signtransactions), that contain actions that add specific access keys with particular permissions to a specific account, by using `signIn`, the wallet receives a direct intention that a user wishes to sign in/out of a dApp's smart contract, which can provide a cleaner UI to the wallet user and allow convenient behavior to be implemented by wallet providers such as 'sign out' automatically deleting the associated limited access key that was created when the user first signed in. -Although intentionally similar to the [Injected Wallet Standard](./InjectedWallets.md), this standard focuses on the transport layer instead of the high-level abstractions found in injected wallets. Below are the key differences between the standards: +Although intentionally similar to the [Injected Wallet Standard](#), this standard focuses on the transport layer instead of the high-level abstractions found in injected wallets. Below are the key differences between the standards: - [Transactions](https://nomicon.io/RuntimeSpec/Transactions) passed to `signTransaction` and `signTransactions` must be encoded. - The result of `signTransaction` and `signTransactions` are encoded [SignedTransaction](https://nomicon.io/RuntimeSpec/Transactions#signed-transaction) models. From 685024f67c3d698d94f4179eac0fb0a569cc914b Mon Sep 17 00:00:00 2001 From: Matias Wald Date: Wed, 14 Sep 2022 07:27:14 -0400 Subject: [PATCH 062/150] fix: Fixed FullAccess key typo, rewriting for better understanding (#390) --- specs/DataStructures/AccessKey.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/specs/DataStructures/AccessKey.md b/specs/DataStructures/AccessKey.md index 9ec66c3ae..b18ad4fca 100644 --- a/specs/DataStructures/AccessKey.md +++ b/specs/DataStructures/AccessKey.md @@ -15,7 +15,7 @@ pub struct AccessKey { } ``` -There are 2 types of `AccessKeyPermission` in Near currently: `FullAccess` and `FunctionCall`. `FunctionCall` grants a permission to issue any action on account like [DeployContract](Transaction.md#DeployContract), [Transfer](Transaction.md#Transfer) tokens to other account, call functions [FunctionCall](Transaction.md#FunctionCall), [Stake](Transaction.md#Stake) and even delete account [DeleteAccountAction](Transaction.md#DeleteAccountAction). `FullAccess` also allow to manage access keys. `AccessKeyPermission::FunctionCall` limits to do only contract calls. +There are 2 types of `AccessKeyPermission` in Near currently: `FullAccess` and `FunctionCall`. `FullAccess` grants permission to request any action on an account like [DeployContract](Transaction.md#DeployContract), [Transfer](Transaction.md#Transfer) tokens to other account, calling functions on smart contracts [FunctionCall](Transaction.md#FunctionCall), [Stake](Transaction.md#Stake) and even delete accounts [DeleteAccountAction](Transaction.md#DeleteAccountAction). `FullAccess` also allows managing access keys. `AccessKeyPermission::FunctionCall` is limited to only having permission to call non-payable methods on contracts. ```rust pub enum AccessKeyPermission { From 9e8603dde766e3a7ffd1d3b635e8815a02773920 Mon Sep 17 00:00:00 2001 From: mzhangmzz <34969888+mzhangmzz@users.noreply.github.com> Date: Wed, 14 Sep 2022 11:58:51 -0400 Subject: [PATCH 063/150] NEPs on how to split states of shards for resharding (#241) --- specs/Proposals/0040-split-states.md | 375 +++++++++++++++++++++++++++ 1 file changed, 375 insertions(+) create mode 100644 specs/Proposals/0040-split-states.md diff --git a/specs/Proposals/0040-split-states.md b/specs/Proposals/0040-split-states.md new file mode 100644 index 000000000..32b777a81 --- /dev/null +++ b/specs/Proposals/0040-split-states.md @@ -0,0 +1,375 @@ +- Proposal Name: Splitting States for Simple Nightshade +- Start Date: 2021-07-19 +- NEP PR: [near/NEPs#241](https://github.com/near/NEPs/pull/241) +- Issue(s): [near/NEPs#225](https://github.com/near/NEPs/issues/225) [near/nearcore#4419](https://github.com/near/nearcore/issues/4419) + +# Summary +[summary]: #summary + +This proposal proposes a way to split each shard in the blockchain into multiple shards. + +Currently, the near blockchain only has one shard and it needs to be split into eight shards for Simple Nightshade. + +# Motivation +[motivation]: #motivation + +To enable sharding, specifically, phase 0 of Simple Nightshade, we need to find a way to split the current one shard state into eight shards. + +# Guide-level explanation +[guide-level-explanation]: #guide-level-explanation + +The proposal assumes that all validators track all shards and that challenges are not enabled. + +Suppose the new sharding assignment comes into effect at epoch T. + +State migration is done at epoch T-1, when the validators for epoch T are catching up states for the next epoch. +At the beginning of epoch T-1, they run state sync for the current shards if needed. +From the existing states, they build states for the new shards, then apply changes to the new states when they process the blocks in epoch T-1. + This whole process runs off-chain as the new states will be not included in blocks at epoch T-1. +At the beginning of epoch T, the new validators start to build blocks based on the new state roots. + +The change involves three parts. + +## Dynamic Shards +The first issue to address in splitting shards is the assumption that the current implementation of chain and runtime makes that the number of shards never changes. +This in turn involves two parts, how the validators know when and how sharding changes happen and how they store states of shards from different epochs during the transition. +The former is a protocol change and the latter only affects validators' internal states. + +### Protocol Change +Sharding config for an epoch will be encapsulated in a struct `ShardLayout`, which not only contains the number of shards, but also layout information to decide which account ids should be mapped to which shards. +The `ShardLayout` information will be stored as part of `EpochConfig`. +Right now, `EpochConfig` is stored in `EpochManager` and remains static accross epochs. +That will be changed in the new implementation so that `EpochConfig` can be changed according to protocol versions, similar to how `RuntimeConfig` is implemented right now. + +The switch to Simple Nightshade will be implemented as a protocol upgrade. +`EpochManager` creates a new `EpochConfig` for each epoch from the protocol version of the epoch. +When the protocol version is large enough and the `SimpleNightShade` feature is enabled, the `EpochConfig` will be use the `ShardLayout` of Simple Nightshade, otherwise it uses the genesis `ShardLayout`. +Since the protocol version and the shard information of epoch T will be determined at the end of epoch T-2, the validators will have time to prepare for states of the new shards during epoch T-1. + +Although not ideal, the `ShardLayout` for Simple Nightshade will be added as part of the genesis config in the code. +The genesis config file itself will not be changed, but the field will be set to a default value we specify in the code. +This process is as hacky as it sounds, but currently we have no better way to account for changing protocol config. +To completely solve this issue will be a hard problem by itself, thus we do not try to solve it in this NEP. + + +We will discuss how the sharding transition will be managed in the next section. + +### State Change +In epoch T-1, the validators need to maintain two versions of states for all shards, one for the current epoch, one that is split for the next epoch. +Currently, shards are identified by their `shard_id`, which is a number ranging from `0` to `NUM_SHARDS-1`.`shard_id` is also used as part of the indexing keys by which trie nodes are stored in the database. +However, when shards may change accross epochs, `shard_id` can no longer be used to uniquely identify states because new shards and old shards will share the same `shard_id`s under this representation. + +To solve this issue, the new proposal creates a new struct `ShardUId` as an unique identifier to reference shards accross epochs. +`ShardUId` will only be used for storing and managing states, for example, in `Trie` related structures, +In most other places in the code, it is clear which epoch the referenced shard belongs, and `ShardId` is enough to identify the shard. +There will be no change in the protocol level since `ShardId` will continue to be used in protocol level specs. + +`ShardUId` contains a version number and the corresponding `shard_id`. +```rust +pub struct ShardUId { + version: u32, + shard_id: u32, +} +``` +The version number is different between different shard layouts, to ensure `ShardUId`s for shards from different epochs are different. +`EpochManager` will be responsible for managing shard versions and `ShardUId` accross epochs. + +## Build New States +Currently, when receiving the first block of every epoch, validators start downloading states to prepare for the next epoch. +We can modify this existing process to make the validators build states for the new shards after they finish downloading states for the existing shards. +To build the new states, the validator iterates through all accounts in the current states and adds them to the new states one by one. + +## Update States +Similar to how validators usually catch up for the next epoch, the new states are updated as new blocks are processed. +The difference is that in epoch T-1, chunks are still sharded by the current sharding assignment, but the validators need to perform updates on the new states. +We cannot simply split transactions and receipts to the new shards and process updates on each new shard separately. +If we do so, since each shard processes transactions and receipts with their own gas limits, some receipts may be delayed in the new states but not in the current states, or the other way around. +That will lead to inconsistencies between the orderings by which transactions and receipts are applied to the current and new states. + +For example, for simplicity, assume there is only one shard A in epoch T-1 and there will be two shards B and C in epoch T. + To process a block in epoch T-1, shard A needs to process receipts 0, 1, .., 99 while in the new sharding assignments receipts 0, 2, …, 98 belong to shard B and receipts 1, 3, …, 99 belong to shard C. +Assume in shard A, the gas limit is hit after receipt 89 is processed, so receipts 90 to 99 are delayed. +To achieve the same processing result, shard B must process receipt 0, 2, …, 88 and delay 90, 92, ..., 98 and shard C must process receipt 1, 3, ..., 89 and delay receipts 91, 93, …, 99. +However, shard B and C have their own gas limits and which receipts will be processed and delayed cannot be guaranteed. + +Whether a receipt is processed in a block or delayed can affect the execution result of this receipt because transactions are charged and local receipts are processed before delayed receipts are processed. +For example, let’s assume Alice’s account has 0N now and Bob sends a transaction T1 to transfer 5N to Alice. +The transaction has been converted to a receipt R at block i-1 and sent to Alice's shard at block i. +Let's say Alice signs another transaction T2 to send 1N to Charlie and that transaction is included in block i+1. +Whether transaction T2 succeeds depends on whether receipt R is processed or delayed in block i. +If R is processed in block i, Alice’s account will have 5N before block i+1 and T2 will succeed while if R is delayed in block i, Alice’s account will have 0N and T2 will be declined. + +Therefore, the validators must still process transactions and receipts based on the current sharding assignment. +After the processing is finished, they can take the generated state changes to apply to the new states. + +# Reference-level explanation +[reference-level-explanation]: #reference-level-explanation +## Protocol-Level Shard Representation +### `ShardLayout` +```rust +pub enum ShardLayout { + V0(ShardLayoutV0), + V1(ShardLayoutV1), +} +``` +ShardLayout is a versioned struct that contains all information needed to decide which accounts belong to which shards. Note that `ShardLayout` only contains information at the protocol level, so it uses `ShardOrd` instead of `ShardId`. + +The API contains the following two functions. +#### `get_split_shards` +``` +pub fn get_split_shards(&self, parent_shard_id: ShardId) -> Option<&Vec> +``` +returns the children shards of shard `parent_shard_id` (we will explain parent-children shards shortly). Note that `parent_shard_id` is a shard from the last ShardLayout, not from `self`. The returned `ShardId` represents shard in the current shard layout. +This information is needed for constructing states for the new shards. + +We only allow adding new shards that are split from the existing shards. If shard B and C are split from shard A, we call shard A the parent shard of shard B and C. +For example, if epoch T-1 has a shard layout `shardlayout0` with two shards with `shard_ord` 0 and 1 and each of them will be split to two shards in `shardlayout1` in epoch T, then `shard_layout1.get_split_shards(0)` returns `[0,1]` and `shard_layout.get_split_shards(1)` returns `[2,3]`. + +#### `version` +```rust +pub fn version(&self) -> ShardVersion +``` +returns the version number of this shard layout. This version number is used to create `ShardUId` for shards in this `ShardLayout`. The version numbers must be different for all shard layouts used in the blockchain. + +#### `account_id_to_shard_id` +```rust +pub fn account_id_to_shard_id(account_id: &AccountId, shard_layout: ShardLayout) -> ShardId +``` +maps account id to shard id given a shard layout + +#### `ShardLayoutV0` +```rust +pub struct ShardLayoutV0 { + /// map accounts evenly accross all shards + num_shards: NumShards, +} +``` +A shard layout that maps accounts evenly accross all shards -- by calculate the hash of account id and mod number of shards. This is added to capture the current `account_id_to_shard_id` algorithm, to keep backward compatibility for some existing tests. `parent_shards` for `ShardLayoutV1` is always `None` and `version`is always `0`. + +#### `ShardLayoutV1` +```rust +pub struct ShardLayoutV1 { + /// num_shards = fixed_shards.len() + boundary_accounts.len() + 1 + /// Each account and all subaccounts map to the shard of position in this array. + fixed_shards: Vec, + /// The rest are divided by boundary_accounts to ranges, each range is mapped to a shard + boundary_accounts: Vec, + /// Parent shards for the shards, useful for constructing states for the shards. + /// None for the genesis shard layout + parent_shards: Option>, + /// Version of the shard layout, useful to uniquely identify the shard layout + version: ShardVersion, +} +``` +A shard layout that consists some fixed shards each of which is mapped to a fixed account and other shards which are mapped to ranges of accounts. This will be the ShardLayout used by Simple Nightshade. + +### `EpochConfig` +`EpochConfig` will contain the shard layout for the given epoch. + +```rust +pub struct EpochConfig { + // existing fields + ... + /// Shard layout of this epoch, may change from epoch to epoch + pub shard_layout: ShardLayout, +``` +### `AllEpochConfig` +`AllEpochConfig` stores a mapping from protocol versions to `EpochConfig`s. `EpochConfig` for a particular epoch can be retrieved from `AllEpochConfig`, given the protocol version of the epoch. For SimpleNightshade migration, it only needs to contain two configs. `AllEpochConfig` will be stored inside `EpochManager` to be used to construct `EpochConfig` for different epochs. + +```rust +pub struct AllEpochConfig { + genesis_epoch_config: Arc, + simple_nightshade_epoch_config: Arc, +} +``` +#### `for_protocol_version` +```rust +pub fn for_protocol_version(&self, protocol_version: ProtocolVersion) -> &Arc +``` +returns `EpochConfig` according to the given protocol version. `EpochManager` will call this function for every new epoch. + +### `EpochManager` +`EpochManager` will be responsible for managing `ShardLayout` accross epochs. As we mentioned, `EpochManager` stores an instance of `AllEpochConfig`, so it can returns the `ShardLayout` for each epoch. + +#### `get_shard_layout` +```rust +pub fn get_shard_layout(&mut self, epoch_id: &EpochId) -> Result<&ShardLayout, EpochError> +``` + +## Internal Shard Representation in Validators' State +### `ShardUId` +`ShardUId` is a unique identifier that a validator uses internally to identify shards from all epochs. It only exists inside a validator's internal state and can be different among validators, thus it should never be exposed to outside APIs. + +```rust +pub struct ShardUId { + pub version: ShardVersion, + pub shard_id: u32, +} +``` + +`version` in `ShardUId` comes from the version of `ShardLayout` that this shard belongs. This way, different shards from different shard layout will have different `ShardUId`s. + +### Database storage +The following database columns are stored with `ShardId` as part of the database key, it will be replaced by `ShardUId` +- ColState +- ColChunkExtra +- ColTrieChanges + +#### `TrieCachingStorage` +Trie storage will contruct database key from `ShardUId` and hash of the trie node. +##### `get_shard_uid_and_hash_from_key` +```rust +fn get_shard_uid_and_hash_from_key(key: &[u8]) -> Result<(ShardUId, CryptoHash), std::io::Error> +``` +##### `get_key_from_shard_uid_and_hash` +```rust +fn get_key_from_shard_uid_and_hash(shard_uid: ShardUId, hash: &CryptoHash) -> [u8; 40] +``` + + +## Build New States +The following method in `Chain` will be added or modified to split a shard's current state into multiple states. + +### `build_state_for_split_shards` +```rust +pub fn build_state_for_split_shards(&mut self, sync_hash: &CryptoHash, shard_id: ShardId) -> Result<(), Error> +``` +builds states for the new shards that the shard `shard_id` will be split to. +After this function is finished, the states for the new shards should be ready in `ShardTries` to be accessed. + +### `run_catchup` +```rust +pub fn run_catchup(...) { + ... + match state_sync.run( + ... + )? { + StateSyncResult::Unchanged => {} + StateSyncResult::Changed(fetch_block) => {...} + StateSyncResult::Completed => { + // build states for new shards if shards will change and we will track some of the new shards + if self.runtime_adapter.will_shards_change_next_epoch(epoch_id) { + let mut parent_shards = HashSet::new(); + let (new_shards, mapping_to_parent_shards) = self.runtime_adapter.get_shards_next_epoch(epoch_id); + for shard_id in new_shards { + if self.runtime_adapter.will_care_about_shard(None, &sync_hash, shard_id, true) { + parent_shards.insert(mapping_to_parent_shards.get(shard_id)?); + } + } + for shard_id in parent_shards { + self.split_shards(me, &sync_hash, shard_id); + } + } + ... + } + } + ... +} +``` + +## Update States +### `split_state_changes` +```rust +split_state_changes(shard_id: ShardId, state_changes: &Vec) -> HashMap> +``` +splits state changes to be made to a current shard to changes that should be applid to the new shards. Note that this function call can take a long time. To avoid blocking the client actor from processing and producing blocks for the current epoch, it should be called from a separate thread. Unfortunately, as of now, catching up states and catching up blocks are both run in client actor. They should be moved to a separate actor. However, that can be a separate project, although this NEP will depend on that project. In fact, the issue has already been discussed in [#3201](https://github.com/near/nearcore/issues/3201). + +### `apply_chunks` +`apply_chunks` will be modified so that states of the new shards will be updated when processing chunks. + In `apply_chunks`, after processing each chunk, the state changes in `apply_results` are sorted into changes to new shards. +At the end, we apply these changes to the new shards. +```rust +fn apply_chunks(...) -> Result<(), Error> { + ... + for (shard_id, (chunk_header, prev_chunk_header)) in + (block.chunks().iter().zip(prev_block.chunks().iter())).enumerate() + { + ... + let apply_result = ...; + // split states to new shards + let changes_to_new_shards = self.split_state_changes(trie_changes); + // apply changes_to_new_changes to the new shards + for (new_shard_id, new_state_changes) in changes_to_new_states { + // locate the state for the new shard + let trie = self.get_trie_for_shard(new_shard_id); + let chunk_extra = + self.chain_store_update.get_chunk_extra(&prev_block.hash(), new_shard_id)?.clone(); + let mut state_update = TrieUpdate::new(trie.clone(), *chunk_extra.state_root()); + + // update the state + for state_change in new_state_changes { + state_update.set(state_change.trie_key, state_change.value); + } + state_update.commit(StateChangeCause::Resharding); + let (trie_changes, state_changes) = state_update.finalize()?; + + // save the TrieChanges and ChunkExtra + self.chain_store_update.save_trie_changes(WrappedTrieChanges::new( + self.tries, + new_shard_id, + trie_changes, + state_changes, + *block.hash(), + )); + self.chain_store_update.save_chunk_extra( + &block.hash(), + new_shard_id, + ChunkExtra::new(&trie_changes.new_root, CryptoHash::default(), Vec::new(), 0, 0, 0), + ); + } + } + ... + +} +``` + +## Garbage Collection +The old states need to be garbage collected after the resharding finishes. The garbage collection algorithm today won't automatically handle that. (#TODO: why?) + +Although we need to handle garbage collection eventually, it is not a pressing issue. Thus, we leave the discussion from this NEP for now and will add a detailed plan later. + +# Drawbacks +[drawbacks]: #drawbacks + +The drawback of this approach is that it will not work when challenges are enabled since challenges to the transition to the new states will be too large to construct or verify. +Thus, most of the change will likely be a one time use that only works for the Simple Nightshade transition, although part of the change involving `ShardId` may be reused in the future. + +# Rationale and alternatives +[rationale-and-alternatives]: #rationale-and-alternatives +- Why is this design the best in the space of possible designs? + - It is the best because its implementation is the simplest. + Considering we want to launch Simple Nightshade as soon as possible by Q4 2021 and we will not enable challenges any time soon, this is the best option we have. +- What other designs have been considered and what is the rationale for not choosing them? + - We have considered other designs that change states incrementally and keep state roots on chain to make it compatible with challenges. +However, the implementation of those approaches are overly complicated and does not fit into our timeline for launching Simple Nightshade. +- What is the impact of not doing this? + - The impact will be the delay of launching Simple Nightshade, or no launch at all. + +# Unresolved questions +[unresolved-questions]: #unresolved-questions +- What parts of the design do you expect to resolve through the NEP process before this gets merged? + - Garbage collection + - State Sync? +- What parts of the design do you expect to resolve through the implementation of this feature before stabilization? + - There might be small changes in the detailed implementations or specifications of some of the functions described above, but the overall structure will not be changed. +- What related issues do you consider out of scope for this NEP that could be addressed in the future independently of the solution that comes out of this NEP? + - One issue that is related to this NEP but will be resolved indepdently is how trie nodes are stored in the database. + Right now, it is a combination of `shard_id` and the node hash. + Part of the change proposed in this NEP regarding `ShardId` is because of this. + Plans on how to only store the node hash as keys are being discussed [here](https://github.com/near/nearcore/issues/4527), but it will happen after the Simple Nightshade migration since completely solving the issue will take some careful design and we want to prioritize launching Simple Nightshade for now. + - Another issue that is not part of this NEP but must be solved for this NEP to work is to move expensive computation related to state sync / catch up into a separate actor [#3201](https://github.com/near/nearcore/issues/3201). + - Lastly, we should also build a better mechanism to deal with changing protocol config. The current way of putting changing protocol config in the genesis config and changing how the genesis config file is parsed is not a long term solution. + +# Future possibilities +[future-possibilities]: #future-possibilities +## Extension +In the future, when challenges are enabled, resharding and state upgrade should be implemented on-chain. +## Affected Projects +- +## Pre-mortem +- Building and catching up new states takes longer than one epoch to finish. +- Protocol version switched back to pre simple nightshade +- Validators cannot track shards properly after resharding +- Genesis State +- Must load the correct `shard_version` +- ShardTracker? From 1b05a4bab3426746cbaf11f2f7b7c901b3a1adcf Mon Sep 17 00:00:00 2001 From: zhan <67903793+zlog-in@users.noreply.github.com> Date: Mon, 26 Sep 2022 16:11:17 +0200 Subject: [PATCH 064/150] chore(nearprotocol): aligned the error wording in the Transactions.md (#398) --- specs/RuntimeSpec/Transactions.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/specs/RuntimeSpec/Transactions.md b/specs/RuntimeSpec/Transactions.md index d03103eb8..505b2ec73 100644 --- a/specs/RuntimeSpec/Transactions.md +++ b/specs/RuntimeSpec/Transactions.md @@ -77,7 +77,7 @@ error is returned. /// The number of actions exceeded the given limit. TotalNumberOfActionsExceeded { total_number_of_actions: u64, limit: u64 } ``` -is returned. +error is returned. - Among the actions in the transaction, whether `DeleteAccount`, if present, is the last action. If not, a ```rust /// The delete action must be a final action in transaction From 6f03760ed83f20c60f712d85635b2a004c7a93e7 Mon Sep 17 00:00:00 2001 From: Robert Zaremba Date: Mon, 26 Sep 2022 15:29:16 +0100 Subject: [PATCH 065/150] chore(NEP-141): Added Robert Zaremba to the authors (#394) NEP-141 came through my proposal https://github.com/near/NEPs/issues/136 as a more robust Interface for Fungible Tokens and reflection from the previous NEP-122. Prior to that we were discussing the pitfalls for ERC20 and a better solution that would serve NEAR ecosystem needs. See Rationale described in https://github.com/near/NEPs/issues/136. I was part of the core research (together with Evgeny, @oysterpack and @luciotato) designing the NEP-141, where we hardened the design by analyzing the storage use cases and metadata management. --- neps/nep-0141.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/neps/nep-0141.md b/neps/nep-0141.md index 609258da1..4c7f0ea26 100644 --- a/neps/nep-0141.md +++ b/neps/nep-0141.md @@ -1,7 +1,7 @@ --- NEP: 141 Title: Fungible Token Standard -Author: Evgeny Kuzyakov , @oysterpack +Author: Evgeny Kuzyakov , Robert Zaremba <@robert-zaremba>, @oysterpack DiscussionsTo: https://github.com/near/NEPs/issues/141 Status: Final Type: Standards Track @@ -471,4 +471,4 @@ Copyright and related rights waived via [CC0](https://creativecommons.org/public [Storage Management]: ../specs/Standards/StorageManagement.md [FT Metadata]: ../specs/Standards/Tokens/FungibleToken/Metadata.md -[FT Core]: ../specs/Standards/Tokens/FungibleToken/Core.md \ No newline at end of file +[FT Core]: ../specs/Standards/Tokens/FungibleToken/Core.md From 68085ce82c18f7e1641fc36c72661a91babfbc8e Mon Sep 17 00:00:00 2001 From: Nate Morris Date: Mon, 26 Sep 2022 10:30:10 -0400 Subject: [PATCH 066/150] chore(nearprotocol): Fixed grammar in Architecture.md (#395) --- specs/Architecture.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/specs/Architecture.md b/specs/Architecture.md index ae205a18f..5728dfe1d 100644 --- a/specs/Architecture.md +++ b/specs/Architecture.md @@ -90,7 +90,7 @@ Interestingly, the following concepts are for the blockchain layer only and the - Blocks or chunks -- the runtime does not know that the receipts that it processes constitute a chunk and that the output receipts will be used in other chunks. From the runtime perspective it consumes and outputs batches of transactions and receipts; - Consensus -- the runtime does not know how consistency of the state is maintained; -- Communication -- the runtime don't know anything about the current network topology. Receipt has only a receiver_id (a recipient account), but knows nothing about the destination shard, so it's a responsibility of a blockchain layer to route a particular receipt. +- Communication -- the runtime does not know anything about the current network topology. Receipt has only a receiver_id (a recipient account), but knows nothing about the destination shard, so it's a responsibility of the blockchain layer to route a particular receipt. ## Runtime Layer Concepts From c02d12e5486555c58dd9f6c0e37a92399d3445d5 Mon Sep 17 00:00:00 2001 From: Nate Morris Date: Mon, 26 Sep 2022 10:31:24 -0400 Subject: [PATCH 067/150] chore(nearprotocol): Fixed punctuation in Architecture.md (#396) --- specs/Architecture.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/specs/Architecture.md b/specs/Architecture.md index 5728dfe1d..d3ed4daeb 100644 --- a/specs/Architecture.md +++ b/specs/Architecture.md @@ -94,5 +94,5 @@ Interestingly, the following concepts are for the blockchain layer only and the ## Runtime Layer Concepts -- Fees and rewards -- fees and rewards are neatly encapsulated in the runtime layer. The blockchain layer, however +- Fees and rewards -- fees and rewards are neatly encapsulated in the runtime layer. The blockchain layer, however, has an indirect knowledge of them through the computation of the tokens-to-gas exchange rate and the inflation. From 74a4fedd35f4180326da8ef7eb862ff0f61cac37 Mon Sep 17 00:00:00 2001 From: Vlad Frolov Date: Mon, 26 Sep 2022 16:53:58 +0200 Subject: [PATCH 068/150] chore: Updated CODEOWNERS to require NEP Moderators review --- CODEOWNERS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CODEOWNERS b/CODEOWNERS index 3e9bdbbaf..252fe2b8d 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -1 +1 @@ -* @near/nep-editors +* @near/nep-moderators From 666bc95beef8040d87f5f2f5617762e249f8a475 Mon Sep 17 00:00:00 2001 From: robin-near <111538878+robin-near@users.noreply.github.com> Date: Mon, 26 Sep 2022 16:36:31 -0700 Subject: [PATCH 069/150] Fix some formatting issues in Consensus.md (#388) --- specs/ChainSpec/Consensus.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/specs/ChainSpec/Consensus.md b/specs/ChainSpec/Consensus.md index f4d9e42ce..8651d49dd 100644 --- a/specs/ChainSpec/Consensus.md +++ b/specs/ChainSpec/Consensus.md @@ -2,7 +2,7 @@ ## Definitions and notation -For the purpose of maintaining consensus, transactions are grouped into *blocks*. There is a single preconfigured block $G$ called *genesis block*. Every block except $G$ has a link pointing to the *previous block* $\operatorname{prev}(B)$, where $$B$$ is the block, and $G$ is reachable from every block by following those links (that is, there are no cycles). +For the purpose of maintaining consensus, transactions are grouped into *blocks*. There is a single preconfigured block $G$ called *genesis block*. Every block except $G$ has a link pointing to the *previous block* $\operatorname{prev}(B)$, where $B$ is the block, and $G$ is reachable from every block by following those links (that is, there are no cycles). The links between blocks give rise to a partial order: for blocks $A$ and $B$, $A < B$ means that $A \ne B$ and $A$ is reachable from $B$ by following links to previous blocks, and $A \le B$ means that $A < B$ or $A = B$. The relations $>$ and $\ge$ are defined as the reflected versions of $<$ and $\le$, respectively. Finally, $A \sim B$ means that either $A < B$, $A = B$ or $A > B$, and $A \nsim B$ means the opposite. @@ -167,11 +167,11 @@ A block $B$ is final in $\operatorname{chain}(T)$, where $T \ge B$, when either ## Epoch switches -There's a parameter $epoch_length \ge 3$ that defines the minimum length of an epoch. Suppose that a particular epoch $e_cur$ started at height $h$, and say the next epoch will be $e_next$. Say $\operatorname{BP}(e)$ is a set of block producers in epoch $e$. Say $\operatorname{last_final}(T)$ is the highest final block in $\operatorname{chain}(T)$. The following are the rules of what blocks contain approvals from what block producers, and belong to what epoch. +There's a parameter $\operatorname{epoch\_ length} \ge 3$ that defines the minimum length of an epoch. Suppose that a particular epoch $e_{cur}$ started at height $h$, and say the next epoch will be $e_{next}$. Say $\operatorname{BP}(e)$ is a set of block producers in epoch $e$. Say $\operatorname{last\_ final}(T)$ is the highest final block in $\operatorname{chain}(T)$. The following are the rules of what blocks contain approvals from what block producers, and belong to what epoch. -- Any block $B$ with $\operatorname{h}(\operatorname{prev}(B)) < h+epoch_length-3$ is in the epoch $e_cur$ and must have approvals from more than $^2\!/_3$ of $\operatorname{BP}(e_cur)$ (stake-weighted). -- Any block $B$ with $\operatorname{h}(\operatorname{prev}(B)) \ge h+epoch_length-3$ for which $\operatorname{h}(\operatorname{last_final}(\operatorname{prev}(B))) < h+epoch_length-3$ is in the epoch $e_cur$ and must logically include approvals from both more than $^2\!/_3$ of $\operatorname{BP}(e_cur)$ and more than $^2\!/_3$ of $\operatorname{BP}(e_next)$ (both stake-weighted). -- The first block $B$ with $\operatorname{h}(\operatorname{last_final}(\operatorname{prev}(B))) >= h+epoch_length-3$ is in the epoch $e_next$ and must logically include approvals from more than $^2\!/_3$ of $\operatorname{BP}(e_next)$ (stake-weighted). +- Any block $B$ with $\operatorname{h}(\operatorname{prev}(B)) < h+\operatorname{epoch\_ length}-3$ is in the epoch $e_{cur}$ and must have approvals from more than $^2\!/_3$ of $\operatorname{BP}(e_{cur})$ (stake-weighted). +- Any block $B$ with $\operatorname{h}(\operatorname{prev}(B)) \ge h+\operatorname{epoch\_ length}-3$ for which $\operatorname{h}(\operatorname{last\_ final}(\operatorname{prev}(B))) < h+\operatorname{epoch\_ length}-3$ is in the epoch $e_{cur}$ and must logically include approvals from both more than $^2\!/_3$ of $\operatorname{BP}(e_{cur})$ and more than $^2\!/_3$ of $\operatorname{BP}(e_{next})$ (both stake-weighted). +- The first block $B$ with $\operatorname{h}(\operatorname{last\_ final}(\operatorname{prev}(B))) >= h+\operatorname{epoch\_ length}-3$ is in the epoch $e_{next}$ and must logically include approvals from more than $^2\!/_3$ of $\operatorname{BP}(e_{next})$ (stake-weighted). (see the definition of *logically including* approvals in [approval requirements](#approvals-requirements)) @@ -189,7 +189,7 @@ Note that with the implementation above a honest block producer can never produc Case 1: Blocks $B_c$, $T_1$ and $T_2$ are all in the same epoch. Because the set of blocks in a given epoch in a given chain is a contiguous range, all blocks between them (specifically, all blocks $X$ such that $B_c < X < T_1$ or $B_c < X < T_2$) are also in the same epoch, so all those blocks include approvals from more than $^2\!/_3$ of the block producers in that epoch. -Case 2: Blocks $B_c$, $T_1$ and $T_2$ are not all in the same epoch. Suppose that $B_c$ and $T_1$ are in different epochs. Let $E$ be the epoch of $T_1$ and $E_p$ be the preceding epoch ($T_1$ cannot be in the same epoch as the genesis block). Let $R$ and $S$ be the first and the last block of $E_p$ in $\operatorname{chain}(T_1)$. Then, there must exist a block $F$ in epoch $E_p$ such that $\operatorname{h}(F)+2 = \operatorname{h}(S) < \operatorname{h}(T_1)$. Because $\operatorname{h}(F) < \operatorname{h}(T_1)-2$, we have $F < B_1$, and since there are no final blocks $X$ such that $B_c < X < B_1$, we conclude that $F \le B_c$. Because there are no epochs between $E$ and $E_p$, we conclude that $B_c$ is in epoch $E_p$. Also, $\operatorname{h}(B_c) \ge \operatorname{h}(F) \ge \operatorname{h}(R)+epoch_length-3$. Thus, any block after $B_c$ and until the end of $E$ must include approvals from more than $^2\!/_3$ of the block producers in $E$. Applying the same argument to $\operatorname{chain}(T_2)$, we can determine that $T_2$ is either in $E$ or $E_p$, and in both cases all blocks $X$ such that $B_c < X \le T_2$ include approvals from more than $^2\!/_3$ of block producers in $E$ (the set of block producers in $E$ is the same in $\operatorname{chain}(T_1)$ and $\operatorname{chain}(T_2)$ because the last block of the epoch preceding $E_p$, if any, is before $B_c$ and thus is shared by both chains). The case where $B_c$ and $T_1$ are in the same epoch, but $B_c$ and $T_2$ are in different epochs is handled similarly. Thus, the lemma is proven. +Case 2: Blocks $B_c$, $T_1$ and $T_2$ are not all in the same epoch. Suppose that $B_c$ and $T_1$ are in different epochs. Let $E$ be the epoch of $T_1$ and $E_p$ be the preceding epoch ($T_1$ cannot be in the same epoch as the genesis block). Let $R$ and $S$ be the first and the last block of $E_p$ in $\operatorname{chain}(T_1)$. Then, there must exist a block $F$ in epoch $E_p$ such that $\operatorname{h}(F)+2 = \operatorname{h}(S) < \operatorname{h}(T_1)$. Because $\operatorname{h}(F) < \operatorname{h}(T_1)-2$, we have $F < B_1$, and since there are no final blocks $X$ such that $B_c < X < B_1$, we conclude that $F \le B_c$. Because there are no epochs between $E$ and $E_p$, we conclude that $B_c$ is in epoch $E_p$. Also, $\operatorname{h}(B_c) \ge \operatorname{h}(F) \ge \operatorname{h}(R)+\operatorname{epoch\_ length}-3$. Thus, any block after $B_c$ and until the end of $E$ must include approvals from more than $^2\!/_3$ of the block producers in $E$. Applying the same argument to $\operatorname{chain}(T_2)$, we can determine that $T_2$ is either in $E$ or $E_p$, and in both cases all blocks $X$ such that $B_c < X \le T_2$ include approvals from more than $^2\!/_3$ of block producers in $E$ (the set of block producers in $E$ is the same in $\operatorname{chain}(T_1)$ and $\operatorname{chain}(T_2)$ because the last block of the epoch preceding $E_p$, if any, is before $B_c$ and thus is shared by both chains). The case where $B_c$ and $T_1$ are in the same epoch, but $B_c$ and $T_2$ are in different epochs is handled similarly. Thus, the lemma is proven. Now back to the theorem. Without loss of generality, assume that $\operatorname{h}(B_1) \le \operatorname{h}(B_2)$. On the one hand, if $\operatorname{chain}(T_2)$ doesn't include a block at height $\operatorname{h}(B_1)$, then the first block at height greater than $\operatorname{h}(B_1)$ must include skips from more than $^2\!/_3$ of the block producers in $E$ which conflict with endorsements in $\operatorname{prev}(T_1)$, therefore, more than $^1\!/_3$ of the block producers in $E$ must have signed conflicting skip and endorsement. Similarly, if $\operatorname{chain}(T_2)$ doesn't include a block at height $\operatorname{h}(B_1)+1$, more than $^1\!/_3$ of the block producers in $E$ signed both an endorsement in $T_1$ and a skip in the first block in $\operatorname{chain}(T_2)$ at height greater than $\operatorname{h}(T_1)$. On the other hand, if $\operatorname{chain}(T_2)$ includes both a block at height $\operatorname{h}(B_1)$ and a block at height $\operatorname{h}(B_1)+1$, the latter must include endorsements for the former, which conflict with endorsements for $B_1$. Therefore, more than $^1\!/_3$ of the block producers in $E$ must have signed conflicting endorsements. Thus, the theorem is proven. From c6b29a4fbd058563f6da3de454578f4395ab4f99 Mon Sep 17 00:00:00 2001 From: Bowen Wang Date: Wed, 5 Oct 2022 04:55:30 -0700 Subject: [PATCH 070/150] recalibrate inflation (#132) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit # Summary This proposal changes inflation calculation to be based on the during of the epoch in seconds instead of relying on number of blocks that are expected to be produced in a year. # Motivation Currently on mainnet blocks are produced usually at between 1.2 and 1.3 per second, which is great. However, when we calculate inflation per epoch, we use the following formula (note: this excludes the tokens burnt in transaction fees): ``` inflation = total_supply * yearly_inflate_rate * epoch_length / expected_num_blocks_per_year ``` where `expected_num_blocks_per_year` is a genesis parameter currently set to 31536000, i.e, a block every second. Since blocks are produced faster that, expected_num_blocks_per_year is smaller than the actual value, which means that, at the current rate, we will have ~20% more inflation than expected. # Guide-level explanation Calculating the inflation based on blocks isn’t the most reliably way to begin with. Even though currently epochs are shorter than expected, they could, in some cases, be longer than expected if there are a few validators offline for the entire duration of the epoch. To address this, I propose that we change the inflation calculation based on time elapsed instead of number of blocks. More specifically, this proposal only requires changing the inflation calculation to ``` inflation = total_supply * yearly_inflation_rate * duration_of_epoch_in_seconds / num_seconds_in_a_year ``` This is essentially still a first-order Taylor approximation of the target inflation rate, in the similar vein as the original calculation. However, it is more accurate and is less subject to the perturbation of the epoch time. # Reference-level explanation * Duration of an epoch can be easily calculated when we finalize the epoch by subtracting the timestamp of the first block of the epoch from that of the last block. * Upgrade process is relatively straightforward. We simply switch to the new way of calculating inflation when the protocol version changes. * For simplicity, we set `num_seconds_in_a_year` as a constant `31536000`. For leap year this will be not entirely accurate but the difference is negligibly small. --- specs/Economics/README.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/specs/Economics/README.md b/specs/Economics/README.md index 82a9584c2..8f608ee69 100644 --- a/specs/Economics/README.md +++ b/specs/Economics/README.md @@ -46,11 +46,12 @@ The protocol sets a ceiling for the maximum issuance of tokens, and dynamically | Name | Description | | - | - | -| `reward[t]` | `totalSupply[t]` * ((`1 + REWARD_PCT_PER_YEAR`) ** (`1/EPOCHS_A_YEAR`) - `1`) | +| `reward[t]` | `totalSupply[t]` * `REWARD_PCT_PER_YEAR` * `epochTime[t]` / `NUM_SECONDS_IN_A_YEAR` | | `epochFee[t]` | `sum([(1 - DEVELOPER_PCT_PER_YEAR) * block.txFee + block.stateFee for block in epoch[t]])` | | `issuance[t]` | The amount of token issued at a certain epoch[t], `issuance[t] = reward[t] - epochFee[t]` | -Where `totalSupply[t]` is the total number of tokens in the system at a given time *t*. +Where `totalSupply[t]` is the total number of tokens in the system at a given time *t* and `epochTime[t]` is the +duration of the epoch in seconds. If `epochFee[t] > reward[t]` the issuance is negative, thus the `totalSupply[t]` decreases in given epoch. ## Transaction Fees From 88ac50c6fa988ff1b1e1ed499d59fcc8494e70fe Mon Sep 17 00:00:00 2001 From: Blas Rodriguez Irizar Date: Thu, 6 Oct 2022 11:29:58 +0200 Subject: [PATCH 071/150] NEP-364: Efficient signature verification host functions (#364) Efficient signature verification and hashing precompile functions Co-authored-by: Marcelo Fornet Co-authored-by: Simonas Kazlauskas --- neps/nep-0364.md | 200 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 200 insertions(+) create mode 100644 neps/nep-0364.md diff --git a/neps/nep-0364.md b/neps/nep-0364.md new file mode 100644 index 000000000..8cdc93797 --- /dev/null +++ b/neps/nep-0364.md @@ -0,0 +1,200 @@ +--- +NEP: 364 +Title: Efficient signature verification and hashing precompile functions +Author: Blas Rodriguez Irizar +DiscussionsTo: https://github.com/nearprotocol/neps/pull/364 +Status: Draft +Type: Runtime Spec +Category: Contract +Created: 15-Jun-2022 +--- + +## Summary + +This NEP introduces the request of adding into the NEAR runtime a pre-compiled +function used to verify signatures that can help IBC compatible light clients run on-chain. + +## Motivation + +Signature verification and hashing are ubiquitous operations in light clients, +especially in PoS consensus mechanisms. Based on Polkadot's consensus mechanism +there will be a need for verification of ~200 signatures every minute +(Polkadot’s authority set is ~300 signers and it may be increased in the future: https://polkadot.polkassembly.io/referendum/16). + +Therefore, a mechanism to perform these operations cost-effectively in terms +of gas and speed would be highly beneficial to have. Currently, NEAR does not have any native signature verification toolbox. +This implies that a light client operating inside NEAR will have to import a library +compiled to WASM as mentioned in [Zulip](https://near.zulipchat.com/#narrow/stream/295302-general/topic/light_client). + +Polkadot uses [three different cryptographic schemes](https://wiki.polkadot.network/docs/learn-keys) +for its keys/accounts, which also translates into different signature types. However, for this NEP the focus is on: + +- The vanilla ed25519 implementation uses Schnorr signatures. + +## Rationale and alternatives + +Add a signature verification signatures function into the runtime as host functions. + +- ED25519 signature verification function using `ed25519_dalek` crates into NEAR runtime as pre-compiled functions. + +Benchmarks were run using a signature verifier smart contract on-chain importing the aforementioned functions from +widespread used crypto Rust crates. The biggest pitfall of these functions running wasm code instead of native +is performance and gas cost. Our [benchmarks](https://github.com/blasrodri/near-test) show the following results: + +```log +near call sitoula-test.testnet verify_ed25519 '{"signature_p1": [145,193,203,18,114,227,14,117,33,213,121,66,130,14,25,4,36,120,46,142,226,215,7,66,122,112,97,30,249,135,61,165], "signature_p2": [221,249,252,23,105,40,56,70,31,152,236,141,154,122,207,20,75,118,79,90,168,6,221,122,213,29,126,196,216,104,191,6], "msg": [107,97,106,100,108,102,107,106,97,108,107,102,106,97,107,108,102,106,100,107,108,97,100,106,102,107,108,106,97,100,115,107], "iterations": 10}' --accountId sitoula-test.testnet --gas 300000000000000 +# transaction id DZMuFHisupKW42w3giWxTRw5nhBviPu4YZLgKZ6cK4Uq +``` + +With `iterations = 130` **all these calls return ExecutionError**: `'Exceeded the maximum amount of gas allowed to burn per contract.'` +With iterations = 50 these are the results: + +``` +ed25519: tx id 6DcJYfkp9fGxDGtQLZ2m6PEDBwKHXpk7Lf5VgDYLi9vB (299 Tgas) +``` + +- Performance in wall clock time when you compile the signature validation library directly from rust to native. + Here are the results on an AMD Ryzen 9 5900X 12-Core Processor machine: + +``` +# 10k signature verifications +ed25519: took 387ms +``` + +- Performance in wall clock time when you compile the library into wasm first and then use the single-pass compiler in Wasmer 1 to then compile to native. + +``` +ed25519: took 9926ms +``` + +As an extra data point, when passing `--enable-simd` instead of `--singlepass` + +``` +ed25519: took 3085ms +``` + +Steps to reproduce: +commit: `31cf97fb2e155d238308f062c4b92bae716ac19f` in `https://github.com/blasrodri/near-test` + +```sh +# wasi singlepass +cargo wasi build --bin benches --release +wasmer compile --singlepass ./target/wasm32-wasi/release/benches.wasi.wasm -o benches_singlepass +wasmer run ./benches_singlepass +``` + +```sh +# rust native +cargo run --bin benches --release +``` + +Overall: the difference between the two versions (native vs wasi + singlepass is) + +``` +ed25519: 25.64x slower +``` + +### What is the impact of not doing this? + +Costs of running IBC-compatible trustless bridges would be very high. Plus, the fact that signature verification +is such an expensive operation will force the contract to split the process of batch verification of signatures +into multiple transactions. + +### Why is this design the best in the space of possible designs? + +Adding existing proved and vetted crypto crates into the runtime is a safe workaround. It will boost performance +between 20-25x according to our benchmarks. This will both reduce operating costs significantly and will also +enable the contract to verify all the signatures in one transaction, which will simplify the contract design. + +### What other designs have been considered and what is the rationale for not choosing them? + +One possible alternative would be to improve the runtime implementation so that it can compile WASM code to a sufficiently +fast machine code. Even when it may not be as fast as LLVM native produced code it could still be acceptable for +these types of use cases (CPU intensive functions) and will certainly avoid the need of adding host functions. +The effort of adding such a feature will be significantly higher than adding these host functions one by one. +But on the other side, it will decrease the need of including more host functions in the future. + +Another alternative is to deal with the high cost of computing/verifying these signatures in some other manner. +Decreasing the overall cost of gas and increasing the limits of gas available to attach to the contract could be a possibility. +Introducing such modification for some contracts, and not for some others can be rather arbitrary +and not straightforward in the implementation, but an alternative nevertheless. + +## Specification + +This NEP aims to introduce the following host function: + +```rust +extern "C"{ + +/// Verify an ED25519 signature given a message and a public key. +/// Ed25519 is a public-key signature system with several attractive features +/// +/// Proof of Stake Validator sets can contain different signature schemes. +/// Ed25519 is one of the most used ones across blockchains, and hence it's importance to be added. +/// For further reference, visit: https://ed25519.cr.yp.to +/// # Returns +/// - 1 if the signature was properly verified +/// - 0 if the signature failed to be verified +/// +/// # Cost +/// +/// Each input can either be in memory or in a register. Set the length of the input to `u64::MAX` +/// to declare that the input is a register number and not a pointer. +/// Each input has a gas cost input_cost(num_bytes) that depends on whether it is from memory +/// or from a register. It is either read_memory_base + num_bytes * read_memory_byte in the +/// former case or read_register_base + num_bytes * read_register_byte in the latter. This function +/// is labeled as `input_cost` below. +/// +/// `input_cost(num_bytes_signature) + input_cost(num_bytes_message) + input_cost(num_bytes_public_key) +/// ed25519_verify_base + ed25519_verify_byte * num_bytes_message` +/// +/// # Errors +/// +/// If the signature size is not equal to 64 bytes, or public key length is not equal to 32 bytes, contract execution is terminated with an error. + fn ed25519_verify( + sig_len: u64, + sig_ptr: u64, + msg_len: u64, + msg_ptr: u64, + pub_key_len: u64, + pub_key_ptr: u64, + ) -> u64; +``` + +And a `rust-sdk` possible implementation could look like this: + +```rs + +pub fn ed25519_verify(sig: &ed25519::Signature, msg: &[u8], pub_key: &ed25519::Public) -> bool; + +``` +Once this NEP is approved and integrated, these functions will be available in the `near_sdk` crate in the +`env` module. + +[This blog post](https://hdevalence.ca/blog/2020-10-04-its-25519am) describes the various ways in which the existing Ed25519 implementations differ in practice. The behavior that this proposal uses, which is shared by Go `crypto/ed25519`, Rust `ed25519-dalek` (using `verify` function with `legacy_compatibility` feature turned off) and several others, makes the following decisions: + +- The encoding of the values `R` and `s` must be canonical, while the encoding of `A` doesn't need to. +- The verification equation is `R = [s]B − [k]A`. +- No additional checks are performed. In particular, the points outside of the order-l subgroup are accepted, as are the points in the torsion subgroup. + +Note that this implementation only refers to the `verify` function in the +crate `ed25519-dalek` and **not** `verify_strict` or `verify_batch`. + +## Security Implications (Optional) + +We have chosen this crate because it is already integrated into `nearcore`. + +## Unresolved Issues (Optional) + +- What parts of the design do you expect to resolve through the NEP process before this gets merged? + Both the function signatures and crates are up for discussion. + +## Future possibilities + +I currently do not envision any extension in this regard. + +## Copyright + +[copyright]: #copyright + +Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). From 30730e7af50b06b07559d3196c5d075ca2b30c3e Mon Sep 17 00:00:00 2001 From: Zion <67903793+zlog-in@users.noreply.github.com> Date: Tue, 11 Oct 2022 11:45:29 +0200 Subject: [PATCH 072/150] fix: Typo fixed in RuntimeSpec/Receipts.md (#406) `receipt_id` should be [`Receipt.receipt_id`] --- specs/RuntimeSpec/Receipts.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/specs/RuntimeSpec/Receipts.md b/specs/RuntimeSpec/Receipts.md index d494d98e8..8d72da26d 100644 --- a/specs/RuntimeSpec/Receipts.md +++ b/specs/RuntimeSpec/Receipts.md @@ -126,7 +126,7 @@ A Receipt which runtime stores until all the designated [`DataReceipt`s](#datare - **`key`** = `account_id`,`receipt_id` - **`value`** = `[u8]` -_Where `account_id` is [`Receipt.receiver_id`](#receiver_id), `receipt_id` is [`Receipt.receiver_id`](#receipt_id) and value is a serialized [`Receipt`](#receipt) (which [type](#type) must be [ActionReceipt](#actionreceipt))._ +_Where `account_id` is [`Receipt.receiver_id`](#receiver_id), `receipt_id` is [`Receipt.receipt_id`](#receipt_id) and value is a serialized [`Receipt`](#receipt) (which [type](#type) must be [ActionReceipt](#actionreceipt))._ #### Pending DataReceipt Count From 740966c7b81fc45471f40fbdcd337a32693317fb Mon Sep 17 00:00:00 2001 From: Vlad Frolov Date: Tue, 11 Oct 2022 13:48:37 +0200 Subject: [PATCH 073/150] fix: Fixed a typo in RuntimeSpec/Receipts.md (#409) Closes #405 --- specs/RuntimeSpec/Receipts.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/specs/RuntimeSpec/Receipts.md b/specs/RuntimeSpec/Receipts.md index 8d72da26d..bbea3d1a5 100644 --- a/specs/RuntimeSpec/Receipts.md +++ b/specs/RuntimeSpec/Receipts.md @@ -41,7 +41,7 @@ The destination account_id. #### receipt_id -- **`type`**: `AccountId` +- **`type`**: `CryptoHash` An unique id for the receipt. From 85e4e33df4e53eb5e257f27c095099ae6b18866d Mon Sep 17 00:00:00 2001 From: Zion <67903793+zlog-in@users.noreply.github.com> Date: Tue, 11 Oct 2022 15:03:38 +0200 Subject: [PATCH 074/150] fix: Fixed a typo in Proposals/0008-transaction-refactoring.md (#410) --- specs/Proposals/0008-transaction-refactoring.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/specs/Proposals/0008-transaction-refactoring.md b/specs/Proposals/0008-transaction-refactoring.md index bacc341bc..c7f7c9eda 100644 --- a/specs/Proposals/0008-transaction-refactoring.md +++ b/specs/Proposals/0008-transaction-refactoring.md @@ -44,7 +44,7 @@ To achieve this, NEP introduces a new message `Action` that represents one of at - `action` is the list of actions to perform. An `Action` can be of the following: -- `CreateAccount` creates a new account with the `receiver_id` account ID. The action fails if the account already exists. `CreateAccount` also grants permission for all subsequent batched action for the newly created account. For example, permission gto deploy code on the new account. Permission details are described in the reference section below. +- `CreateAccount` creates a new account with the `receiver_id` account ID. The action fails if the account already exists. `CreateAccount` also grants permission for all subsequent batched action for the newly created account. For example, permission to deploy code on the new account. Permission details are described in the reference section below. - `DeployContract` deploys given binary wasm code on the account. Either the `receiver_id` equals to the `signer_id`, or the batch of actions has started with `CreateAccount`, which granted that permission. - `FunctionCall` executes a function call on the last deployed contract. The action fails if the account or the code doesn't exist. E.g. if the previous action was `DeployContract`, then the code to execute will be the new deployed contract. `FunctionCall` has `method_name` and `args` to identify method with arguments to call. It also has `gas` and the `deposit`. `gas` is a prepaid amount of gas for this call (the price of gas is determined when a signed transaction is converted to a receipt. `deposit` is the attached deposit balance of NEAR tokens that the contract can spend, e.g. 10 tokens to pay for a crypto-corgi. - `Transfer` transfers the given `deposit` balance of tokens from the predecessor to the receiver. From 6b778237a92106c83df93f5a4f8b39dcaabd9e5f Mon Sep 17 00:00:00 2001 From: Zion <67903793+zlog-in@users.noreply.github.com> Date: Wed, 12 Oct 2022 16:47:20 +0200 Subject: [PATCH 075/150] fix: Add explanation for abbreviation "sir" (#412) --- specs/GenesisConfig/RuntimeFeeConfig/Fee.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/specs/GenesisConfig/RuntimeFeeConfig/Fee.md b/specs/GenesisConfig/RuntimeFeeConfig/Fee.md index 76495545f..384f6d1bb 100644 --- a/specs/GenesisConfig/RuntimeFeeConfig/Fee.md +++ b/specs/GenesisConfig/RuntimeFeeConfig/Fee.md @@ -4,7 +4,7 @@ Costs associated with an object that can only be sent over the network (and exec ## send_sir -Fee for sending an object from the sender to itself, guaranteeing that it does not leave +Fee for sending an object from the sender to itself, guaranteeing that it does not leave (SIR = signer is receiver, which guarantees the receipt is local). ## send_not_sir From 5b78d0358fb8a925713832c30d17ed596e22b674 Mon Sep 17 00:00:00 2001 From: Zion <67903793+zlog-in@users.noreply.github.com> Date: Wed, 12 Oct 2022 16:48:16 +0200 Subject: [PATCH 076/150] fix(Proposals/0008-transaction-refactoring.md): Replace a noun with its verb (#411) --- specs/Proposals/0008-transaction-refactoring.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/specs/Proposals/0008-transaction-refactoring.md b/specs/Proposals/0008-transaction-refactoring.md index c7f7c9eda..c5b00bdba 100644 --- a/specs/Proposals/0008-transaction-refactoring.md +++ b/specs/Proposals/0008-transaction-refactoring.md @@ -167,7 +167,7 @@ To create a new account we can create a new `Transaction`: This transaction is sent from `vasya.near` signed with a `public_key`. The receiver is `vitalik.vasya.near`, which is a new account id. The transaction contains a batch of actions. -First we create the account, then we transaction a few tokens on the new account, then we deploy code on the new account, add a new access key with some given public key, and as a final action initializing the deployed code by calling a method `init` with some arguments. +First we create the account, then we transfer a few tokens to the newly created account, then we deploy code on the new account, add a new access key with some given public key, and as a final action initializing the deployed code by calling a method `init` with some arguments. For this transaction to work `vasya.near` needs to have enough balance on the account cover gas and deposits for all actions at once. Every action has some associated action gas fee with it. While `transfer` and `function_call` actions need additional balance for deposits and gas (for executions and promises). From 3b8acc876e2385a1e0a59ba122c48af35214e6b4 Mon Sep 17 00:00:00 2001 From: Vlad Frolov Date: Mon, 17 Oct 2022 14:23:32 +0200 Subject: [PATCH 077/150] fix: Corrected the notes for the "Reference Implementation" section (#401) --- nep-0000-template.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nep-0000-template.md b/nep-0000-template.md index 6a7123d4c..b1b631ced 100644 --- a/nep-0000-template.md +++ b/nep-0000-template.md @@ -34,7 +34,7 @@ Explain the proposal as if it was already implemented and you were teaching it t For user-facing NEPs this section should focus on user stories. -## Reference Implementation (Required for Contract category, optional for other categories) +## Reference Implementation (Required for Protocol Working Group proposals, optional for other categories) This is the technical portion of the NEP. Explain the design in sufficient detail that: From aef88181affd55e7b311a1091d39a40c12cc4272 Mon Sep 17 00:00:00 2001 From: nujabes403 Date: Mon, 17 Oct 2022 21:27:59 +0900 Subject: [PATCH 078/150] typo: Fixed a typo in Receipts.md (#416) --- specs/RuntimeSpec/Receipts.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/specs/RuntimeSpec/Receipts.md b/specs/RuntimeSpec/Receipts.md index bbea3d1a5..814c07082 100644 --- a/specs/RuntimeSpec/Receipts.md +++ b/specs/RuntimeSpec/Receipts.md @@ -1,6 +1,6 @@ # Receipt -All cross-contract (we assume that each account lives in it's own shard) communication in Near happens trough Receipts. +All cross-contract (we assume that each account lives in its own shard) communication in Near happens through Receipts. Receipts are stateful in a sense that they serve not only as messages between accounts but also can be stored in the account storage to await DataReceipts. Each receipt has a [`predecessor_id`](#predecessor_id) (who sent it) and [`receiver_id`](#receiver_id) the current account. From b149dfd0e441eb01ada57769ce13b099a35bf5f4 Mon Sep 17 00:00:00 2001 From: Dennis <10233439+idea404@users.noreply.github.com> Date: Mon, 17 Oct 2022 17:31:58 +0200 Subject: [PATCH 079/150] Nomicon: Change `state rent` to `storage staking` (#414) This PR changes the outdated concept in `FinancialTransaction.md`. Mentioned: https://github.com/near/docs/issues/345 --- .../Scenarios/FinancialTransaction.md | 25 ++++++++----------- 1 file changed, 10 insertions(+), 15 deletions(-) diff --git a/specs/RuntimeSpec/Scenarios/FinancialTransaction.md b/specs/RuntimeSpec/Scenarios/FinancialTransaction.md index 6ac045f4c..997c30f93 100644 --- a/specs/RuntimeSpec/Scenarios/FinancialTransaction.md +++ b/specs/RuntimeSpec/Scenarios/FinancialTransaction.md @@ -18,9 +18,8 @@ Suppose Alice has account `alice_near` and Bob has account `bob_near`. Also, som each of them has created a public-secret key-pair, saved the secret key somewhere (e.g. in a wallet application) and created a full access key with the public key for the account. -We also need to assume that both Alice and Bob have some number of tokens on their accounts. Alice needs >100 tokens on the account -so that she could transfer 100 tokens to Bob, but also Alice and Bob need to have some tokens to pay for the _rent_ of their account -- -which is essentially the cost of the storage occupied by the account in the Near Protocol network. +We also need to assume that both Alice and Bob have some number of tokens on their accounts. Alice needs >100 tokens on her account +so that she could transfer 100 tokens to Bob, but also Alice and Bob need to have some tokens on balance to pay for the data they store on-chain for their accounts -- which is essentially the refundable cost of the storage occupied by the account in the Near Protocol network. ## Creating a transaction @@ -88,20 +87,14 @@ which in turn does the following: The first two items are performed inside `Runtime::verify_and_charge_transaction` method. Specifically it does the following checks: -- Verifies that `alice_near` and `bob_near` are syntactically valid account ids; - Verifies that the signature of the transaction is correct based on the transaction hash and the attached public key; - Retrieves the latest state of the `alice_near` account, and simultaneously checks that it exists; - Retrieves the state of the access key of that `alice_near` used to sign the transaction; - Checks that transaction nonce is greater than the nonce of the latest transaction executed with that access key; -- Checks whether the account that signed the transaction is the same as the account that receives it. In our case the sender (`alice_near`) and the receiver (`bob_near`) are not the same. We apply different fees if receiver and sender is the same account; -- Applies the storage rent to the `alice_near` account; -- Computes how much gas we need to spend to convert this transaction to a receipt; -- Computes how much balance we need to subtract from `alice_near`, in this case it is 100 tokens; -- Deducts the tokens and the gas from `alice_near` balance, using the current gas price; -- Checks whether after all these operations account has enough balance to passively pay for the rent for the next several blocks - (an economical constant defined by Near Protocol). Otherwise account will be open for an immediate deletion, which we do not want; +- Subtracts the `total_cost` of the transaction from the account balance, or throws `InvalidTxError::NotEnoughBalance`. If the transaction is part of a transaction by a FunctionCall Access Key, subtracts the `total_cost` from the `allowance` or throws `InvalidAccessKeyError::NotEnoughAllowance`; +- Checks whether the `signer` account has insufficient balance for the storage deposit and throws `InvalidTxError::LackBalanceForState` if so +- If the transaction is part of a transaction by a FunctionCall Access Key, throws `InvalidAccessKeyError::RequiresFullAccess`; - Updates the `alice_near` account with the new balance and the used access key with the new nonce; -- Computes how much reward should be paid to the validators from the burnt gas. If any of the above operations fail all of the changes will be reverted. @@ -110,10 +103,12 @@ If any of the above operations fail all of the changes will be reverted. The receipt created in the previous section will eventually arrive to a runtime on the shard that hosts `bob_near` account. Again, it will be processed by `Runtime::apply` which will immediately call `Runtime::process_receipt`. It will check that this receipt does not have data dependencies (which is only the case of function calls) and will then call `Runtime::apply_action_receipt` on `TransferAction`. + `Runtime::apply_action_receipt` will perform the following checks: - Retrieves the state of `bob_near` account, if it still exists (it is possible that Bob has deleted his account concurrently with the transfer transaction); -- Applies the rent to Bob's account; - Computes the cost of processing a receipt and a transfer action; -- Checks if `bob_near` still exists and if it is deposits the transferred tokens; -- Computes how much reward should be paid to the validators from the burnt gas. +- Computes how much reward should be burnt; +- Checks if `bob_near` still exists and if it does, deposits the transferred tokens to `bob_near`; +- Checks if `bob_near` still exists and if so, deposits the gas reward to the `bob_near` account; +- Checks if `bob_near` has enough balance for the storage deposit, the transaction's temporary state is dropped/rolled back if there is not enough balance; From 9c666f134cb7175611381d12d1a2a92a4e86c265 Mon Sep 17 00:00:00 2001 From: codingshot <45281667+codingshot@users.noreply.github.com> Date: Fri, 21 Oct 2022 10:44:28 -0400 Subject: [PATCH 080/150] typo: took out extra bullet point from transactions.md spec (#419) --- specs/RuntimeSpec/Transactions.md | 1 - 1 file changed, 1 deletion(-) diff --git a/specs/RuntimeSpec/Transactions.md b/specs/RuntimeSpec/Transactions.md index 505b2ec73..55f64a53d 100644 --- a/specs/RuntimeSpec/Transactions.md +++ b/specs/RuntimeSpec/Transactions.md @@ -149,7 +149,6 @@ error is returned. * `InvalidAccessKeyError::RequiresFullAccess` if the transaction contains more than one action or if the only action it contains is not a `FunctionCall` action. * `InvalidAccessKeyError::DepositWithFunctionCall` if the function call action has nonzero `deposit`. -* ```rust /// Transaction `receiver_id` doesn't match the access key receiver_id InvalidAccessKeyError::ReceiverMismatch { tx_receiver: AccountId, ak_receiver: AccountId }, From 1db84f65ccd0edbd3c8f7d096aee27b0f33dcf01 Mon Sep 17 00:00:00 2001 From: Daryl Collins Date: Fri, 21 Oct 2022 11:35:54 -0700 Subject: [PATCH 081/150] NEP-408: Injected Wallet API (#408) ## Summary This is a proposal for a new NEP regarding an Injected Wallet Standard. Adopted from https://github.com/near/NEPs/pull/370 as the original author is no longer working on this task; see #370 for prior discussion. ## Demo You can find a demo of this standard using the project detailed below: - Implementation: https://github.com/lewis-sqa/near-injected-wallet-poc - Running the project: - Execute `yarn install && yarn start` from root. - Navigate to http://localhost:1234. Co-authored-by: Lewis Barnes Co-authored-by: Osman Abdelnasir --- specs/Standards/Wallets/InjectedWallets.md | 325 +++++++++++++++++++++ 1 file changed, 325 insertions(+) create mode 100644 specs/Standards/Wallets/InjectedWallets.md diff --git a/specs/Standards/Wallets/InjectedWallets.md b/specs/Standards/Wallets/InjectedWallets.md new file mode 100644 index 000000000..e591395c6 --- /dev/null +++ b/specs/Standards/Wallets/InjectedWallets.md @@ -0,0 +1,325 @@ +# Injected Wallets + +## Summary + +Standard interface for injected wallets. + +## Motivation + +dApps are finding it increasingly difficult to support the ever expanding choice of wallets due to their wildly different implementations. While projects such as [Wallet Selector](https://github.com/near/wallet-selector) attempt to mask this problem, it's clear the ecosystem requires a standard that will not only benefit dApps but make it easier for established wallets to support NEAR. + +## Rationale and alternatives + +At its most basic, a wallet contains key pairs required to sign messages. This standard aims to define an API (based on our learning from [Wallet Selector](https://github.com/near/wallet-selector)) that achieves this requirement through a number of methods exposed on the `window` object. + +The introduction of this standard makes it possible for `near-api-js` to become wallet-agnostic and eventually move away from the high amount of coupling with NEAR Wallet. It simplifies projects such as [Wallet Selector](https://github.com/near/wallet-selector) that must implement various abstractions to normalise the different APIs before it can display a modal for selecting a wallet. + +This standard takes a different approach to a wallet API than other blockchains such as [Ethereum's JSON-RPC Methods](https://docs.metamask.io/guide/rpc-api.html#ethereum-json-rpc-methods). Mainly, it rejects the `request` abstraction that feels unnecessary and only adds to the complexity both in terms of implementation and types. Instead, it exposes various methods directly on the top-level object that also improves discoverability. + +There have been many iterations of this standard to help inform what we consider the "best" approach right now for NEAR. Below is a summary of the key design choices: + +### Single account vs. multiple account + +Almost every wallet implementation in NEAR used a single account model until we began integrating with [WalletConnect](https://walletconnect.com/). In WalletConnect, sessions can contain any number of accounts that can be modified by the dApp or wallet. The decision to use a multiple account model was influenced by the following reasons: + +- It future-proofs the API even if wallets (such as MetaMask) only support a single "active" account. +- Other blockchains such as [Ethereum](https://docs.metamask.io/guide/rpc-api.html#eth-requestaccounts) implement this model. +- Access to multiple accounts allow dApps more freedom to improve UX as users can seamlessly switch between accounts. +- Aligns with WalletConnect via the [Bridge Wallet Standard](./BridgeWallets.md). + +### Storage of key pairs for FunctionCall access keys in dApp context vs. wallet context + +- NEAR's unique concept of `FunctionCall` access keys allow for the concept of 'signing in' to a dApp using your wallet. 'Signing In' to a dApp is accomplished by adding `FunctionCall` type access key that the dApp owns to the account that the user is logging in as. +- Once a user has 'signed in' to a dApp, the dApp can then use the keypair that it owns to execute transactions without having to prompt the user to route and approve those transactions through their wallet. +- `FunctionCall` access keys have a limited quota that can only be used to pay for gas fees (typically 0.25 NEAR) and can further be restricted to only be allowed to call *specific methods* on one **specific** smart contract. +- This allows for an ideal user experience for dApps that require small gas-only transactions regularly while in use. Those transactions can be done without interrupting the user experience by requiring them to be approved through their wallet. A great example of this is evident in gaming use-cases -- take a gaming dApp where some interactions the user makes must write to the blockchain as they do common actions in the game world. Without the 'sign in' concept that provides the dApp with its own limited usage key, the user might be constantly interrupted by needing to approve transactions on their wallet as they perform common actions. If a player has their account secured with a ledger, the gameplay experience would be constantly interrupted by prompts to approve transactions on their ledger device! With the 'sign in' concept, the user will only intermittently need to approve transactions to re-sign-in, when the quota that they approved for gas usage during their last login has been used up. +- Generally, it is recommended to only keep `FullAccess` keys in wallet scope and hidden from the dApp consumer. `FunctionCall` type keys should be generated and owned by the dApp, and requested to be added using the `signIn` method. They should **not** be 'hidden' inside the wallet in the way that `FullAccess` type keys are. + +## Specification + +Injected wallets are typically browser extensions that implement the `Wallet` API (see below). References to the currently available wallets are tracked on the `window` object. To avoid namespace collisions and easily detect when they're available, wallets must mount under their own key of the object `window.near` (e.g. `window.near.sender`). +**NOTE: Do not replace the entire `window.near` object with your wallet implementation, or add any objects as properties of the `window.near` object that do not conform to the Injected Wallet Standard** + +At the core of a wallet are [`signTransaction`](#signtransaction) and [`signTransactions`](#signtransactions). These methods, when given a [`TransactionOptions`](#Wallet-API) instance, will prompt the user to sign with a key pair previously imported (with the assumption it has [`FullAccess`](https://nomicon.io/DataStructures/AccessKey) permission). + +In most cases, a dApp will need a reference to an account and associated public key to construct a [`Transaction`](https://nomicon.io/RuntimeSpec/Transactions). The [`connect`](#connect) method helps solve this issue by prompting the user to select one or more accounts they would like to make visible to the dApp. When at least one account is visible, the wallet considers the dApp [`connected`](#connected) and they can access a list of [`accounts`](#accounts) containing an `accountId` and `publicKey`. + +For dApps that often sign gas-only transactions, [`FunctionCall`](https://nomicon.io/DataStructures/AccessKey#accesskeypermissionfunctioncall) access keys can be added/deleted for one or more accounts using the [`signIn`](#signin) and [`signOut`](#signout) methods. While this functionality could be achieved with [`signTransactions`](#signtransactions), it suggests a direct intention that a user wishes to sign in/out of a dApp's smart contract. + +### Wallet API + +Below is the entire API for injected wallets. It makes use of `near-api-js` to enable interoperability with dApps that will already use it for constructing transactions and communicating with RPC endpoints. + +```ts +import { transactions, utils } from "near-api-js"; + +interface Account { + accountId: string; + publicKey: utils.PublicKey; +} + +interface Network { + networkId: string; + nodeUrl: string; +} + +interface SignInParams { + permission: transactions.FunctionCallPermission; + accounts: Array; +} + +interface SignOutParams { + accounts: Array; +} + +interface TransactionOptions { + receiverId: string; + actions: Array; + signerId?: string; +} + +interface SignTransactionParams { + transaction: TransactionOptions; +} + +interface SignTransactionsParams { + transactions: Array; +} + +interface Events { + accountsChanged: { accounts: Array }; +} + +interface ConnectParams { + networkId: string; +} + +type Unsubscribe = () => void; + +interface Wallet { + id: string; + connected: boolean; + network: Network; + accounts: Array; + + supportsNetwork(networkId: string): Promise; + connect(params: ConnectParams): Promise>; + signIn(params: SignInParams): Promise; + signOut(params: SignOutParams): Promise; + signTransaction(params: SignTransactionParams): Promise; + signTransactions(params: SignTransactionsParams): Promise>; + disconnect(): Promise; + on( + event: EventName, + callback: (params: Events[EventName]) => void + ): Unsubscribe; + off( + event: EventName, + callback?: () => void + ): void; +} +``` + +#### Properties + +##### `id` + +Retrieve the wallet's unique identifier. + +```ts +const { id } = window.near.wallet; + +console.log(id) // "wallet" +``` + +##### `connected` + +Determine whether we're already connected to the wallet and have visibility of at least one account. + +```ts +const { connected } = window.near.wallet; + +console.log(connected) // true +``` + +##### `network` + +Retrieve the currently selected network. + +```ts +const { network } = window.near.wallet; + +console.log(network) // { networkId: "testnet", nodeUrl: "https://rpc.testnet.near.org" } +``` + +##### `accounts` + +Retrieve all accounts visible to the dApp. + +```ts +const { accounts } = window.near.wallet; + +console.log(accounts) // [{ accountId: "test.testnet", publicKey: PublicKey }] +``` + +#### Methods + +##### `connect` + +Request visibility for one or more accounts from the wallet. This should explicitly prompt the user to select from their list of imported accounts. dApps can use the `accounts` property once connected to retrieve the list of visible accounts. + +> Note: Calling this method when already connected will allow users to modify their selection, triggering the 'accountsChanged' event. + +```ts +const accounts = await window.near.wallet.connect(); +``` + +##### `signTransaction` + +Sign a transaction. This request should require explicit approval from the user. + +```ts +import { transactions, providers, utils } from "near-api-js"; + +// Retrieve accounts (assuming already connected) and current network. +const { network, accounts } = window.near.wallet; + +// Setup RPC to retrieve transaction-related prerequisites. +const provider = new providers.JsonRpcProvider({ url: network.nodeUrl }); + +const signedTx = await window.near.wallet.signTransaction({ + transaction: { + signerId: accounts[0].accountId, + receiverId: "guest-book.testnet", + actions: [transactions.functionCall( + "addMessage", + { text: "Hello World!" }, + utils.format.parseNearAmount("0.00000000003"), + utils.format.parseNearAmount("0.01") + )] + } +}); +// Send the transaction to the blockchain. +await provider.sendTransaction(signedTx); +``` + +##### `signTransactions` + +Sign a list of transactions. This request should require explicit approval from the user. + +```ts +import { transactions, providers, utils } from "near-api-js"; + +// Retrieve accounts (assuming already connected) and current network. +const { network, accounts } = window.near.wallet; + +// Setup RPC to retrieve transaction-related prerequisites. +const provider = new providers.JsonRpcProvider({ url: network.nodeUrl }); + +const signedTxs = await window.near.wallet.signTransactions({ + transactions: [ + { + signerId: accounts[0].accountId, + receiverId: "guest-book.testnet", + actions: [transactions.functionCall( + "addMessage", + { text: "Hello World! (1/2)" }, + utils.format.parseNearAmount("0.00000000003"), + utils.format.parseNearAmount("0.01") + )] + }, + { + signerId: accounts[0].accountId, + receiverId: "guest-book.testnet", + actions: [transactions.functionCall( + "addMessage", + { text: "Hello World! (2/2)" }, + utils.format.parseNearAmount("0.00000000003"), + utils.format.parseNearAmount("0.01") + )] + } + ] +}); + +for (let i = 0; i < signedTxs.length; i += 1) { + const signedTx = signedTxs[i]; + + // Send the transaction to the blockchain. + await provider.sendTransaction(signedTx); +} +``` + +##### `disconnect` + +Remove visibility of all accounts from the wallet. + +```ts +await window.near.wallet.disconnect(); +``` + +##### `signIn` + +Add `FunctionCall` access key(s) for one or more accounts. This request should require explicit approval from the user. + +```ts +import { utils } from "near-api-js"; + +// Retrieve the list of accounts we have visibility of. +const { accounts } = window.near.wallet; + +// Request FunctionCall access to the 'guest-book.testnet' smart contract for each account. +await window.near.wallet.signIn({ + permission: { + receiverId: "guest-book.testnet", + methodNames: [], + }, + accounts: accounts.map(({ accountId }) => { + const keyPair = utils.KeyPair.fromRandom("ed25519"); + + return { + accountId, + publicKey: keyPair.getPublicKey() + }; + }), +}); +``` + +##### `signOut` + +Delete `FunctionCall` access key(s) for one or more accounts. This request should require explicit approval from the user. + +```ts +import { utils, keyStores } from "near-api-js"; + +// Setup keystore to retrieve locally stored FunctionCall access keys. +const keystore = new keyStores.BrowserLocalStorageKeyStore(); + +// Retrieve accounts (assuming already connected) and current network. +const { network, accounts } = window.near.wallet; + +// Remove FunctionCall access (previously granted via signIn) for each account. +await window.near.wallet.signOut({ + accounts: await Promise.all( + accounts.map(async ({ accountId }) => { + const keyPair = await keystore.getKey(network.networkId, accountId); + + return { + accountId, + publicKey: keyPair.getPublicKey() + }; + }) + ), +}); +``` + +#### Events + +##### `accountsChanged` + +Triggered whenever accounts are updated (e.g. calling `connect` or `disconnect`). + +```ts +window.near.wallet.on("accountsChanged", ({ accounts }) => { + console.log("Accounts Changed", accounts); +}); +``` From 4fb1913c830bf601ca8bbd99886abe8e26ab31b2 Mon Sep 17 00:00:00 2001 From: ori-near <110252255+ori-near@users.noreply.github.com> Date: Mon, 14 Nov 2022 11:05:10 -0800 Subject: [PATCH 082/150] Update nep-0001.md (#427) We updated the following sections based on feedback we got from processing recent NEPS: - Clarified the NEP workflow and lifecycle diagram with specific actions that created bottlenecks - Clarified the responsibilities of the Reviewer (Subject Matter Expert) - Clarified how to modify a NEP when it is still in the review phase - Added a new NEP communication section --- neps/nep-0001.md | 32 ++++++++++++++++++++++++-------- 1 file changed, 24 insertions(+), 8 deletions(-) diff --git a/neps/nep-0001.md b/neps/nep-0001.md index fa4c1bbfd..49e0505d6 100644 --- a/neps/nep-0001.md +++ b/neps/nep-0001.md @@ -24,7 +24,7 @@ The purpose of the NEP process is to ensure seamless protocol upgrades and to em The working groups are responsible for coordinating the public review of NEPs, gauging the viability and community support, and overseeing decisions. Each group will focus on various ecosystem needs, such as the protocol, standards, and tools. -Pagoda has selected a few leading subject matter experts to help bootstrap the first two groups: Protocols and Contract Standards. Putting these groups into practice will require flexibility. The goal is to iterate and eventually introduce more groups and broader participation. Visit [https://near.org/working-groups](https://near.org/working-groups) to learn more about these groups, their members, and the upcoming meetings. +Pagoda has selected a few leading subject matter experts to help bootstrap the first two groups: Protocols and Contract Standards. Putting these groups into practice will require flexibility. The goal is to iterate and eventually introduce more groups and broader participation. Visit [https://near.org/developer-governance](https://near.org/developer-governance) to learn more about these groups, their members, and the upcoming meetings. ## Audience The typical primary audience for NEPs are the core developers of the NEAR reference implementations and decentralized applications developers @@ -66,16 +66,33 @@ The NEP workflow is: - The title accurately describes the content. - The language (spelling, grammar, sentence structure, etc.) and code style are correct and conformant. - If the NEP is not ready for approval, the moderators will send it back to the author for revision, with specific instructions in the pull request. The review by the moderators is expected to finish within one week. -- Once the moderators agree that the PR is ready for review, the moderators notify the approvers (working groups) to assign a team of at least two reviewers (subject matter experts) to review the NEP. The reviewers will review the technical details of the proposal and assess its merits. They may ask clarification questions, request changes, or reject the proposal. The review by the reviewers is expected to finish within one week. The author of the proposal is free to revise the proposal and re-request reviews from reviewers. -- If a proposal is in the review stage for more than two months, it is automatically rejected. To re-open the proposal, the author must start over with the NEP process again. -- Once the reviewers agree that the proposal is close to a decision, they will have a final two week review period to add their comments, and then ask the author to present the NEP to the working group in a meeting, where it can enter the final voting stage. If the moderators agree that the NEP is overall beneficial for the NEAR ecosystem and vote to approve it, then the proposal is considered accepted. +- Once the moderators agree that the PR is ready for review, the moderators will notify the approvers (working group members) to assign a team of at least two reviewers (subject matter experts) to review the NEP. The reviewers will review the technical details of the proposal and assess its merits. They may ask clarification questions, request changes, or reject the proposal. If the assigned reviewers feel that they do not have the relevant expertise to fully review the NEP, they can request the working group to re-assign subject matter experts for the NEP. +- The review by the reviewers is expected to finish within one week. After completing the review, the reviewer must add an explicit comment to indicate the next step and tag the appropriate member: + - To request revisions from the author: "As the assigned Reviewer, I request from the author @author-username to address [provide concerns or suggestions]." + - To move to the next stage: "As the assigned Reviewer, I do not have any feedback for the author. I recommend moving this NEP forward and for the working group to [accept or reject] it based on [provide reasoning, including a sense of importance or urgency of this NEP]." +- The author of the proposal is free to revise the proposal and re-request reviews from reviewers. If a proposal is in the review stage for more than two months, the moderator will automatically reject it. To re-open the proposal, the author must start over with the NEP process again. +- Once the two reviewers agree that the proposal is close to the voting stage, the moderators will assign the approvers (working group) to review the NEP. The approvers will review the proposal and add their voting indication. +- The final review period by the approvers is expected to finish within one week. After completing the review, the approvers must add an explicit comment with their voting indication: + - To reject: "As a working group member, I lean towards rejecting this proposal based on [provide reasoning]." + - To approve: "As a working group member, I lean towards approving this NEP based on [provide reasoning]." +- Once all the approvers add their voting indication, the moderator will review the voting indication for a 2/3 majority vote: + - If the votes lean toward rejection: The moderator will summarize the feedback and close the NEP. + - If the votes lean toward approval: The moderator will schedule a public call (see [NEP Communication](#nep-communication)) for the author to present the NEP and for the working group members to formalize the voting decision. If the working group members agree that the NEP is overall beneficial for the NEAR ecosystem and vote to approve it, then the proposal is considered accepted. After the call, the moderator will summarize the decision on the NEP. + +### NEP Communication + +NEP discussions should happen asynchronously within the NEP’s public thread. + +However, if a discussion becomes circular and could benefit from a synchronous conversation, any participants on a given NEP can suggest for the moderator to schedule an ad hoc meeting. For example, if a reviewer and author have multiple rounds of comments, they may request a call. The moderator can help coordinate the call and post the registration link on the NEP. The person who requested the call should designate a note taker to post a summary on the NEP after the call. + +When a NEP gets to the final voting stage, the moderator will schedule a public working group meeting to discuss the NEP with the author and formalize the decision. The moderator will first coordinate a time with the author and working group members, and then post the meeting time and registration link on the NEP at least one week in advance. ### NEP Maintenance In general, NEPs are no longer modified after they have reached the Final state. ## NEP Life Cycle -![NEP Process](https://user-images.githubusercontent.com/110252255/184407496-e96b0a96-af43-4694-90ed-58d8bb463958.png) +![NEP Process](https://user-images.githubusercontent.com/110252255/201413632-f72743d6-593e-4747-9409-f56bc38de17b.png) A given NEP can have one of the following states: @@ -119,12 +136,11 @@ The NEP process has various roles and responsibilities. - Gives feedback on proposals - Assesses technical feasibility of proposals -- Has rejecting voting power - Does not have the ability to approve proposal ![Approver](https://user-images.githubusercontent.com/110252255/181816752-521dd147-f56f-4c5c-84de-567b109f21d6.png) **Approver** (Community Working Groups)
-*Appointed by Pagoda in the boostraphing phase* +*Appointed by Pagoda in the bootstrapping phase* - Assigns reviewers to proposals - Attends working group meetings to review proposals @@ -193,7 +209,7 @@ Images, diagrams and auxiliary files should be included in a subdirectory of the ## Transferring NEP Ownership It occasionally becomes necessary to transfer ownership of NEPs to a new author. In general, it is preferable to retain the original author as a co-author of the transferred NEP, but that is up to the original author. A good reason to transfer ownership is because the original author no longer has the time or interest in updating it or following through with the NEP process. A bad reason to transfer ownership is because the author does not agree with the direction of the NEP. One aim of the NEP process is to try to build consensus around a NEP, but if that is not possible, an author can submit a competing NEP. -If you are interested in assuming ownership of a NEP, you can also do this via pull request. Fork the NEP repository, make your ownership modification, and submit a pull request. You should mention both the original author and @near/nep-editors in a comment on the pull request. +If you are interested in assuming ownership of a NEP, you can also do this via pull request. Fork the NEP repository, make your ownership modification, and submit a pull request. In the PR description, tag the original author and provide a summary of the work that was previously done. Also clearly state the intent of the fork and the relationship of the new PR to the old one. For example: "Forked to address the remaining review comments in NEP # since the original author does not have time to address them." ## Style Guide From ea76e8a8e2f6ade3f0316e44588b32de39b0370b Mon Sep 17 00:00:00 2001 From: Akhilesh Singhania Date: Fri, 18 Nov 2022 15:48:49 +0100 Subject: [PATCH 083/150] fix: Clarify reference and draft implementation (#400) I believe this document uses the term "reference implementation" to mean "draft implementation". Given that we say that `nearcore` is the reference implementation of the protocol, this PR rewords "reference implementation" to "draft implementation" to clarify the intend. --- neps/nep-0001.md | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/neps/nep-0001.md b/neps/nep-0001.md index 49e0505d6..1bb03de30 100644 --- a/neps/nep-0001.md +++ b/neps/nep-0001.md @@ -116,8 +116,7 @@ The NEP process has various roles and responsibilities. - Submits proposal with prototype when ready for review and changes the status to “Draft” - Addresses comments - Presents to working group and incorporates necessary changes -- Executes implementation once approved -- Provides reference implementation and documentation once approved +- Provides final implementation with sufficient testing and documentation once approved ![Moderator](https://user-images.githubusercontent.com/110252255/181816650-b1610c0e-6d32-4d2a-a34e-877c702139bd.png) **Moderator**
@@ -154,8 +153,8 @@ Each NEP should have the following parts/sections: 1. Motivation - The motivation section should clearly explain why the existing contract ecosystem is inadequate to address the problem that the NEP solves. This can include collecting documented support for the NEP from important projects in the NEAR ecosystem. NEP submissions without sufficient motivation may be rejected. 1. Rationale and alternatives - The rationale fleshes out the specification by describing why particular design decisions were made. It should describe alternate designs that were considered and related work, e.g. how the feature is supported in other platforms. 1. Specification - The technical specification should describe the syntax and semantics of the contract or protocol feature. The specification should be detailed enough to allow competing, interoperable implementations for at least the current major NEAR version. -1. Reference Implementation - The reference implementation must be completed before any NEP is given the “Approved” status. - While there is merit to the approach of reaching consensus on the specification and rationale before writing code, the principle of “rough consensus and running code” is still useful when it comes to resolving many discussions of API details. The final implementation must include test code and documentation. +1. Draft Implementation - A draft implementation showing the viability of the proposal must be completed before any NEP is given the “Approved” status. + While there is merit to the approach of reaching consensus on the specification and rationale before writing code, the principle of “rough consensus and running code” is still useful when it comes to resolving many discussions of API details. Once approved, the final implementation must include test code and documentation. 1. Security Implications - If there are security concerns in relation to the NEP, those concerns should be explicitly written out to make sure reviewers of the NEP are aware of them. 1. Drawbacks - Throughout the discussion of a NEP, various ideas will be proposed which are not accepted. Those rejected ideas should be recorded along with the reasoning as to why they were rejected. This both helps record the thought process behind the final version of the NEP as well as preventing people from bringing up the same rejected idea again in subsequent discussions. In a way this section can be thought of as a breakout section of the Rationale section that is focused specifically on why certain ideas were not ultimately pursued. From 3a2fd9840e0b044c37acff3016af7b4378666e3f Mon Sep 17 00:00:00 2001 From: Willem Wyndham Date: Fri, 18 Nov 2022 12:55:25 -0500 Subject: [PATCH 084/150] feat(NFT): Add option types and add missing memo parameter (#276) This adds the missing memo argument needed by `nft_transfer` and changes types inspired by Paras' usage. Notably using a type alias for `Payout` of a hashmap. Also adds more options so that the API is less strict. https://github.com/ParasHQ/paras-marketplace-contract/blob/ac35d84a1af7ea369c3916db32af0dd1e5a43024/paras-marketplace-contract/src/external.rs#L7-L14 ```rust fn nft_transfer_payout( &mut self, receiver_id: AccountId, token_id: TokenId, approval_id: Option, memo: Option, // This is ignored by Paras balance: U128, max_len_payout: Option, ); ``` - [x] Need to specify that a `nft_transfer_payout` that returns a bad "payout" should still payout to old token owner --- neps/nep-0199.md | 33 ++++++++++---- .../Tokens/NonFungibleToken/Payout.md | 43 +++++++++++++------ 2 files changed, 55 insertions(+), 21 deletions(-) diff --git a/neps/nep-0199.md b/neps/nep-0199.md index 92c51f4bf..0821fe357 100644 --- a/neps/nep-0199.md +++ b/neps/nep-0199.md @@ -16,7 +16,7 @@ An interface allowing non-fungible token contracts to request that financial con ## Motivation -Currently, NFTs on NEAR support the field `owner_id`, but lack flexibility for ownership and payout mechanics with more complexity, including but not limited to royalties. Financial contracts, such as marketplaces, auction houses, and NFT Loan contracts would benefit from a standard interface on NFT producer contracts for querying whom to pay out, and how much to pay. +Currently, NFTs on NEAR support the field `owner_id`, but lack flexibility for ownership and payout mechanics with more complexity, including but not limited to royalties. Financial contracts, such as marketplaces, auction houses, and NFT loan contracts would benefit from a standard interface on NFT producer contracts for querying whom to pay out, and how much to pay. Therefore, the core goal of this standard is to define a set of methods for financial contracts to call, without specifying how NFT contracts define the divide of payout mechanics, and a standard `Payout` response structure. @@ -76,11 +76,11 @@ pub struct Payout { pub payout: HashMap, } -pub trait Payouts{ +pub trait Payouts { /// Given a `token_id` and NEAR-denominated balance, return the `Payout`. /// struct for the given token. Panic if the length of the payout exceeds /// `max_len_payout.` - fn nft_payout(&self, token_id: String, balance: U128, max_len_payout: u32) -> Payout; + fn nft_payout(&self, token_id: String, balance: U128, max_len_payout: Option) -> Payout; /// Given a `token_id` and NEAR-denominated balance, transfer the token /// and return the `Payout` struct for the given token. Panic if the /// length of the payout exceeds `max_len_payout.` @@ -89,19 +89,33 @@ pub trait Payouts{ &mut self, receiver_id: AccountId, token_id: String, - approval_id: u64, + approval_id: Option, + memo: Option, balance: U128, - max_len_payout: u32, - ) -> Payout{ + max_len_payout: Option, + ) -> Payout { assert_one_yocto(); let payout = self.nft_payout(token_id, balance); - self.nft_transfer(receiver_id, token_id, approval_id); + self.nft_transfer(receiver_id, token_id, approval_id, memo); payout } } ``` -Note that NFT and financial contracts will vary in implementation. This means that some extra CPU cycles may occur in one NFT contract and not another. Furthermore, a financial contract may accept fungible tokens, native NEAR, or another entity as payment. Transferring native NEAR tokens is less expensive in gas than sending fungible tokens. For these reasons, the maximum length of payouts may vary according to the customization of the smart contracts. +## Fallback on error + +In the case where either the `max_len_payout` causes a panic, or a malformed `Payout` is returned, the caller contract should transfer all funds to the original token owner selling the token. + +## Potential pitfalls + +The payout must include all accounts that should receive funds. Thus it is a mistake to assume that the original token owner will receive funds if they are not included in the payout. + +NFT and financial contracts vary in implementation. This means that some extra CPU cycles may occur in one NFT contract and not another. Furthermore, a financial contract may accept fungible tokens, native NEAR, or another entity as payment. Transferring native NEAR tokens is less expensive in gas than sending fungible tokens. For these reasons, the maximum length of payouts may vary according to the customization of the smart contracts. + +## Drawbacks + +There is an introduction of trust that the contract calling `nft_transfer_payout` will indeed pay out to all intended parties. However, since the calling contract will typically be something like a marketplace used by end users, malicious actors might be found out more easily and might have less incentive. +There is an assumption that NFT contracts will understand the limits of gas and not allow for a number of payouts that cannot be achieved. ## Future possibilities @@ -109,7 +123,8 @@ In the future, the NFT contract itself may be able to place an NFT transfer is a ## Errata -Version `2.0.0` contains the intended `approval_id` of `u64` instead of the stringified `U64` version. This was an oversight, but since the standard was live for a few months before noticing, the team thought it best to bump the major version. +- Version `2.1.0` adds a memo parameter to `nft_transfer_payout`, which previously forced implementers of `2.0.0` to pass `None` to the inner `nft_transfer`. Also refactors `max_len_payout` to be an option type. +- Version `2.0.0` contains the intended `approval_id` of `u64` instead of the stringified `U64` version. This was an oversight, but since the standard was live for a few months before noticing, the team thought it best to bump the major version. ## Copyright [copyright]: #copyright diff --git a/specs/Standards/Tokens/NonFungibleToken/Payout.md b/specs/Standards/Tokens/NonFungibleToken/Payout.md index 225599159..2464eb5b1 100644 --- a/specs/Standards/Tokens/NonFungibleToken/Payout.md +++ b/specs/Standards/Tokens/NonFungibleToken/Payout.md @@ -8,14 +8,17 @@ This standard assumes the NFT contract has implemented [NEP-171](https://github.com/near/NEPs/blob/master/specs/Standards/Tokens/NonFungibleToken/Core.md) (Core) and [NEP-178](https://github.com/near/NEPs/blob/master/specs/Standards/Tokens/NonFungibleToken/ApprovalManagement.md) (Approval Management). ## Summary + An interface allowing non-fungible token contracts to request that financial contracts pay-out multiple receivers, enabling flexible royalty implementations. ## Motivation -Currently, NFTs on NEAR support the field `owner_id`, but lack flexibility for ownership and payout mechanics with more complexity, including but not limited to royalties. Financial contracts, such as marketplaces, auction houses, and NFT Loan contracts would benefit from a standard interface on NFT producer contracts for querying whom to pay out, and how much to pay. + +Currently, NFTs on NEAR support the field `owner_id`, but lack flexibility for ownership and payout mechanics with more complexity, including but not limited to royalties. Financial contracts, such as marketplaces, auction houses, and NFT loan contracts would benefit from a standard interface on NFT producer contracts for querying whom to pay out, and how much to pay. Therefore, the core goal of this standard is to define a set of methods for financial contracts to call, without specifying how NFT contracts define the divide of payout mechanics, and a standard `Payout` response structure. -## Guide-level explanation + +## Specification This Payout extension standard adds two methods to NFT contracts: - a view method: `nft_payout`, accepting a `token_id` and some `balance`, returning the `Payout` mapping for the given token. @@ -56,7 +59,8 @@ Financial contracts MAY take a cut of the NFT sale price as commission, subtract └───────────────────────────────────────────────┘ ``` -## Reference-level explanation +## Reference Implementation + ```rust /// A mapping of NEAR accounts to the amount each should be paid out, in /// the event of a token-sale. The payout mapping MUST be shorter than the @@ -69,11 +73,11 @@ pub struct Payout { pub payout: HashMap, } -pub trait Payouts{ +pub trait Payouts { /// Given a `token_id` and NEAR-denominated balance, return the `Payout`. /// struct for the given token. Panic if the length of the payout exceeds /// `max_len_payout.` - fn nft_payout(&self, token_id: String, balance: U128, max_len_payout: u32) -> Payout; + fn nft_payout(&self, token_id: String, balance: U128, max_len_payout: Option) -> Payout; /// Given a `token_id` and NEAR-denominated balance, transfer the token /// and return the `Payout` struct for the given token. Panic if the /// length of the payout exceeds `max_len_payout.` @@ -82,23 +86,32 @@ pub trait Payouts{ &mut self, receiver_id: AccountId, token_id: String, - approval_id: u64, + approval_id: Option, + memo: Option, balance: U128, - max_len_payout: u32, - ) -> Payout{ + max_len_payout: Option, + ) -> Payout { assert_one_yocto(); let payout = self.nft_payout(token_id, balance); - self.nft_transfer(receiver_id, token_id, approval_id); + self.nft_transfer(receiver_id, token_id, approval_id, memo); payout } } ``` -Note that NFT and financial contracts will vary in implementation. This means that some extra CPU cycles may occur in one NFT contract and not another. Furthermore, a financial contract may accept fungible tokens, native NEAR, or another entity as payment. Transferring native NEAR tokens is less expensive in gas than sending fungible tokens. For these reasons, the maximum length of payouts may vary according to the customization of the smart contracts. +## Fallback on error + +In the case where either the `max_len_payout` causes a panic, or a malformed `Payout` is returned, the caller contract should transfer all funds to the original token owner selling the token. + +## Potential pitfalls + +The payout must include all accounts that should receive funds. Thus it is a mistake to assume that the original token owner will receive funds if they are not included in the payout. + +NFT and financial contracts vary in implementation. This means that some extra CPU cycles may occur in one NFT contract and not another. Furthermore, a financial contract may accept fungible tokens, native NEAR, or another entity as payment. Transferring native NEAR tokens is less expensive in gas than sending fungible tokens. For these reasons, the maximum length of payouts may vary according to the customization of the smart contracts. ## Drawbacks -There is an introduction of trust that the contract calling `nft_transfer_payout` will indeed pay out all intended parties. However, since the calling contract will typically be something like a marketplace used by end users, malicious actors might be found out more easily and might have less incentive. +There is an introduction of trust that the contract calling `nft_transfer_payout` will indeed pay out to all intended parties. However, since the calling contract will typically be something like a marketplace used by end users, malicious actors might be found out more easily and might have less incentive. There is an assumption that NFT contracts will understand the limits of gas and not allow for a number of payouts that cannot be achieved. ## Future possibilities @@ -107,4 +120,10 @@ In the future, the NFT contract itself may be able to place an NFT transfer is a ## Errata -Version `2.0.0` contains the intended `approval_id` of `u64` instead of the stringified `U64` version. This was an oversight, but since the standard was live for a few months before noticing, the team thought it best to bump the major version. +- Version `2.1.0` adds a memo parameter to `nft_transfer_payout`, which previously forced implementers of `2.0.0` to pass `None` to the inner `nft_transfer`. Also refactors `max_len_payout` to be an option type. +- Version `2.0.0` contains the intended `approval_id` of `u64` instead of the stringified `U64` version. This was an oversight, but since the standard was live for a few months before noticing, the team thought it best to bump the major version. + +## Copyright +[copyright]: #copyright + +Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). \ No newline at end of file From 77ebb7056900d4fca51f0b4065fcfbb1ef72d30a Mon Sep 17 00:00:00 2001 From: Max Harpunsky Date: Mon, 21 Nov 2022 14:38:51 +0200 Subject: [PATCH 085/150] algolia search (#433) --- website/docusaurus.config.js | 21 +- website/package.json | 2 +- website/src/theme/SearchBar/algolia.css | 533 -- website/src/theme/SearchBar/index.js | 118 - website/src/theme/SearchBar/lib/DocSearch.js | 306 - .../src/theme/SearchBar/lib/lunar-search.js | 146 - website/src/theme/SearchBar/lib/templates.js | 114 - website/src/theme/SearchBar/lib/utils.js | 270 - website/src/theme/SearchBar/styles.css | 40 - website/yarn.lock | 5982 ++++++++--------- 10 files changed, 2901 insertions(+), 4631 deletions(-) delete mode 100644 website/src/theme/SearchBar/algolia.css delete mode 100644 website/src/theme/SearchBar/index.js delete mode 100644 website/src/theme/SearchBar/lib/DocSearch.js delete mode 100644 website/src/theme/SearchBar/lib/lunar-search.js delete mode 100644 website/src/theme/SearchBar/lib/templates.js delete mode 100644 website/src/theme/SearchBar/lib/utils.js delete mode 100644 website/src/theme/SearchBar/styles.css diff --git a/website/docusaurus.config.js b/website/docusaurus.config.js index 2726aeb8f..9f5969faf 100644 --- a/website/docusaurus.config.js +++ b/website/docusaurus.config.js @@ -18,7 +18,7 @@ const config = { favicon: 'img/favicon.ico', organizationName: 'near', // Usually your GitHub org/user name. projectName: 'NEPs', // Usually your repo name. - plugins: [require.resolve('docusaurus-lunr-search')], + plugins: [], stylesheets: [ { href: 'https://cdn.jsdelivr.net/npm/katex@0.13.24/dist/katex.min.css', @@ -57,7 +57,6 @@ const config = { }), ], ], - themeConfig: /** @type {import('@docusaurus/preset-classic').ThemeConfig} */ ({ @@ -147,6 +146,24 @@ const config = { ], copyright: `Copyright © ${new Date().getFullYear()} NEAR Protocol | All rights reserved | hello@near.org`, }, + algolia: { + // The application ID provided by Algolia + appId: "Q3YLAPF2JG", + // Public API key: it is safe to commit it + apiKey: "85c789900f6274dc604e76c92c565e5f", + indexName: "nomicon", + // Optional: see doc section below + contextualSearch: false, + // Optional: Algolia search parameters + searchParameters: { + clickAnalytics: true, + analytics: true, + enableReRanking: true, + hitsPerPage: 30, + }, + //... other Algolia params + placeholder: "Search the Docs...", + }, prism: { theme: lightCodeTheme, darkTheme: darkCodeTheme, diff --git a/website/package.json b/website/package.json index bc53d1421..0bf3f81fb 100644 --- a/website/package.json +++ b/website/package.json @@ -14,12 +14,12 @@ "write-heading-ids": "docusaurus write-heading-ids" }, "dependencies": { + "@babel/helper-get-function-arity": "^7.16.7", "@docusaurus/core": "^2.0.0-beta.15", "@docusaurus/plugin-sitemap": "^2.0.0-beta.15", "@docusaurus/preset-classic": "^2.0.0-beta.15", "@mdx-js/react": "^1.6.21", "clsx": "^1.1.1", - "docusaurus-lunr-search": "^2.1.15", "gleap": "^7.0.29", "hast-util-is-element": "1.1.0", "prism-react-renderer": "^1.2.1", diff --git a/website/src/theme/SearchBar/algolia.css b/website/src/theme/SearchBar/algolia.css deleted file mode 100644 index 8f3038edc..000000000 --- a/website/src/theme/SearchBar/algolia.css +++ /dev/null @@ -1,533 +0,0 @@ -/** - * Copyright (c) 2017-present, Facebook, Inc. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -/* Bottom border of each suggestion */ -.algolia-docsearch-suggestion { - border-bottom-color: #3a3dd1; -} -/* Main category headers */ -.algolia-docsearch-suggestion--category-header { - background-color: #4b54de; -} -/* Highlighted search terms */ -.algolia-docsearch-suggestion--highlight { - color: #3a33d1; -} -/* Highligted search terms in the main category headers */ -.algolia-docsearch-suggestion--category-header - .algolia-docsearch-suggestion--highlight { - background-color: #4d47d5; -} -/* Currently selected suggestion */ -.aa-cursor .algolia-docsearch-suggestion--content { - color: #272296; -} -.aa-cursor .algolia-docsearch-suggestion { - background: #ebebfb; -} - -/* For bigger screens, when displaying results in two columns */ -@media (min-width: 768px) { - /* Bottom border of each suggestion */ - .algolia-docsearch-suggestion { - border-bottom-color: #7671df; - } - /* Left column, with secondary category header */ - .algolia-docsearch-suggestion--subcategory-column { - border-right-color: #7671df; - color: #4e4726; - } -} - -.searchbox { - display: inline-block; - position: relative; - width: 200px; - height: 32px !important; - white-space: nowrap; - box-sizing: border-box; - visibility: visible !important; -} - -.searchbox .algolia-autocomplete { - display: block; - width: 100%; - height: 100%; -} - -.searchbox__wrapper { - width: 100%; - height: 100%; - z-index: 999; - position: relative; -} - -.searchbox__input { - display: inline-block; - box-sizing: border-box; - -webkit-transition: box-shadow 0.4s ease, background 0.4s ease; - transition: box-shadow 0.4s ease, background 0.4s ease; - border: 0; - border-radius: 16px; - box-shadow: inset 0 0 0 1px #cccccc; - background: #ffffff !important; - padding: 0; - padding-right: 26px; - padding-left: 32px; - width: 100%; - height: 100%; - vertical-align: middle; - white-space: normal; - font-size: 12px; - -webkit-appearance: none; - -moz-appearance: none; - appearance: none; -} - -.searchbox__input::-webkit-search-decoration, -.searchbox__input::-webkit-search-cancel-button, -.searchbox__input::-webkit-search-results-button, -.searchbox__input::-webkit-search-results-decoration { - display: none; -} - -.searchbox__input:hover { - box-shadow: inset 0 0 0 1px #b3b3b3; -} - -.searchbox__input:focus, -.searchbox__input:active { - outline: 0; - box-shadow: inset 0 0 0 1px #aaaaaa; - background: #ffffff; -} - -.searchbox__input::-webkit-input-placeholder { - color: #aaaaaa; -} - -.searchbox__input::-moz-placeholder { - color: #aaaaaa; -} - -.searchbox__input:-ms-input-placeholder { - color: #aaaaaa; -} - -.searchbox__input::placeholder { - color: #aaaaaa; -} - -.searchbox__submit { - position: absolute; - top: 0; - margin: 0; - border: 0; - border-radius: 16px 0 0 16px; - background-color: rgba(69, 142, 225, 0); - padding: 0; - width: 32px; - height: 100%; - vertical-align: middle; - text-align: center; - font-size: inherit; - -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - user-select: none; - right: inherit; - left: 0; -} - -.searchbox__submit::before { - display: inline-block; - margin-right: -4px; - height: 100%; - vertical-align: middle; - content: ''; -} - -.searchbox__submit:hover, -.searchbox__submit:active { - cursor: pointer; -} - -.searchbox__submit:focus { - outline: 0; -} - -.searchbox__submit svg { - width: 14px; - height: 14px; - vertical-align: middle; - fill: #6d7e96; -} - -.searchbox__reset { - display: block; - position: absolute; - top: 8px; - right: 8px; - margin: 0; - border: 0; - background: none; - cursor: pointer; - padding: 0; - font-size: inherit; - -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - user-select: none; - fill: rgba(0, 0, 0, 0.5); -} - -.searchbox__reset.hide { - display: none; -} - -.searchbox__reset:focus { - outline: 0; -} - -.searchbox__reset svg { - display: block; - margin: 4px; - width: 8px; - height: 8px; -} - -.searchbox__input:valid ~ .searchbox__reset { - display: block; - -webkit-animation-name: sbx-reset-in; - animation-name: sbx-reset-in; - -webkit-animation-duration: 0.15s; - animation-duration: 0.15s; -} - -@-webkit-keyframes sbx-reset-in { - 0% { - -webkit-transform: translate3d(-20%, 0, 0); - transform: translate3d(-20%, 0, 0); - opacity: 0; - } - 100% { - -webkit-transform: none; - transform: none; - opacity: 1; - } -} - -@keyframes sbx-reset-in { - 0% { - -webkit-transform: translate3d(-20%, 0, 0); - transform: translate3d(-20%, 0, 0); - opacity: 0; - } - 100% { - -webkit-transform: none; - transform: none; - opacity: 1; - } -} - -.algolia-autocomplete .ds-dropdown-menu:before { - display: block; - position: absolute; - content: ''; - width: 14px; - height: 14px; - background: #373940; - z-index: 1000; - top: -7px; - border-top: 1px solid #373940; - border-right: 1px solid #373940; - -webkit-transform: rotate(-45deg); - transform: rotate(-45deg); - border-radius: 2px; -} - -.algolia-autocomplete .ds-dropdown-menu { - box-shadow: 0 1px 0 0 rgba(0, 0, 0, 0.2), 0 2px 3px 0 rgba(0, 0, 0, 0.1); -} - -@media (min-width: 601px) { - .algolia-autocomplete.algolia-autocomplete-right .ds-dropdown-menu { - right: 0 !important; - left: inherit !important; - } - - .algolia-autocomplete.algolia-autocomplete-right .ds-dropdown-menu:before { - right: 48px; - } - - .algolia-autocomplete .ds-dropdown-menu { - position: relative; - top: -6px; - border-radius: 4px; - margin: 6px 0 0; - padding: 0; - text-align: left; - height: auto; - position: relative; - background: transparent; - border: none; - z-index: 999; - max-width: 600px; - min-width: 500px; - } -} - -@media (max-width: 600px) { - .algolia-autocomplete .ds-dropdown-menu { - z-index: 100; - position: fixed !important; - top: 50px !important; - left: auto !important; - right: 1rem !important; - width: 600px; - max-width: calc(100% - 2rem); - max-height: calc(100% - 5rem); - display: block; - } - - .algolia-autocomplete .ds-dropdown-menu:before { - right: 6rem; - } -} - -.algolia-autocomplete .ds-dropdown-menu .ds-suggestions { - position: relative; - z-index: 1000; -} - -.algolia-autocomplete .ds-dropdown-menu .ds-suggestion { - cursor: pointer; -} - -.algolia-autocomplete .ds-dropdown-menu [class^='ds-dataset-'] { - position: relative; - border-radius: 4px; - overflow: auto; - padding: 0; - background: #ffffff; -} - -.algolia-autocomplete .ds-dropdown-menu * { - box-sizing: border-box; -} - -.algolia-autocomplete .algolia-docsearch-suggestion { - display: block; - position: relative; - padding: 0; - overflow: hidden; - text-decoration: none; -} - -.algolia-autocomplete .ds-cursor .algolia-docsearch-suggestion--wrapper { - background: #f1f1f1; - box-shadow: inset -2px 0 0 #61dafb; -} - -.algolia-autocomplete .algolia-docsearch-suggestion--highlight { - background: #ffe564; - padding: 0.1em 0.05em; -} - -.algolia-autocomplete - .algolia-docsearch-suggestion--category-header - .algolia-docsearch-suggestion--category-header-lvl0 - .algolia-docsearch-suggestion--highlight, -.algolia-autocomplete - .algolia-docsearch-suggestion--category-header - .algolia-docsearch-suggestion--category-header-lvl1 - .algolia-docsearch-suggestion--highlight { - color: inherit; - background: inherit; -} - -.algolia-autocomplete - .algolia-docsearch-suggestion--text - .algolia-docsearch-suggestion--highlight { - padding: 0 0 1px; - background: inherit; - box-shadow: inset 0 -2px 0 0 rgba(69, 142, 225, 0.8); - color: inherit; -} - -.algolia-autocomplete .algolia-docsearch-suggestion--content { - display: block; - float: right; - width: 70%; - position: relative; - padding: 5.33333px 0 5.33333px 10.66667px; - cursor: pointer; -} - -.algolia-autocomplete .algolia-docsearch-suggestion--content:before { - content: ''; - position: absolute; - display: block; - top: 0; - height: 100%; - width: 1px; - background: #ececec; - left: -1px; -} - -.algolia-autocomplete .algolia-docsearch-suggestion--category-header { - position: relative; - display: none; - font-size: 14px; - letter-spacing: 0.08em; - font-weight: 700; - background-color: #373940; - text-transform: uppercase; - color: #fff; - margin: 0; - padding: 5px 8px; -} - -.algolia-autocomplete .algolia-docsearch-suggestion--wrapper { - background-color: #fff; - width: 100%; - float: left; - padding: 8px 0 0 0; -} - -.algolia-autocomplete .algolia-docsearch-suggestion--subcategory-column { - float: left; - width: 30%; - display: none; - padding-left: 0; - text-align: right; - position: relative; - padding: 5.33333px 10.66667px; - color: #777; - font-size: 0.9em; - word-wrap: break-word; -} - -.algolia-autocomplete .algolia-docsearch-suggestion--subcategory-column:before { - content: ''; - position: absolute; - display: block; - top: 0; - height: 100%; - width: 1px; - background: #ececec; - right: 0; -} - -.algolia-autocomplete - .algolia-docsearch-suggestion.algolia-docsearch-suggestion__main - .algolia-docsearch-suggestion--category-header, -.algolia-autocomplete - .algolia-docsearch-suggestion.algolia-docsearch-suggestion__secondary { - display: block; -} - -.algolia-autocomplete - .algolia-docsearch-suggestion--subcategory-column - .algolia-docsearch-suggestion--highlight { - background-color: inherit; - color: inherit; -} - -.algolia-autocomplete .algolia-docsearch-suggestion--subcategory-inline { - display: none; -} - -.algolia-autocomplete .algolia-docsearch-suggestion--title { - margin-bottom: 4px; - color: #02060c; - font-size: 0.9em; - font-weight: bold; -} - -.algolia-autocomplete .algolia-docsearch-suggestion--text { - display: block; - line-height: 1.2em; - font-size: 0.85em; - color: #63676d; - padding-right: 2px; -} - -.algolia-autocomplete .algolia-docsearch-suggestion--no-results { - width: 100%; - padding: 8px 0; - text-align: center; - font-size: 1.2em; - background-color: #373940; - margin-top: -8px; -} - -.algolia-autocomplete - .algolia-docsearch-suggestion--no-results - .algolia-docsearch-suggestion--text { - color: #ffffff; - margin-top: 4px; -} - -.algolia-autocomplete .algolia-docsearch-suggestion--no-results::before { - display: none; -} - -.algolia-autocomplete .algolia-docsearch-suggestion code { - padding: 1px 5px; - font-size: 90%; - border: none; - color: #222222; - background-color: #ebebeb; - border-radius: 3px; - font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', - monospace; -} - -.algolia-autocomplete - .algolia-docsearch-suggestion - code - .algolia-docsearch-suggestion--highlight { - background: none; -} - -.algolia-autocomplete - .algolia-docsearch-suggestion.algolia-docsearch-suggestion__main - .algolia-docsearch-suggestion--category-header { - color: white; - display: block; -} - -.algolia-autocomplete - .algolia-docsearch-suggestion.algolia-docsearch-suggestion__secondary - .algolia-docsearch-suggestion--subcategory-column { - display: block; -} - -.algolia-autocomplete .algolia-docsearch-footer { - background-color: #fff; - width: 100%; - height: 30px; - z-index: 2000; - float: right; - font-size: 0; - line-height: 0; -} - -.algolia-autocomplete .algolia-docsearch-footer--logo { - background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 130 18'%3E%3Cdefs%3E%3ClinearGradient id='a' x1='-36.87%25' x2='129.43%25' y1='134.94%25' y2='-27.7%25'%3E%3Cstop stop-color='%252300AEFF' offset='0%25'/%3E%3Cstop stop-color='%25233369E7' offset='100%25'/%3E%3C/linearGradient%3E%3C/defs%3E%3Cg fill='none' fill-rule='evenodd'%3E%3Cpath fill='url(%2523a)' d='M59.4.02h13.3a2.37 2.37 0 0 1 2.38 2.37V15.6a2.37 2.37 0 0 1-2.38 2.36H59.4a2.37 2.37 0 0 1-2.38-2.36V2.38A2.37 2.37 0 0 1 59.4.02z'/%3E%3Cpath fill='%2523FFF' d='M66.26 4.56c-2.82 0-5.1 2.27-5.1 5.08 0 2.8 2.28 5.07 5.1 5.07 2.8 0 5.1-2.26 5.1-5.07 0-2.8-2.28-5.07-5.1-5.07zm0 8.65c-2 0-3.6-1.6-3.6-3.56 0-1.97 1.6-3.58 3.6-3.58 1.98 0 3.6 1.6 3.6 3.58a3.58 3.58 0 0 1-3.6 3.57zm0-6.4v2.66c0 .07.08.13.15.1l2.4-1.24c.04-.02.06-.1.03-.14a2.96 2.96 0 0 0-2.46-1.5c-.06 0-.1.05-.1.1zm-3.33-1.96l-.3-.3a.78.78 0 0 0-1.12 0l-.36.36a.77.77 0 0 0 0 1.1l.3.3c.05.05.13.04.17 0 .2-.25.4-.5.6-.7.23-.23.46-.43.7-.6.07-.04.07-.1.03-.16zm5-.8V3.4a.78.78 0 0 0-.78-.78h-1.83a.78.78 0 0 0-.78.78v.63c0 .07.06.12.14.1a5.74 5.74 0 0 1 1.58-.22c.52 0 1.04.07 1.54.2a.1.1 0 0 0 .13-.1z'/%3E%3Cpath fill='%2523182359' d='M102.16 13.76c0 1.46-.37 2.52-1.12 3.2-.75.67-1.9 1-3.44 1-.56 0-1.74-.1-2.67-.3l.34-1.7c.78.17 1.82.2 2.36.2.86 0 1.48-.16 1.84-.5.37-.36.55-.88.55-1.57v-.35a6.37 6.37 0 0 1-.84.3 4.15 4.15 0 0 1-1.2.17 4.5 4.5 0 0 1-1.6-.28 3.38 3.38 0 0 1-1.26-.82 3.74 3.74 0 0 1-.8-1.35c-.2-.54-.3-1.5-.3-2.2 0-.67.1-1.5.3-2.06a3.92 3.92 0 0 1 .9-1.43 4.12 4.12 0 0 1 1.45-.92 5.3 5.3 0 0 1 1.94-.37c.7 0 1.35.1 1.97.2a15.86 15.86 0 0 1 1.6.33v8.46zm-5.95-4.2c0 .9.2 1.88.6 2.3.4.4.9.62 1.53.62.34 0 .66-.05.96-.15a2.75 2.75 0 0 0 .73-.33V6.7a8.53 8.53 0 0 0-1.42-.17c-.76-.02-1.36.3-1.77.8-.4.5-.62 1.4-.62 2.23zm16.13 0c0 .72-.1 1.26-.32 1.85a4.4 4.4 0 0 1-.9 1.53c-.38.42-.85.75-1.4.98-.54.24-1.4.37-1.8.37-.43 0-1.27-.13-1.8-.36a4.1 4.1 0 0 1-1.4-.97 4.5 4.5 0 0 1-.92-1.52 5.04 5.04 0 0 1-.33-1.84c0-.72.1-1.4.32-2 .22-.6.53-1.1.92-1.5.4-.43.86-.75 1.4-.98a4.55 4.55 0 0 1 1.78-.34 4.7 4.7 0 0 1 1.8.34c.54.23 1 .55 1.4.97.38.42.68.92.9 1.5.23.6.35 1.3.35 2zm-2.2 0c0-.92-.2-1.7-.6-2.22-.38-.54-.94-.8-1.64-.8-.72 0-1.27.26-1.67.8-.4.54-.58 1.3-.58 2.22 0 .93.2 1.56.6 2.1.38.54.94.8 1.64.8s1.25-.26 1.65-.8c.4-.55.6-1.17.6-2.1zm6.97 4.7c-3.5.02-3.5-2.8-3.5-3.27L113.57.92l2.15-.34v10c0 .25 0 1.87 1.37 1.88v1.8zm3.77 0h-2.15v-9.2l2.15-.33v9.54zM119.8 3.74c.7 0 1.3-.58 1.3-1.3 0-.7-.58-1.3-1.3-1.3-.73 0-1.3.6-1.3 1.3 0 .72.58 1.3 1.3 1.3zm6.43 1c.7 0 1.3.1 1.78.27.5.18.88.42 1.17.73.28.3.5.74.6 1.18.13.46.2.95.2 1.5v5.47a25.24 25.24 0 0 1-1.5.25c-.67.1-1.42.15-2.25.15a6.83 6.83 0 0 1-1.52-.16 3.2 3.2 0 0 1-1.18-.5 2.46 2.46 0 0 1-.76-.9c-.18-.37-.27-.9-.27-1.44 0-.52.1-.85.3-1.2.2-.37.48-.67.83-.9a3.6 3.6 0 0 1 1.23-.5 7.07 7.07 0 0 1 2.2-.1l.83.16v-.35c0-.25-.03-.48-.1-.7a1.5 1.5 0 0 0-.3-.58c-.15-.18-.34-.3-.58-.4a2.54 2.54 0 0 0-.92-.17c-.5 0-.94.06-1.35.13-.4.08-.75.16-1 .25l-.27-1.74c.27-.1.67-.18 1.2-.28a9.34 9.34 0 0 1 1.65-.14zm.18 7.74c.66 0 1.15-.04 1.5-.1V10.2a5.1 5.1 0 0 0-2-.1c-.23.03-.45.1-.64.2a1.17 1.17 0 0 0-.47.38c-.13.17-.18.26-.18.52 0 .5.17.8.5.98.32.2.74.3 1.3.3zM84.1 4.8c.72 0 1.3.08 1.8.26.48.17.87.42 1.15.73.3.3.5.72.6 1.17.14.45.2.94.2 1.47v5.48a25.24 25.24 0 0 1-1.5.26c-.67.1-1.42.14-2.25.14a6.83 6.83 0 0 1-1.52-.16 3.2 3.2 0 0 1-1.18-.5 2.46 2.46 0 0 1-.76-.9c-.18-.38-.27-.9-.27-1.44 0-.53.1-.86.3-1.22.2-.36.5-.65.84-.88a3.6 3.6 0 0 1 1.24-.5 7.07 7.07 0 0 1 2.2-.1c.26.03.54.08.84.15v-.35c0-.24-.03-.48-.1-.7a1.5 1.5 0 0 0-.3-.58c-.15-.17-.34-.3-.58-.4a2.54 2.54 0 0 0-.9-.15c-.5 0-.96.05-1.37.12-.4.07-.75.15-1 .24l-.26-1.75c.27-.08.67-.17 1.18-.26a8.9 8.9 0 0 1 1.66-.15zm.2 7.73c.65 0 1.14-.04 1.48-.1v-2.17a5.1 5.1 0 0 0-1.98-.1c-.24.03-.46.1-.65.18a1.17 1.17 0 0 0-.47.4c-.12.17-.17.26-.17.52 0 .5.18.8.5.98.32.2.75.3 1.3.3zm8.68 1.74c-3.5 0-3.5-2.82-3.5-3.28L89.45.92 91.6.6v10c0 .25 0 1.87 1.38 1.88v1.8z'/%3E%3Cpath fill='%25231D3657' d='M5.03 11.03c0 .7-.26 1.24-.76 1.64-.5.4-1.2.6-2.1.6-.88 0-1.6-.14-2.17-.42v-1.2c.36.16.74.3 1.14.38.4.1.78.15 1.13.15.5 0 .88-.1 1.12-.3a.94.94 0 0 0 .35-.77.98.98 0 0 0-.33-.74c-.22-.2-.68-.44-1.37-.72-.72-.3-1.22-.62-1.52-1C.23 8.27.1 7.82.1 7.3c0-.65.22-1.17.7-1.55.46-.37 1.08-.56 1.86-.56.76 0 1.5.16 2.25.48l-.4 1.05c-.7-.3-1.32-.44-1.87-.44-.4 0-.73.08-.94.26a.9.9 0 0 0-.33.72c0 .2.04.38.12.52.08.15.22.3.42.4.2.14.55.3 1.06.52.58.24 1 .47 1.27.67.27.2.47.44.6.7.12.26.18.57.18.92zM9 13.27c-.92 0-1.64-.27-2.16-.8-.52-.55-.78-1.3-.78-2.24 0-.97.24-1.73.72-2.3.5-.54 1.15-.82 2-.82.78 0 1.4.25 1.85.72.46.48.7 1.14.7 1.97v.67H7.35c0 .58.17 1.02.46 1.33.3.3.7.47 1.24.47.36 0 .68-.04.98-.1a5.1 5.1 0 0 0 .98-.33v1.02a3.87 3.87 0 0 1-.94.32 5.72 5.72 0 0 1-1.08.1zm-.22-5.2c-.4 0-.73.12-.97.38s-.37.62-.42 1.1h2.7c0-.48-.13-.85-.36-1.1-.23-.26-.54-.38-.94-.38zm7.7 5.1l-.26-.84h-.05c-.28.36-.57.6-.86.74-.28.13-.65.2-1.1.2-.6 0-1.05-.16-1.38-.48-.32-.32-.5-.77-.5-1.34 0-.62.24-1.08.7-1.4.45-.3 1.14-.47 2.07-.5l1.02-.03V9.2c0-.37-.1-.65-.27-.84-.17-.2-.45-.28-.82-.28-.3 0-.6.04-.88.13a6.68 6.68 0 0 0-.8.33l-.4-.9a4.4 4.4 0 0 1 1.05-.4 4.86 4.86 0 0 1 1.08-.12c.76 0 1.33.18 1.7.5.4.33.6.85.6 1.56v4h-.9zm-1.9-.87c.47 0 .83-.13 1.1-.38.3-.26.43-.62.43-1.08v-.52l-.76.03c-.6.03-1.02.13-1.3.3s-.4.45-.4.82c0 .26.08.47.24.6.16.16.4.23.7.23zm7.57-5.2c.25 0 .46.03.62.06l-.12 1.18a2.38 2.38 0 0 0-.56-.06c-.5 0-.92.16-1.24.5-.3.32-.47.75-.47 1.27v3.1h-1.27V7.23h1l.16 1.05h.05c.2-.36.45-.64.77-.85a1.83 1.83 0 0 1 1.02-.3zm4.12 6.17c-.9 0-1.58-.27-2.05-.8-.47-.52-.7-1.27-.7-2.25 0-1 .24-1.77.73-2.3.5-.54 1.2-.8 2.12-.8.63 0 1.2.1 1.7.34l-.4 1c-.52-.2-.96-.3-1.3-.3-1.04 0-1.55.68-1.55 2.05 0 .67.13 1.17.38 1.5.26.34.64.5 1.13.5a3.23 3.23 0 0 0 1.6-.4v1.1a2.53 2.53 0 0 1-.73.28 4.36 4.36 0 0 1-.93.08zm8.28-.1h-1.27V9.5c0-.45-.1-.8-.28-1.02-.18-.23-.47-.34-.88-.34-.53 0-.9.16-1.16.48-.25.3-.38.85-.38 1.6v2.94h-1.26V4.8h1.26v2.12c0 .34-.02.7-.06 1.1h.08a1.76 1.76 0 0 1 .72-.67c.3-.16.66-.24 1.07-.24 1.43 0 2.15.74 2.15 2.2v3.86zM42.2 7.1c.74 0 1.32.28 1.73.82.4.53.62 1.3.62 2.26 0 .97-.2 1.73-.63 2.27-.42.54-1 .82-1.75.82s-1.33-.27-1.75-.8h-.08l-.23.7h-.94V4.8h1.26v2l-.02.64-.03.56h.05c.4-.6 1-.9 1.78-.9zm-.33 1.04c-.5 0-.88.15-1.1.45-.22.3-.34.8-.35 1.5v.08c0 .72.12 1.24.35 1.57.23.32.6.48 1.12.48.44 0 .78-.17 1-.53.24-.35.36-.87.36-1.53 0-1.35-.47-2.03-1.4-2.03zm3.24-.92h1.4l1.2 3.37c.18.47.3.92.36 1.34h.04l.18-.72 1.37-4H51l-2.53 6.73c-.46 1.23-1.23 1.85-2.3 1.85-.3 0-.56-.03-.83-.1v-1c.2.05.4.08.65.08.6 0 1.03-.36 1.28-1.06l.22-.56-2.4-5.94z'/%3E%3C/g%3E%3C/svg%3E"); - background-repeat: no-repeat; - background-position: center; - background-size: 100%; - overflow: hidden; - text-indent: -9000px; - width: 110px; - height: 100%; - display: block; - margin-left: auto; - margin-right: 5px; -} diff --git a/website/src/theme/SearchBar/index.js b/website/src/theme/SearchBar/index.js deleted file mode 100644 index 2f189d11e..000000000 --- a/website/src/theme/SearchBar/index.js +++ /dev/null @@ -1,118 +0,0 @@ -/** - * Copyright (c) 2017-present, Facebook, Inc. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -import React, { useRef, useCallback, useState } from "react"; -import classnames from "classnames"; -import { useHistory } from "@docusaurus/router"; -import useDocusaurusContext from "@docusaurus/useDocusaurusContext"; -import { usePluginData } from '@docusaurus/useGlobalData'; -const Search = props => { - const initialized = useRef(false); - const searchBarRef = useRef(null); - const [indexReady, setIndexReady] = useState(false); - const history = useHistory(); - const { siteConfig = {}, isClient = false} = useDocusaurusContext(); - const { baseUrl } = siteConfig; - const initAlgolia = (searchDocs, searchIndex, DocSearch) => { - new DocSearch({ - searchDocs, - searchIndex, - inputSelector: "#search_input_react", - // Override algolia's default selection event, allowing us to do client-side - // navigation and avoiding a full page refresh. - handleSelected: (_input, _event, suggestion) => { - const url = baseUrl + suggestion.url; - // Use an anchor tag to parse the absolute url into a relative url - // Alternatively, we can use new URL(suggestion.url) but its not supported in IE - const a = document.createElement("a"); - a.href = url; - // Algolia use closest parent element id #__docusaurus when a h1 page title does not have an id - // So, we can safely remove it. See https://github.com/facebook/docusaurus/issues/1828 for more details. - - history.push(url); - } - }); - }; - - const pluginData = usePluginData('docusaurus-lunr-search'); - const getSearchDoc = () => - process.env.NODE_ENV === "production" - ? fetch(`${baseUrl}${pluginData.fileNames.searchDoc}`).then((content) => content.json()) - : Promise.resolve([]); - - const getLunrIndex = () => - process.env.NODE_ENV === "production" - ? fetch(`${baseUrl}${pluginData.fileNames.lunrIndex}`).then((content) => content.json()) - : Promise.resolve([]); - - const loadAlgolia = () => { - if (!initialized.current) { - Promise.all([ - getSearchDoc(), - getLunrIndex(), - import("./lib/DocSearch"), - import("./algolia.css") - ]).then(([searchDocs, searchIndex, { default: DocSearch }]) => { - if( searchDocs.length === 0) { - return; - } - initAlgolia(searchDocs, searchIndex, DocSearch); - setIndexReady(true); - }); - initialized.current = true; - } - }; - - const toggleSearchIconClick = useCallback( - e => { - if (!searchBarRef.current.contains(e.target)) { - searchBarRef.current.focus(); - } - - props.handleSearchBarToggle && props.handleSearchBarToggle(!props.isSearchBarExpanded); - }, - [props.isSearchBarExpanded] - ); - - if (isClient) { - loadAlgolia(); - } - - return ( -
- - -
- ); -}; - -export default Search; diff --git a/website/src/theme/SearchBar/lib/DocSearch.js b/website/src/theme/SearchBar/lib/DocSearch.js deleted file mode 100644 index ffdca6a59..000000000 --- a/website/src/theme/SearchBar/lib/DocSearch.js +++ /dev/null @@ -1,306 +0,0 @@ -import Hogan from "hogan.js"; -import LunrSearchAdapter from "./lunar-search"; -import autocomplete from "autocomplete.js"; -import templates from "./templates"; -import utils from "./utils"; -import $ from "autocomplete.js/zepto"; - -/** - * Adds an autocomplete dropdown to an input field - * @function DocSearch - * @param {Object} options.searchDocs Search Documents - * @param {Object} options.searchIndex Lune searchIndexes - * @param {string} options.inputSelector CSS selector that targets the input - * value. - * @param {Object} [options.autocompleteOptions] Options to pass to the underlying autocomplete instance - * @return {Object} - */ -class DocSearch { - constructor({ - searchDocs, - searchIndex, - inputSelector, - debug = false, - queryDataCallback = null, - autocompleteOptions = { - debug: false, - hint: false, - autoselect: true - }, - transformData = false, - queryHook = false, - handleSelected = false, - enhancedSearchInput = false, - layout = "collumns" - }) { - this.input = DocSearch.getInputFromSelector(inputSelector); - this.queryDataCallback = queryDataCallback || null; - const autocompleteOptionsDebug = - autocompleteOptions && autocompleteOptions.debug - ? autocompleteOptions.debug - : false; - // eslint-disable-next-line no-param-reassign - autocompleteOptions.debug = debug || autocompleteOptionsDebug; - this.autocompleteOptions = autocompleteOptions; - this.autocompleteOptions.cssClasses = - this.autocompleteOptions.cssClasses || {}; - this.autocompleteOptions.cssClasses.prefix = - this.autocompleteOptions.cssClasses.prefix || "ds"; - const inputAriaLabel = - this.input && - typeof this.input.attr === "function" && - this.input.attr("aria-label"); - this.autocompleteOptions.ariaLabel = - this.autocompleteOptions.ariaLabel || inputAriaLabel || "search input"; - - this.isSimpleLayout = layout === "simple"; - - this.client = new LunrSearchAdapter(searchDocs, searchIndex); - - if (enhancedSearchInput) { - this.input = DocSearch.injectSearchBox(this.input); - } - this.autocomplete = autocomplete(this.input, autocompleteOptions, [ - { - source: this.getAutocompleteSource(transformData, queryHook), - templates: { - suggestion: DocSearch.getSuggestionTemplate(this.isSimpleLayout), - footer: templates.footer, - empty: DocSearch.getEmptyTemplate() - } - } - ]); - - const customHandleSelected = handleSelected; - this.handleSelected = customHandleSelected || this.handleSelected; - - // We prevent default link clicking if a custom handleSelected is defined - if (customHandleSelected) { - $(".algolia-autocomplete").on("click", ".ds-suggestions a", event => { - event.preventDefault(); - }); - } - - this.autocomplete.on( - "autocomplete:selected", - this.handleSelected.bind(null, this.autocomplete.autocomplete) - ); - - this.autocomplete.on( - "autocomplete:shown", - this.handleShown.bind(null, this.input) - ); - - if (enhancedSearchInput) { - DocSearch.bindSearchBoxEvent(); - } - } - - static injectSearchBox(input) { - input.before(templates.searchBox); - const newInput = input - .prev() - .prev() - .find("input"); - input.remove(); - return newInput; - } - - static bindSearchBoxEvent() { - $('.searchbox [type="reset"]').on("click", function () { - $("input#docsearch").focus(); - $(this).addClass("hide"); - autocomplete.autocomplete.setVal(""); - }); - - $("input#docsearch").on("keyup", () => { - const searchbox = document.querySelector("input#docsearch"); - const reset = document.querySelector('.searchbox [type="reset"]'); - reset.className = "searchbox__reset"; - if (searchbox.value.length === 0) { - reset.className += " hide"; - } - }); - } - - /** - * Returns the matching input from a CSS selector, null if none matches - * @function getInputFromSelector - * @param {string} selector CSS selector that matches the search - * input of the page - * @returns {void} - */ - static getInputFromSelector(selector) { - const input = $(selector).filter("input"); - return input.length ? $(input[0]) : null; - } - - /** - * Returns the `source` method to be passed to autocomplete.js. It will query - * the Algolia index and call the callbacks with the formatted hits. - * @function getAutocompleteSource - * @param {function} transformData An optional function to transform the hits - * @param {function} queryHook An optional function to transform the query - * @returns {function} Method to be passed as the `source` option of - * autocomplete - */ - getAutocompleteSource(transformData, queryHook) { - return (query, callback) => { - if (queryHook) { - // eslint-disable-next-line no-param-reassign - query = queryHook(query) || query; - } - this.client.search(query).then(hits => { - if ( - this.queryDataCallback && - typeof this.queryDataCallback == "function" - ) { - this.queryDataCallback(hits); - } - if (transformData) { - hits = transformData(hits) || hits; - } - callback(DocSearch.formatHits(hits)); - }); - }; - } - - // Given a list of hits returned by the API, will reformat them to be used in - // a Hogan template - static formatHits(receivedHits) { - const clonedHits = utils.deepClone(receivedHits); - const hits = clonedHits.map(hit => { - if (hit._highlightResult) { - // eslint-disable-next-line no-param-reassign - hit._highlightResult = utils.mergeKeyWithParent( - hit._highlightResult, - "hierarchy" - ); - } - return utils.mergeKeyWithParent(hit, "hierarchy"); - }); - - // Group hits by category / subcategory - let groupedHits = utils.groupBy(hits, "lvl0"); - $.each(groupedHits, (level, collection) => { - const groupedHitsByLvl1 = utils.groupBy(collection, "lvl1"); - const flattenedHits = utils.flattenAndFlagFirst( - groupedHitsByLvl1, - "isSubCategoryHeader" - ); - groupedHits[level] = flattenedHits; - }); - groupedHits = utils.flattenAndFlagFirst(groupedHits, "isCategoryHeader"); - - // Translate hits into smaller objects to be send to the template - return groupedHits.map(hit => { - const url = DocSearch.formatURL(hit); - const category = utils.getHighlightedValue(hit, "lvl0"); - const subcategory = utils.getHighlightedValue(hit, "lvl1") || category; - const displayTitle = utils - .compact([ - utils.getHighlightedValue(hit, "lvl2") || subcategory, - utils.getHighlightedValue(hit, "lvl3"), - utils.getHighlightedValue(hit, "lvl4"), - utils.getHighlightedValue(hit, "lvl5"), - utils.getHighlightedValue(hit, "lvl6") - ]) - .join( - '' - ); - const text = utils.getSnippetedValue(hit, "content"); - const isTextOrSubcategoryNonEmpty = - (subcategory && subcategory !== "") || - (displayTitle && displayTitle !== ""); - const isLvl1EmptyOrDuplicate = - !subcategory || subcategory === "" || subcategory === category; - const isLvl2 = - displayTitle && displayTitle !== "" && displayTitle !== subcategory; - const isLvl1 = - !isLvl2 && - (subcategory && subcategory !== "" && subcategory !== category); - const isLvl0 = !isLvl1 && !isLvl2; - - return { - isLvl0, - isLvl1, - isLvl2, - isLvl1EmptyOrDuplicate, - isCategoryHeader: hit.isCategoryHeader, - isSubCategoryHeader: hit.isSubCategoryHeader, - isTextOrSubcategoryNonEmpty, - category, - subcategory, - title: displayTitle, - text, - url - }; - }); - } - - static formatURL(hit) { - const { url, anchor } = hit; - if (url) { - const containsAnchor = url.indexOf("#") !== -1; - if (containsAnchor) return url; - else if (anchor) return `${hit.url}#${hit.anchor}`; - return url; - } else if (anchor) return `#${hit.anchor}`; - /* eslint-disable */ - console.warn("no anchor nor url for : ", JSON.stringify(hit)); - /* eslint-enable */ - return null; - } - - static getEmptyTemplate() { - return args => Hogan.compile(templates.empty).render(args); - } - - static getSuggestionTemplate(isSimpleLayout) { - const stringTemplate = isSimpleLayout - ? templates.suggestionSimple - : templates.suggestion; - const template = Hogan.compile(stringTemplate); - return suggestion => template.render(suggestion); - } - - handleSelected(input, event, suggestion, datasetNumber, context = {}) { - // Do nothing if click on the suggestion, as it's already a , the - // browser will take care of it. This allow Ctrl-Clicking on results and not - // having the main window being redirected as well - if (context.selectionMethod === "click") { - return; - } - - input.setVal(""); - window.location.assign(suggestion.url); - } - - handleShown(input) { - const middleOfInput = input.offset().left + input.width() / 2; - let middleOfWindow = $(document).width() / 2; - - if (isNaN(middleOfWindow)) { - middleOfWindow = 900; - } - - const alignClass = - middleOfInput - middleOfWindow >= 0 - ? "algolia-autocomplete-right" - : "algolia-autocomplete-left"; - const otherAlignClass = - middleOfInput - middleOfWindow < 0 - ? "algolia-autocomplete-right" - : "algolia-autocomplete-left"; - const autocompleteWrapper = $(".algolia-autocomplete"); - if (!autocompleteWrapper.hasClass(alignClass)) { - autocompleteWrapper.addClass(alignClass); - } - - if (autocompleteWrapper.hasClass(otherAlignClass)) { - autocompleteWrapper.removeClass(otherAlignClass); - } - } -} - -export default DocSearch; \ No newline at end of file diff --git a/website/src/theme/SearchBar/lib/lunar-search.js b/website/src/theme/SearchBar/lib/lunar-search.js deleted file mode 100644 index 159b79504..000000000 --- a/website/src/theme/SearchBar/lib/lunar-search.js +++ /dev/null @@ -1,146 +0,0 @@ -import lunr from "@generated/lunr.client"; -lunr.tokenizer.separator = /[\s\-/]+/; - -class LunrSearchAdapter { - constructor(searchDocs, searchIndex) { - this.searchDocs = searchDocs; - this.lunrIndex = lunr.Index.load(searchIndex); - } - - getLunrResult(input) { - return this.lunrIndex.query(function (query) { - const tokens = lunr.tokenizer(input); - query.term(tokens, { - boost: 10 - }); - query.term(tokens, { - wildcard: lunr.Query.wildcard.TRAILING - }); - }); - } - - getHit(doc, formattedTitle, formattedContent) { - return { - hierarchy: { - lvl0: doc.pageTitle || doc.title, - lvl1: doc.type === 0 ? null : doc.title - }, - url: doc.url, - _snippetResult: formattedContent ? { - content: { - value: formattedContent, - matchLevel: "full" - } - } : null, - _highlightResult: { - hierarchy: { - lvl0: { - value: doc.type === 0 ? formattedTitle || doc.title : doc.pageTitle, - }, - lvl1: - doc.type === 0 - ? null - : { - value: formattedTitle || doc.title - } - } - } - }; - } - getTitleHit(doc, position, length) { - const start = position[0]; - const end = position[0] + length; - let formattedTitle = doc.title.substring(0, start) + '' + doc.title.substring(start, end) + '' + doc.title.substring(end, doc.title.length); - return this.getHit(doc, formattedTitle) - } - - getKeywordHit(doc, position, length) { - const start = position[0]; - const end = position[0] + length; - let formattedTitle = doc.title + '
Keywords: ' + doc.keywords.substring(0, start) + '' + doc.keywords.substring(start, end) + '' + doc.keywords.substring(end, doc.keywords.length) + '' - return this.getHit(doc, formattedTitle) - } - - getContentHit(doc, position) { - const start = position[0]; - const end = position[0] + position[1]; - let previewStart = start; - let previewEnd = end; - let ellipsesBefore = true; - let ellipsesAfter = true; - for (let k = 0; k < 3; k++) { - const nextSpace = doc.content.lastIndexOf(' ', previewStart - 2); - const nextDot = doc.content.lastIndexOf('.', previewStart - 2); - if ((nextDot > 0) && (nextDot > nextSpace)) { - previewStart = nextDot + 1; - ellipsesBefore = false; - break; - } - if (nextSpace < 0) { - previewStart = 0; - ellipsesBefore = false; - break; - } - previewStart = nextSpace + 1; - } - for (let k = 0; k < 10; k++) { - const nextSpace = doc.content.indexOf(' ', previewEnd + 1); - const nextDot = doc.content.indexOf('.', previewEnd + 1); - if ((nextDot > 0) && (nextDot < nextSpace)) { - previewEnd = nextDot; - ellipsesAfter = false; - break; - } - if (nextSpace < 0) { - previewEnd = doc.content.length; - ellipsesAfter = false; - break; - } - previewEnd = nextSpace; - } - let preview = doc.content.substring(previewStart, start); - if (ellipsesBefore) { - preview = '... ' + preview; - } - preview += '' + doc.content.substring(start, end) + ''; - preview += doc.content.substring(end, previewEnd); - if (ellipsesAfter) { - preview += ' ...'; - } - return this.getHit(doc, null, preview); - - } - search(input) { - return new Promise((resolve, rej) => { - const results = this.getLunrResult(input); - const hits = []; - results.length > 5 && (results.length = 5); - this.titleHitsRes = [] - this.contentHitsRes = [] - results.forEach(result => { - const doc = this.searchDocs[result.ref]; - const { metadata } = result.matchData; - for (let i in metadata) { - if (metadata[i].title) { - if (!this.titleHitsRes.includes(result.ref)) { - const position = metadata[i].title.position[0] - hits.push(this.getTitleHit(doc, position, input.length)); - this.titleHitsRes.push(result.ref); - } - } else if (metadata[i].content) { - const position = metadata[i].content.position[0] - hits.push(this.getContentHit(doc, position)) - } else if (metadata[i].keywords) { - const position = metadata[i].keywords.position[0] - hits.push(this.getKeywordHit(doc, position, input.length)); - this.titleHitsRes.push(result.ref); - } - } - }); - hits.length > 5 && (hits.length = 5); - resolve(hits); - }); - } -} - -export default LunrSearchAdapter; diff --git a/website/src/theme/SearchBar/lib/templates.js b/website/src/theme/SearchBar/lib/templates.js deleted file mode 100644 index c7ea998fd..000000000 --- a/website/src/theme/SearchBar/lib/templates.js +++ /dev/null @@ -1,114 +0,0 @@ -const prefix = 'algolia-docsearch'; -const suggestionPrefix = `${prefix}-suggestion`; -const footerPrefix = `${prefix}-footer`; - -/* eslint-disable max-len */ - -const templates = { - suggestion: ` -
-
- {{{category}}} -
-
-
- {{{subcategory}}} -
- {{#isTextOrSubcategoryNonEmpty}} -
-
{{{subcategory}}}
-
{{{title}}}
- {{#text}}
{{{text}}}
{{/text}} -
- {{/isTextOrSubcategoryNonEmpty}} -
-
- `, - suggestionSimple: ` -
-
- {{^isLvl0}} - {{{category}}} - {{^isLvl1}} - {{^isLvl1EmptyOrDuplicate}} - - {{{subcategory}}} - - {{/isLvl1EmptyOrDuplicate}} - {{/isLvl1}} - {{/isLvl0}} -
- {{#isLvl2}} - {{{title}}} - {{/isLvl2}} - {{#isLvl1}} - {{{subcategory}}} - {{/isLvl1}} - {{#isLvl0}} - {{{category}}} - {{/isLvl0}} -
-
-
- {{#text}} -
-
{{{text}}}
-
- {{/text}} -
-
- `, - footer: ` -
-
- `, - empty: ` -
-
-
-
-
- No results found for query "{{query}}" -
-
-
-
-
- `, - searchBox: ` - - - - `, -}; - -export default templates; diff --git a/website/src/theme/SearchBar/lib/utils.js b/website/src/theme/SearchBar/lib/utils.js deleted file mode 100644 index 0807500d7..000000000 --- a/website/src/theme/SearchBar/lib/utils.js +++ /dev/null @@ -1,270 +0,0 @@ -import $ from "autocomplete.js/zepto"; - -const utils = { - /* - * Move the content of an object key one level higher. - * eg. - * { - * name: 'My name', - * hierarchy: { - * lvl0: 'Foo', - * lvl1: 'Bar' - * } - * } - * Will be converted to - * { - * name: 'My name', - * lvl0: 'Foo', - * lvl1: 'Bar' - * } - * @param {Object} object Main object - * @param {String} property Main object key to move up - * @return {Object} - * @throws Error when key is not an attribute of Object or is not an object itself - */ - mergeKeyWithParent(object, property) { - if (object[property] === undefined) { - return object; - } - if (typeof object[property] !== 'object') { - return object; - } - const newObject = $.extend({}, object, object[property]); - delete newObject[property]; - return newObject; - }, - /* - * Group all objects of a collection by the value of the specified attribute - * If the attribute is a string, use the lowercase form. - * - * eg. - * groupBy([ - * {name: 'Tim', category: 'dev'}, - * {name: 'Vincent', category: 'dev'}, - * {name: 'Ben', category: 'sales'}, - * {name: 'Jeremy', category: 'sales'}, - * {name: 'AlexS', category: 'dev'}, - * {name: 'AlexK', category: 'sales'} - * ], 'category'); - * => - * { - * 'devs': [ - * {name: 'Tim', category: 'dev'}, - * {name: 'Vincent', category: 'dev'}, - * {name: 'AlexS', category: 'dev'} - * ], - * 'sales': [ - * {name: 'Ben', category: 'sales'}, - * {name: 'Jeremy', category: 'sales'}, - * {name: 'AlexK', category: 'sales'} - * ] - * } - * @param {array} collection Array of objects to group - * @param {String} property The attribute on which apply the grouping - * @return {array} - * @throws Error when one of the element does not have the specified property - */ - groupBy(collection, property) { - const newCollection = {}; - $.each(collection, (index, item) => { - if (item[property] === undefined) { - throw new Error(`[groupBy]: Object has no key ${property}`); - } - let key = item[property]; - if (typeof key === 'string') { - key = key.toLowerCase(); - } - // fix #171 the given data type of docsearch hits might be conflict with the properties of the native Object, - // such as the constructor, so we need to do this check. - if (!Object.prototype.hasOwnProperty.call(newCollection, key)) { - newCollection[key] = []; - } - newCollection[key].push(item); - }); - return newCollection; - }, - /* - * Return an array of all the values of the specified object - * eg. - * values({ - * foo: 42, - * bar: true, - * baz: 'yep' - * }) - * => - * [42, true, yep] - * @param {object} object Object to extract values from - * @return {array} - */ - values(object) { - return Object.keys(object).map(key => object[key]); - }, - /* - * Flattens an array - * eg. - * flatten([1, 2, [3, 4], [5, 6]]) - * => - * [1, 2, 3, 4, 5, 6] - * @param {array} array Array to flatten - * @return {array} - */ - flatten(array) { - const results = []; - array.forEach(value => { - if (!Array.isArray(value)) { - results.push(value); - return; - } - value.forEach(subvalue => { - results.push(subvalue); - }); - }); - return results; - }, - /* - * Flatten all values of an object into an array, marking each first element of - * each group with a specific flag - * eg. - * flattenAndFlagFirst({ - * 'devs': [ - * {name: 'Tim', category: 'dev'}, - * {name: 'Vincent', category: 'dev'}, - * {name: 'AlexS', category: 'dev'} - * ], - * 'sales': [ - * {name: 'Ben', category: 'sales'}, - * {name: 'Jeremy', category: 'sales'}, - * {name: 'AlexK', category: 'sales'} - * ] - * , 'isTop'); - * => - * [ - * {name: 'Tim', category: 'dev', isTop: true}, - * {name: 'Vincent', category: 'dev', isTop: false}, - * {name: 'AlexS', category: 'dev', isTop: false}, - * {name: 'Ben', category: 'sales', isTop: true}, - * {name: 'Jeremy', category: 'sales', isTop: false}, - * {name: 'AlexK', category: 'sales', isTop: false} - * ] - * @param {object} object Object to flatten - * @param {string} flag Flag to set to true on first element of each group - * @return {array} - */ - flattenAndFlagFirst(object, flag) { - const values = this.values(object).map(collection => - collection.map((item, index) => { - // eslint-disable-next-line no-param-reassign - item[flag] = index === 0; - return item; - }) - ); - return this.flatten(values); - }, - /* - * Removes all empty strings, null, false and undefined elements array - * eg. - * compact([42, false, null, undefined, '', [], 'foo']); - * => - * [42, [], 'foo'] - * @param {array} array Array to compact - * @return {array} - */ - compact(array) { - const results = []; - array.forEach(value => { - if (!value) { - return; - } - results.push(value); - }); - return results; - }, - /* - * Returns the highlighted value of the specified key in the specified object. - * If no highlighted value is available, will return the key value directly - * eg. - * getHighlightedValue({ - * _highlightResult: { - * text: { - * value: 'foo' - * } - * }, - * text: 'foo' - * }, 'text'); - * => - * 'foo' - * @param {object} object Hit object returned by the Algolia API - * @param {string} property Object key to look for - * @return {string} - **/ - getHighlightedValue(object, property) { - if ( - object._highlightResult && - object._highlightResult.hierarchy_camel && - object._highlightResult.hierarchy_camel[property] && - object._highlightResult.hierarchy_camel[property].matchLevel && - object._highlightResult.hierarchy_camel[property].matchLevel !== 'none' && - object._highlightResult.hierarchy_camel[property].value - ) { - return object._highlightResult.hierarchy_camel[property].value; - } - if ( - object._highlightResult && - object._highlightResult && - object._highlightResult[property] && - object._highlightResult[property].value - ) { - return object._highlightResult[property].value; - } - return object[property]; - }, - /* - * Returns the snippeted value of the specified key in the specified object. - * If no highlighted value is available, will return the key value directly. - * Will add starting and ending ellipsis (…) if we detect that a sentence is - * incomplete - * eg. - * getSnippetedValue({ - * _snippetResult: { - * text: { - * value: 'This is an unfinished sentence' - * } - * }, - * text: 'This is an unfinished sentence' - * }, 'text'); - * => - * 'This is an unfinished sentence…' - * @param {object} object Hit object returned by the Algolia API - * @param {string} property Object key to look for - * @return {string} - **/ - getSnippetedValue(object, property) { - if ( - !object._snippetResult || - !object._snippetResult[property] || - !object._snippetResult[property].value - ) { - return object[property]; - } - let snippet = object._snippetResult[property].value; - - if (snippet[0] !== snippet[0].toUpperCase()) { - snippet = `…${snippet}`; - } - if (['.', '!', '?'].indexOf(snippet[snippet.length - 1]) === -1) { - snippet = `${snippet}…`; - } - return snippet; - }, - /* - * Deep clone an object. - * Note: This will not clone functions and dates - * @param {object} object Object to clone - * @return {object} - */ - deepClone(object) { - return JSON.parse(JSON.stringify(object)); - }, -}; - -export default utils; diff --git a/website/src/theme/SearchBar/styles.css b/website/src/theme/SearchBar/styles.css deleted file mode 100644 index 047517ec0..000000000 --- a/website/src/theme/SearchBar/styles.css +++ /dev/null @@ -1,40 +0,0 @@ -/** - * Copyright (c) 2017-present, Facebook, Inc. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -.search-icon { - background-image: var(--ifm-navbar-search-input-icon); - height: auto; - width: 24px; - cursor: pointer; - padding: 8px; - line-height: 32px; - background-repeat: no-repeat; - background-position: center; - display: none; -} - -.search-icon-hidden { - visibility: hidden; -} - -@media (max-width: 360px) { - .search-bar { - width: 0 !important; - background: none !important; - padding: 0 !important; - transition: none !important; - } - - .search-bar-expanded { - width: 9rem !important; - } - - .search-icon { - display: inline; - vertical-align: sub; - } -} diff --git a/website/yarn.lock b/website/yarn.lock index d9430b961..66c62c12d 100644 --- a/website/yarn.lock +++ b/website/yarn.lock @@ -2,145 +2,153 @@ # yarn lockfile v1 -"@algolia/autocomplete-core@1.5.0": - version "1.5.0" - resolved "https://registry.yarnpkg.com/@algolia/autocomplete-core/-/autocomplete-core-1.5.0.tgz#6c91c9de7748e9c103846828a58dfe92bd4d6689" - integrity sha512-E7+VJwcvwMM8vPeaVn7fNUgix8WHV8A1WUeHDi2KHemCaaGc8lvUnP3QnvhMxiDhTe7OpMEv4o2TBUMyDgThaw== +"@algolia/autocomplete-core@1.7.2": + version "1.7.2" + resolved "https://registry.yarnpkg.com/@algolia/autocomplete-core/-/autocomplete-core-1.7.2.tgz#8abbed88082f611997538760dffcb43b33b1fd1d" + integrity sha512-eclwUDC6qfApNnEfu1uWcL/rudQsn59tjEoUYZYE2JSXZrHLRjBUGMxiCoknobU2Pva8ejb0eRxpIYDtVVqdsw== dependencies: - "@algolia/autocomplete-shared" "1.5.0" + "@algolia/autocomplete-shared" "1.7.2" -"@algolia/autocomplete-preset-algolia@1.5.0": - version "1.5.0" - resolved "https://registry.yarnpkg.com/@algolia/autocomplete-preset-algolia/-/autocomplete-preset-algolia-1.5.0.tgz#61671f09c0c77133d9baf1356719f8378c48437a" - integrity sha512-iiFxKERGHkvkiupmrFJbvESpP/zv5jSgH714XRiP5LDvUHaYOo4GLAwZCFf2ef/L5tdtPBARvekn6k1Xf33gjA== +"@algolia/autocomplete-preset-algolia@1.7.2": + version "1.7.2" + resolved "https://registry.yarnpkg.com/@algolia/autocomplete-preset-algolia/-/autocomplete-preset-algolia-1.7.2.tgz#9cd4f64b3d64399657ee2dc2b7e0a939e0713a26" + integrity sha512-+RYEG6B0QiGGfRb2G3MtPfyrl0dALF3cQNTWBzBX6p5o01vCCGTTinAm2UKG3tfc2CnOMAtnPLkzNZyJUpnVJw== dependencies: - "@algolia/autocomplete-shared" "1.5.0" + "@algolia/autocomplete-shared" "1.7.2" -"@algolia/autocomplete-shared@1.5.0": - version "1.5.0" - resolved "https://registry.yarnpkg.com/@algolia/autocomplete-shared/-/autocomplete-shared-1.5.0.tgz#09580bc89408a2ab5f29e312120dad68f58019bd" - integrity sha512-bRSkqHHHSwZYbFY3w9hgMyQRm86Wz27bRaGCbNldLfbk0zUjApmE4ajx+ZCVSLqxvcUEjMqZFJzDsder12eKsg== +"@algolia/autocomplete-shared@1.7.2": + version "1.7.2" + resolved "https://registry.yarnpkg.com/@algolia/autocomplete-shared/-/autocomplete-shared-1.7.2.tgz#daa23280e78d3b42ae9564d12470ae034db51a89" + integrity sha512-QCckjiC7xXHIUaIL3ektBtjJ0w7tTA3iqKcAE/Hjn1lZ5omp7i3Y4e09rAr9ZybqirL7AbxCLLq0Ra5DDPKeug== -"@algolia/cache-browser-local-storage@4.12.0": - version "4.12.0" - resolved "https://registry.yarnpkg.com/@algolia/cache-browser-local-storage/-/cache-browser-local-storage-4.12.0.tgz#1f873e4f28a39d25b0a589ebe8f826509458e1fb" - integrity sha512-l+G560B6N1k0rIcOjTO1yCzFUbg2Zy2HCii9s03e13jGgqduVQmk79UUCYszjsJ5GPJpUEKcVEtAIpP7tjsXVA== +"@algolia/cache-browser-local-storage@4.14.2": + version "4.14.2" + resolved "https://registry.yarnpkg.com/@algolia/cache-browser-local-storage/-/cache-browser-local-storage-4.14.2.tgz#d5b1b90130ca87c6321de876e167df9ec6524936" + integrity sha512-FRweBkK/ywO+GKYfAWbrepewQsPTIEirhi1BdykX9mxvBPtGNKccYAxvGdDCumU1jL4r3cayio4psfzKMejBlA== dependencies: - "@algolia/cache-common" "4.12.0" + "@algolia/cache-common" "4.14.2" -"@algolia/cache-common@4.12.0": - version "4.12.0" - resolved "https://registry.yarnpkg.com/@algolia/cache-common/-/cache-common-4.12.0.tgz#c1111a4d3e9ba2d52cadb4523152580db0887293" - integrity sha512-2Z8BV+NX7oN7RmmQbLqmW8lfN9aAjOexX1FJjzB0YfKC9ifpi9Jl4nSxlnbU+iLR6QhHo0IfuyQ7wcnucCGCGQ== +"@algolia/cache-common@4.14.2": + version "4.14.2" + resolved "https://registry.yarnpkg.com/@algolia/cache-common/-/cache-common-4.14.2.tgz#b946b6103c922f0c06006fb6929163ed2c67d598" + integrity sha512-SbvAlG9VqNanCErr44q6lEKD2qoK4XtFNx9Qn8FK26ePCI8I9yU7pYB+eM/cZdS9SzQCRJBbHUumVr4bsQ4uxg== -"@algolia/cache-in-memory@4.12.0": - version "4.12.0" - resolved "https://registry.yarnpkg.com/@algolia/cache-in-memory/-/cache-in-memory-4.12.0.tgz#f4bdcbf8a6419f0166cfc7ef5594af871741e29e" - integrity sha512-b6ANkZF6vGAo+sYv6g25W5a0u3o6F549gEAgtTDTVA1aHcdWwe/HG/dTJ7NsnHbuR+A831tIwnNYQjRp3/V/Jw== +"@algolia/cache-in-memory@4.14.2": + version "4.14.2" + resolved "https://registry.yarnpkg.com/@algolia/cache-in-memory/-/cache-in-memory-4.14.2.tgz#88e4a21474f9ac05331c2fa3ceb929684a395a24" + integrity sha512-HrOukWoop9XB/VFojPv1R5SVXowgI56T9pmezd/djh2JnVN/vXswhXV51RKy4nCpqxyHt/aGFSq2qkDvj6KiuQ== dependencies: - "@algolia/cache-common" "4.12.0" + "@algolia/cache-common" "4.14.2" -"@algolia/client-account@4.12.0": - version "4.12.0" - resolved "https://registry.yarnpkg.com/@algolia/client-account/-/client-account-4.12.0.tgz#b28445b47e2abf81dc76982d16ba8458f5c99521" - integrity sha512-gzXN75ZydNheNXUN3epS+aLsKnB/PHFVlGUUjXL8WHs4lJP3B5FtHvaA/NCN5DsM3aamhuY5p0ff1XIA+Lbcrw== +"@algolia/client-account@4.14.2": + version "4.14.2" + resolved "https://registry.yarnpkg.com/@algolia/client-account/-/client-account-4.14.2.tgz#b76ac1ba9ea71e8c3f77a1805b48350dc0728a16" + integrity sha512-WHtriQqGyibbb/Rx71YY43T0cXqyelEU0lB2QMBRXvD2X0iyeGl4qMxocgEIcbHyK7uqE7hKgjT8aBrHqhgc1w== dependencies: - "@algolia/client-common" "4.12.0" - "@algolia/client-search" "4.12.0" - "@algolia/transporter" "4.12.0" + "@algolia/client-common" "4.14.2" + "@algolia/client-search" "4.14.2" + "@algolia/transporter" "4.14.2" -"@algolia/client-analytics@4.12.0": - version "4.12.0" - resolved "https://registry.yarnpkg.com/@algolia/client-analytics/-/client-analytics-4.12.0.tgz#470f115517256c92a5605ae95762531c7906ec74" - integrity sha512-rO2cZCt00Opk66QBZb7IBGfCq4ZE3EiuGkXssf2Monb5urujy0r8CknK2i7bzaKtPbd2vlvhmLP4CEHQqF6SLQ== +"@algolia/client-analytics@4.14.2": + version "4.14.2" + resolved "https://registry.yarnpkg.com/@algolia/client-analytics/-/client-analytics-4.14.2.tgz#ca04dcaf9a78ee5c92c5cb5e9c74cf031eb2f1fb" + integrity sha512-yBvBv2mw+HX5a+aeR0dkvUbFZsiC4FKSnfqk9rrfX+QrlNOKEhCG0tJzjiOggRW4EcNqRmaTULIYvIzQVL2KYQ== dependencies: - "@algolia/client-common" "4.12.0" - "@algolia/client-search" "4.12.0" - "@algolia/requester-common" "4.12.0" - "@algolia/transporter" "4.12.0" + "@algolia/client-common" "4.14.2" + "@algolia/client-search" "4.14.2" + "@algolia/requester-common" "4.14.2" + "@algolia/transporter" "4.14.2" -"@algolia/client-common@4.12.0": - version "4.12.0" - resolved "https://registry.yarnpkg.com/@algolia/client-common/-/client-common-4.12.0.tgz#402395e2cffad89188d76b83615acffb3e45e658" - integrity sha512-fcrFN7FBmxiSyjeu3sF4OnPkC1l7/8oyQ8RMM8CHpVY8cad6/ay35MrfRfgfqdzdFA8LzcBYO7fykuJv0eOqxw== +"@algolia/client-common@4.14.2": + version "4.14.2" + resolved "https://registry.yarnpkg.com/@algolia/client-common/-/client-common-4.14.2.tgz#e1324e167ffa8af60f3e8bcd122110fd0bfd1300" + integrity sha512-43o4fslNLcktgtDMVaT5XwlzsDPzlqvqesRi4MjQz2x4/Sxm7zYg5LRYFol1BIhG6EwxKvSUq8HcC/KxJu3J0Q== dependencies: - "@algolia/requester-common" "4.12.0" - "@algolia/transporter" "4.12.0" + "@algolia/requester-common" "4.14.2" + "@algolia/transporter" "4.14.2" -"@algolia/client-personalization@4.12.0": - version "4.12.0" - resolved "https://registry.yarnpkg.com/@algolia/client-personalization/-/client-personalization-4.12.0.tgz#09c89c1558a91db3bfa60d17f7258ae63861352b" - integrity sha512-wCJfSQEmX6ZOuJBJGjy+sbXiW0iy7tMNAhsVMV9RRaJE4727e5WAqwFWZssD877WQ74+/nF/VyTaB1+wejo33Q== +"@algolia/client-personalization@4.14.2": + version "4.14.2" + resolved "https://registry.yarnpkg.com/@algolia/client-personalization/-/client-personalization-4.14.2.tgz#656bbb6157a3dd1a4be7de65e457fda136c404ec" + integrity sha512-ACCoLi0cL8CBZ1W/2juehSltrw2iqsQBnfiu/Rbl9W2yE6o2ZUb97+sqN/jBqYNQBS+o0ekTMKNkQjHHAcEXNw== dependencies: - "@algolia/client-common" "4.12.0" - "@algolia/requester-common" "4.12.0" - "@algolia/transporter" "4.12.0" + "@algolia/client-common" "4.14.2" + "@algolia/requester-common" "4.14.2" + "@algolia/transporter" "4.14.2" -"@algolia/client-search@4.12.0": - version "4.12.0" - resolved "https://registry.yarnpkg.com/@algolia/client-search/-/client-search-4.12.0.tgz#ac099ee9f8de85ec204d840bcac734224c7d150c" - integrity sha512-ik6dswcTQtOdZN+8aKntI9X2E6Qpqjtyda/+VANiHThY9GD2PBXuNuuC2HvlF26AbBYp5xaSE/EKxn1DIiIJ4Q== +"@algolia/client-search@4.14.2": + version "4.14.2" + resolved "https://registry.yarnpkg.com/@algolia/client-search/-/client-search-4.14.2.tgz#357bdb7e640163f0e33bad231dfcc21f67dc2e92" + integrity sha512-L5zScdOmcZ6NGiVbLKTvP02UbxZ0njd5Vq9nJAmPFtjffUSOGEp11BmD2oMJ5QvARgx2XbX4KzTTNS5ECYIMWw== dependencies: - "@algolia/client-common" "4.12.0" - "@algolia/requester-common" "4.12.0" - "@algolia/transporter" "4.12.0" + "@algolia/client-common" "4.14.2" + "@algolia/requester-common" "4.14.2" + "@algolia/transporter" "4.14.2" "@algolia/events@^4.0.1": version "4.0.1" resolved "https://registry.yarnpkg.com/@algolia/events/-/events-4.0.1.tgz#fd39e7477e7bc703d7f893b556f676c032af3950" integrity sha512-FQzvOCgoFXAbf5Y6mYozw2aj5KCJoA3m4heImceldzPSMbdyS4atVjJzXKMsfX3wnZTFYwkkt8/z8UesLHlSBQ== -"@algolia/logger-common@4.12.0": - version "4.12.0" - resolved "https://registry.yarnpkg.com/@algolia/logger-common/-/logger-common-4.12.0.tgz#0f9dbe7ace88194b395a2cb958490eb47ac91f8e" - integrity sha512-V//9rzLdJujA3iZ/tPhmKR/m2kjSZrymxOfUiF3024u2/7UyOpH92OOCrHUf023uMGYHRzyhBz5ESfL1oCdh7g== +"@algolia/logger-common@4.14.2": + version "4.14.2" + resolved "https://registry.yarnpkg.com/@algolia/logger-common/-/logger-common-4.14.2.tgz#b74b3a92431f92665519d95942c246793ec390ee" + integrity sha512-/JGlYvdV++IcMHBnVFsqEisTiOeEr6cUJtpjz8zc0A9c31JrtLm318Njc72p14Pnkw3A/5lHHh+QxpJ6WFTmsA== -"@algolia/logger-console@4.12.0": - version "4.12.0" - resolved "https://registry.yarnpkg.com/@algolia/logger-console/-/logger-console-4.12.0.tgz#a40edeb989bf0d7ff79d989171dad64cd0f01225" - integrity sha512-pHvoGv53KXRIJHLk9uxBwKirwEo12G9+uo0sJLWESThAN3v5M+ycliU1AkUXQN8+9rds2KxfULAb+vfyfBKf8A== +"@algolia/logger-console@4.14.2": + version "4.14.2" + resolved "https://registry.yarnpkg.com/@algolia/logger-console/-/logger-console-4.14.2.tgz#ec49cb47408f5811d4792598683923a800abce7b" + integrity sha512-8S2PlpdshbkwlLCSAB5f8c91xyc84VM9Ar9EdfE9UmX+NrKNYnWR1maXXVDQQoto07G1Ol/tYFnFVhUZq0xV/g== dependencies: - "@algolia/logger-common" "4.12.0" + "@algolia/logger-common" "4.14.2" -"@algolia/requester-browser-xhr@4.12.0": - version "4.12.0" - resolved "https://registry.yarnpkg.com/@algolia/requester-browser-xhr/-/requester-browser-xhr-4.12.0.tgz#64e8e4d4f0724e477421454215195400351cfe61" - integrity sha512-rGlHNMM3jIZBwSpz33CVkeXHilzuzHuFXEEW1icP/k3KW7kwBrKFJwBy42RzAJa5BYlLsTCFTS3xkPhYwTQKLg== +"@algolia/requester-browser-xhr@4.14.2": + version "4.14.2" + resolved "https://registry.yarnpkg.com/@algolia/requester-browser-xhr/-/requester-browser-xhr-4.14.2.tgz#a2cd4d9d8d90d53109cc7f3682dc6ebf20f798f2" + integrity sha512-CEh//xYz/WfxHFh7pcMjQNWgpl4wFB85lUMRyVwaDPibNzQRVcV33YS+63fShFWc2+42YEipFGH2iPzlpszmDw== dependencies: - "@algolia/requester-common" "4.12.0" + "@algolia/requester-common" "4.14.2" -"@algolia/requester-common@4.12.0": - version "4.12.0" - resolved "https://registry.yarnpkg.com/@algolia/requester-common/-/requester-common-4.12.0.tgz#b4d96f3cbd73206b6042e523d414a34cc005c2e2" - integrity sha512-qgfdc73nXqpVyOMr6CMTx3nXvud9dP6GcMGDqPct+fnxogGcJsp24cY2nMqUrAfgmTJe9Nmy7Lddv0FyHjONMg== +"@algolia/requester-common@4.14.2": + version "4.14.2" + resolved "https://registry.yarnpkg.com/@algolia/requester-common/-/requester-common-4.14.2.tgz#bc4e9e5ee16c953c0ecacbfb334a33c30c28b1a1" + integrity sha512-73YQsBOKa5fvVV3My7iZHu1sUqmjjfs9TteFWwPwDmnad7T0VTCopttcsM3OjLxZFtBnX61Xxl2T2gmG2O4ehg== -"@algolia/requester-node-http@4.12.0": - version "4.12.0" - resolved "https://registry.yarnpkg.com/@algolia/requester-node-http/-/requester-node-http-4.12.0.tgz#8d8e1b67edbaec8e8e8b8c7c606945b969667267" - integrity sha512-mOTRGf/v/dXshBoZKNhMG00ZGxoUH9QdSpuMKYnuWwIgstN24uj3DQx+Ho3c+uq0TYfq7n2v71uoJWuiW32NMQ== +"@algolia/requester-node-http@4.14.2": + version "4.14.2" + resolved "https://registry.yarnpkg.com/@algolia/requester-node-http/-/requester-node-http-4.14.2.tgz#7c1223a1785decaab1def64c83dade6bea45e115" + integrity sha512-oDbb02kd1o5GTEld4pETlPZLY0e+gOSWjWMJHWTgDXbv9rm/o2cF7japO6Vj1ENnrqWvLBmW1OzV9g6FUFhFXg== dependencies: - "@algolia/requester-common" "4.12.0" + "@algolia/requester-common" "4.14.2" -"@algolia/transporter@4.12.0": - version "4.12.0" - resolved "https://registry.yarnpkg.com/@algolia/transporter/-/transporter-4.12.0.tgz#e375e10731df95f1be3593b32e86b5c6452cc213" - integrity sha512-MOQVHZ4BcBpf3LtOY/3fqXHAcvI8MahrXDHk9QrBE/iGensQhDiZby5Dn3o2JN/zd9FMnVbdPQ8gnkiMwZiakQ== +"@algolia/transporter@4.14.2": + version "4.14.2" + resolved "https://registry.yarnpkg.com/@algolia/transporter/-/transporter-4.14.2.tgz#77c069047fb1a4359ee6a51f51829508e44a1e3d" + integrity sha512-t89dfQb2T9MFQHidjHcfhh6iGMNwvuKUvojAj+JsrHAGbuSy7yE4BylhLX6R0Q1xYRoC4Vvv+O5qIw/LdnQfsQ== dependencies: - "@algolia/cache-common" "4.12.0" - "@algolia/logger-common" "4.12.0" - "@algolia/requester-common" "4.12.0" + "@algolia/cache-common" "4.14.2" + "@algolia/logger-common" "4.14.2" + "@algolia/requester-common" "4.14.2" -"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.10.4", "@babel/code-frame@^7.16.0", "@babel/code-frame@^7.16.7", "@babel/code-frame@^7.8.3": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.16.7.tgz#44416b6bd7624b998f5b1af5d470856c40138789" - integrity sha512-iAXqUn8IIeBTNd72xsFlgaXHkMBMt6y4HJp1tIaK465CWLT/fG1aqB7ykr95gHHmlBdGbFeWWfyB4NJJ0nmeIg== +"@ampproject/remapping@^2.1.0": + version "2.2.0" + resolved "https://registry.yarnpkg.com/@ampproject/remapping/-/remapping-2.2.0.tgz#56c133824780de3174aed5ab6834f3026790154d" + integrity sha512-qRmjj8nj9qmLTQXXmaR1cck3UXSRMPrbsLJAasZpF+t3riI71BXed5ebIOYwQntykeZuhjsdweEc9BxH5Jc26w== + dependencies: + "@jridgewell/gen-mapping" "^0.1.0" + "@jridgewell/trace-mapping" "^0.3.9" + +"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.10.4", "@babel/code-frame@^7.16.0", "@babel/code-frame@^7.18.6", "@babel/code-frame@^7.8.3": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.18.6.tgz#3b25d38c89600baa2dcc219edfa88a74eb2c427a" + integrity sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q== dependencies: - "@babel/highlight" "^7.16.7" + "@babel/highlight" "^7.18.6" -"@babel/compat-data@^7.13.11", "@babel/compat-data@^7.16.4", "@babel/compat-data@^7.16.8": - version "7.16.8" - resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.16.8.tgz#31560f9f29fdf1868de8cb55049538a1b9732a60" - integrity sha512-m7OkX0IdKLKPpBlJtF561YJal5y/jyI5fNfWbPxh2D/nbzzGI4qRyrD8xO2jB24u7l+5I2a43scCG2IrfjC50Q== +"@babel/compat-data@^7.17.7", "@babel/compat-data@^7.20.0", "@babel/compat-data@^7.20.1": + version "7.20.1" + resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.20.1.tgz#f2e6ef7790d8c8dbf03d379502dcc246dcce0b30" + integrity sha512-EWZ4mE2diW3QALKvDMiXnbZpRvlj+nayZ112nK93SnhqOtpdsbVD4W+2tEoT3YNBAG9RBR0ISY758ZkOgsn6pQ== "@babel/core@7.12.9": version "7.12.9" @@ -164,118 +172,113 @@ semver "^5.4.1" source-map "^0.5.0" -"@babel/core@^7.15.5", "@babel/core@^7.16.0": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.16.7.tgz#db990f931f6d40cb9b87a0dc7d2adc749f1dcbcf" - integrity sha512-aeLaqcqThRNZYmbMqtulsetOQZ/5gbR/dWruUCJcpas4Qoyy+QeagfDsPdMrqwsPRDNxJvBlRiZxxX7THO7qtA== - dependencies: - "@babel/code-frame" "^7.16.7" - "@babel/generator" "^7.16.7" - "@babel/helper-compilation-targets" "^7.16.7" - "@babel/helper-module-transforms" "^7.16.7" - "@babel/helpers" "^7.16.7" - "@babel/parser" "^7.16.7" - "@babel/template" "^7.16.7" - "@babel/traverse" "^7.16.7" - "@babel/types" "^7.16.7" +"@babel/core@^7.18.6", "@babel/core@^7.19.6": + version "7.20.2" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.20.2.tgz#8dc9b1620a673f92d3624bd926dc49a52cf25b92" + integrity sha512-w7DbG8DtMrJcFOi4VrLm+8QM4az8Mo+PuLBKLp2zrYRCow8W/f9xiXm5sN53C8HksCyDQwCKha9JiDoIyPjT2g== + dependencies: + "@ampproject/remapping" "^2.1.0" + "@babel/code-frame" "^7.18.6" + "@babel/generator" "^7.20.2" + "@babel/helper-compilation-targets" "^7.20.0" + "@babel/helper-module-transforms" "^7.20.2" + "@babel/helpers" "^7.20.1" + "@babel/parser" "^7.20.2" + "@babel/template" "^7.18.10" + "@babel/traverse" "^7.20.1" + "@babel/types" "^7.20.2" convert-source-map "^1.7.0" debug "^4.1.0" gensync "^1.0.0-beta.2" - json5 "^2.1.2" + json5 "^2.2.1" semver "^6.3.0" - source-map "^0.5.0" -"@babel/generator@^7.12.5", "@babel/generator@^7.16.0", "@babel/generator@^7.16.7", "@babel/generator@^7.16.8": - version "7.16.8" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.16.8.tgz#359d44d966b8cd059d543250ce79596f792f2ebe" - integrity sha512-1ojZwE9+lOXzcWdWmO6TbUzDfqLD39CmEhN8+2cX9XkDo5yW1OpgfejfliysR2AWLpMamTiOiAp/mtroaymhpw== +"@babel/generator@^7.12.5", "@babel/generator@^7.18.7", "@babel/generator@^7.20.1", "@babel/generator@^7.20.2": + version "7.20.4" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.20.4.tgz#4d9f8f0c30be75fd90a0562099a26e5839602ab8" + integrity sha512-luCf7yk/cm7yab6CAW1aiFnmEfBJplb/JojV56MYEK7ziWfGmFlTfmL9Ehwfy4gFhbjBfWO1wj7/TuSbVNEEtA== dependencies: - "@babel/types" "^7.16.8" + "@babel/types" "^7.20.2" + "@jridgewell/gen-mapping" "^0.3.2" jsesc "^2.5.1" - source-map "^0.5.0" -"@babel/helper-annotate-as-pure@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.16.7.tgz#bb2339a7534a9c128e3102024c60760a3a7f3862" - integrity sha512-s6t2w/IPQVTAET1HitoowRGXooX8mCgtuP5195wD/QJPV6wYjpujCGF7JuMODVX2ZAJOf1GT6DT9MHEZvLOFSw== +"@babel/helper-annotate-as-pure@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.18.6.tgz#eaa49f6f80d5a33f9a5dd2276e6d6e451be0a6bb" + integrity sha512-duORpUiYrEpzKIop6iNbjnwKLAKnJ47csTyRACyEmWj0QdUrm5aqNJGHSSEQSUAvNW0ojX0dOmK9dZduvkfeXA== dependencies: - "@babel/types" "^7.16.7" + "@babel/types" "^7.18.6" -"@babel/helper-builder-binary-assignment-operator-visitor@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.16.7.tgz#38d138561ea207f0f69eb1626a418e4f7e6a580b" - integrity sha512-C6FdbRaxYjwVu/geKW4ZeQ0Q31AftgRcdSnZ5/jsH6BzCJbtvXvhpfkbkThYSuutZA7nCXpPR6AD9zd1dprMkA== +"@babel/helper-builder-binary-assignment-operator-visitor@^7.18.6": + version "7.18.9" + resolved "https://registry.yarnpkg.com/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.18.9.tgz#acd4edfd7a566d1d51ea975dff38fd52906981bb" + integrity sha512-yFQ0YCHoIqarl8BCRwBL8ulYUaZpz3bNsA7oFepAzee+8/+ImtADXNOmO5vJvsPff3qi+hvpkY/NYBTrBQgdNw== dependencies: - "@babel/helper-explode-assignable-expression" "^7.16.7" - "@babel/types" "^7.16.7" + "@babel/helper-explode-assignable-expression" "^7.18.6" + "@babel/types" "^7.18.9" -"@babel/helper-compilation-targets@^7.13.0", "@babel/helper-compilation-targets@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.16.7.tgz#06e66c5f299601e6c7da350049315e83209d551b" - integrity sha512-mGojBwIWcwGD6rfqgRXVlVYmPAv7eOpIemUG3dGnDdCY4Pae70ROij3XmfrH6Fa1h1aiDylpglbZyktfzyo/hA== +"@babel/helper-compilation-targets@^7.17.7", "@babel/helper-compilation-targets@^7.18.9", "@babel/helper-compilation-targets@^7.20.0": + version "7.20.0" + resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.20.0.tgz#6bf5374d424e1b3922822f1d9bdaa43b1a139d0a" + integrity sha512-0jp//vDGp9e8hZzBc6N/KwA5ZK3Wsm/pfm4CrY7vzegkVxc65SgSn6wYOnwHe9Js9HRQ1YTCKLGPzDtaS3RoLQ== dependencies: - "@babel/compat-data" "^7.16.4" - "@babel/helper-validator-option" "^7.16.7" - browserslist "^4.17.5" + "@babel/compat-data" "^7.20.0" + "@babel/helper-validator-option" "^7.18.6" + browserslist "^4.21.3" semver "^6.3.0" -"@babel/helper-create-class-features-plugin@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.16.7.tgz#9c5b34b53a01f2097daf10678d65135c1b9f84ba" - integrity sha512-kIFozAvVfK05DM4EVQYKK+zteWvY85BFdGBRQBytRyY3y+6PX0DkDOn/CZ3lEuczCfrCxEzwt0YtP/87YPTWSw== - dependencies: - "@babel/helper-annotate-as-pure" "^7.16.7" - "@babel/helper-environment-visitor" "^7.16.7" - "@babel/helper-function-name" "^7.16.7" - "@babel/helper-member-expression-to-functions" "^7.16.7" - "@babel/helper-optimise-call-expression" "^7.16.7" - "@babel/helper-replace-supers" "^7.16.7" - "@babel/helper-split-export-declaration" "^7.16.7" - -"@babel/helper-create-regexp-features-plugin@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.16.7.tgz#0cb82b9bac358eb73bfbd73985a776bfa6b14d48" - integrity sha512-fk5A6ymfp+O5+p2yCkXAu5Kyj6v0xh0RBeNcAkYUMDvvAAoxvSKXn+Jb37t/yWFiQVDFK1ELpUTD8/aLhCPu+g== - dependencies: - "@babel/helper-annotate-as-pure" "^7.16.7" - regexpu-core "^4.7.1" - -"@babel/helper-define-polyfill-provider@^0.3.0": - version "0.3.0" - resolved "https://registry.yarnpkg.com/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.3.0.tgz#c5b10cf4b324ff840140bb07e05b8564af2ae971" - integrity sha512-7hfT8lUljl/tM3h+izTX/pO3W3frz2ok6Pk+gzys8iJqDfZrZy2pXjRTZAvG2YmfHun1X4q8/UZRLatMfqc5Tg== - dependencies: - "@babel/helper-compilation-targets" "^7.13.0" - "@babel/helper-module-imports" "^7.12.13" - "@babel/helper-plugin-utils" "^7.13.0" - "@babel/traverse" "^7.13.0" +"@babel/helper-create-class-features-plugin@^7.18.6", "@babel/helper-create-class-features-plugin@^7.20.2": + version "7.20.2" + resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.20.2.tgz#3c08a5b5417c7f07b5cf3dfb6dc79cbec682e8c2" + integrity sha512-k22GoYRAHPYr9I+Gvy2ZQlAe5mGy8BqWst2wRt8cwIufWTxrsVshhIBvYNqC80N0GSFWTsqRVexOtfzlgOEDvA== + dependencies: + "@babel/helper-annotate-as-pure" "^7.18.6" + "@babel/helper-environment-visitor" "^7.18.9" + "@babel/helper-function-name" "^7.19.0" + "@babel/helper-member-expression-to-functions" "^7.18.9" + "@babel/helper-optimise-call-expression" "^7.18.6" + "@babel/helper-replace-supers" "^7.19.1" + "@babel/helper-split-export-declaration" "^7.18.6" + +"@babel/helper-create-regexp-features-plugin@^7.18.6", "@babel/helper-create-regexp-features-plugin@^7.19.0": + version "7.19.0" + resolved "https://registry.yarnpkg.com/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.19.0.tgz#7976aca61c0984202baca73d84e2337a5424a41b" + integrity sha512-htnV+mHX32DF81amCDrwIDr8nrp1PTm+3wfBN9/v8QJOLEioOCOG7qNyq0nHeFiWbT3Eb7gsPwEmV64UCQ1jzw== + dependencies: + "@babel/helper-annotate-as-pure" "^7.18.6" + regexpu-core "^5.1.0" + +"@babel/helper-define-polyfill-provider@^0.3.3": + version "0.3.3" + resolved "https://registry.yarnpkg.com/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.3.3.tgz#8612e55be5d51f0cd1f36b4a5a83924e89884b7a" + integrity sha512-z5aQKU4IzbqCC1XH0nAqfsFLMVSo22SBKUc0BxGrLkolTdPTructy0ToNnlO2zA4j9Q/7pjMZf0DSY+DSTYzww== + dependencies: + "@babel/helper-compilation-targets" "^7.17.7" + "@babel/helper-plugin-utils" "^7.16.7" debug "^4.1.1" lodash.debounce "^4.0.8" resolve "^1.14.2" semver "^6.1.2" -"@babel/helper-environment-visitor@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.16.7.tgz#ff484094a839bde9d89cd63cba017d7aae80ecd7" - integrity sha512-SLLb0AAn6PkUeAfKJCCOl9e1R53pQlGAfc4y4XuMRZfqeMYLE0dM1LMhqbGAlGQY0lfw5/ohoYWAe9V1yibRag== - dependencies: - "@babel/types" "^7.16.7" +"@babel/helper-environment-visitor@^7.18.9": + version "7.18.9" + resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.9.tgz#0c0cee9b35d2ca190478756865bb3528422f51be" + integrity sha512-3r/aACDJ3fhQ/EVgFy0hpj8oHyHpQc+LPtJoY9SzTThAsStm4Ptegq92vqKoE3vD706ZVFWITnMnxucw+S9Ipg== -"@babel/helper-explode-assignable-expression@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.16.7.tgz#12a6d8522fdd834f194e868af6354e8650242b7a" - integrity sha512-KyUenhWMC8VrxzkGP0Jizjo4/Zx+1nNZhgocs+gLzyZyB8SHidhoq9KK/8Ato4anhwsivfkBLftky7gvzbZMtQ== +"@babel/helper-explode-assignable-expression@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.18.6.tgz#41f8228ef0a6f1a036b8dfdfec7ce94f9a6bc096" + integrity sha512-eyAYAsQmB80jNfg4baAtLeWAQHfHFiR483rzFK+BhETlGZaQC9bsfrugfXDCbRHLQbIA7U5NxhhOxN7p/dWIcg== dependencies: - "@babel/types" "^7.16.7" + "@babel/types" "^7.18.6" -"@babel/helper-function-name@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.16.7.tgz#f1ec51551fb1c8956bc8dd95f38523b6cf375f8f" - integrity sha512-QfDfEnIUyyBSR3HtrtGECuZ6DAyCkYFp7GHl75vFtTnn6pjKeK0T1DB5lLkFvBea8MdaiUABx3osbgLyInoejA== +"@babel/helper-function-name@^7.18.9", "@babel/helper-function-name@^7.19.0": + version "7.19.0" + resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.19.0.tgz#941574ed5390682e872e52d3f38ce9d1bef4648c" + integrity sha512-WAwHBINyrpqywkUH0nTnNgI5ina5TFn85HKS0pbPDfxFfhyR/aNQEn4hGi1P1JyT//I0t4OgXUlofzWILRvS5w== dependencies: - "@babel/helper-get-function-arity" "^7.16.7" - "@babel/template" "^7.16.7" - "@babel/types" "^7.16.7" + "@babel/template" "^7.18.10" + "@babel/types" "^7.19.0" "@babel/helper-get-function-arity@^7.16.7": version "7.16.7" @@ -284,230 +287,237 @@ dependencies: "@babel/types" "^7.16.7" -"@babel/helper-hoist-variables@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.16.7.tgz#86bcb19a77a509c7b77d0e22323ef588fa58c246" - integrity sha512-m04d/0Op34H5v7pbZw6pSKP7weA6lsMvfiIAMeIvkY/R4xQtBSMFEigu9QTZ2qB/9l22vsxtM8a+Q8CzD255fg== +"@babel/helper-hoist-variables@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.18.6.tgz#d4d2c8fb4baeaa5c68b99cc8245c56554f926678" + integrity sha512-UlJQPkFqFULIcyW5sbzgbkxn2FKRgwWiRexcuaR8RNJRy8+LLveqPjwZV/bwrLZCN0eUHD/x8D0heK1ozuoo6Q== dependencies: - "@babel/types" "^7.16.7" + "@babel/types" "^7.18.6" -"@babel/helper-member-expression-to-functions@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.16.7.tgz#42b9ca4b2b200123c3b7e726b0ae5153924905b0" - integrity sha512-VtJ/65tYiU/6AbMTDwyoXGPKHgTsfRarivm+YbB5uAzKUyuPjgZSgAFeG87FCigc7KNHu2Pegh1XIT3lXjvz3Q== +"@babel/helper-member-expression-to-functions@^7.18.9": + version "7.18.9" + resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.18.9.tgz#1531661e8375af843ad37ac692c132841e2fd815" + integrity sha512-RxifAh2ZoVU67PyKIO4AMi1wTenGfMR/O/ae0CCRqwgBAt5v7xjdtRw7UoSbsreKrQn5t7r89eruK/9JjYHuDg== dependencies: - "@babel/types" "^7.16.7" + "@babel/types" "^7.18.9" -"@babel/helper-module-imports@^7.12.13", "@babel/helper-module-imports@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.16.7.tgz#25612a8091a999704461c8a222d0efec5d091437" - integrity sha512-LVtS6TqjJHFc+nYeITRo6VLXve70xmq7wPhWTqDJusJEgGmkAACWwMiTNrvfoQo6hEhFwAIixNkvB0jPXDL8Wg== +"@babel/helper-module-imports@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.18.6.tgz#1e3ebdbbd08aad1437b428c50204db13c5a3ca6e" + integrity sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA== dependencies: - "@babel/types" "^7.16.7" + "@babel/types" "^7.18.6" -"@babel/helper-module-transforms@^7.12.1", "@babel/helper-module-transforms@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.16.7.tgz#7665faeb721a01ca5327ddc6bba15a5cb34b6a41" - integrity sha512-gaqtLDxJEFCeQbYp9aLAefjhkKdjKcdh6DB7jniIGU3Pz52WAmP268zK0VgPz9hUNkMSYeH976K2/Y6yPadpng== - dependencies: - "@babel/helper-environment-visitor" "^7.16.7" - "@babel/helper-module-imports" "^7.16.7" - "@babel/helper-simple-access" "^7.16.7" - "@babel/helper-split-export-declaration" "^7.16.7" - "@babel/helper-validator-identifier" "^7.16.7" - "@babel/template" "^7.16.7" - "@babel/traverse" "^7.16.7" - "@babel/types" "^7.16.7" +"@babel/helper-module-transforms@^7.12.1", "@babel/helper-module-transforms@^7.18.6", "@babel/helper-module-transforms@^7.19.6", "@babel/helper-module-transforms@^7.20.2": + version "7.20.2" + resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.20.2.tgz#ac53da669501edd37e658602a21ba14c08748712" + integrity sha512-zvBKyJXRbmK07XhMuujYoJ48B5yvvmM6+wcpv6Ivj4Yg6qO7NOZOSnvZN9CRl1zz1Z4cKf8YejmCMh8clOoOeA== + dependencies: + "@babel/helper-environment-visitor" "^7.18.9" + "@babel/helper-module-imports" "^7.18.6" + "@babel/helper-simple-access" "^7.20.2" + "@babel/helper-split-export-declaration" "^7.18.6" + "@babel/helper-validator-identifier" "^7.19.1" + "@babel/template" "^7.18.10" + "@babel/traverse" "^7.20.1" + "@babel/types" "^7.20.2" -"@babel/helper-optimise-call-expression@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.16.7.tgz#a34e3560605abbd31a18546bd2aad3e6d9a174f2" - integrity sha512-EtgBhg7rd/JcnpZFXpBy0ze1YRfdm7BnBX4uKMBd3ixa3RGAE002JZB66FJyNH7g0F38U05pXmA5P8cBh7z+1w== +"@babel/helper-optimise-call-expression@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.18.6.tgz#9369aa943ee7da47edab2cb4e838acf09d290ffe" + integrity sha512-HP59oD9/fEHQkdcbgFCnbmgH5vIQTJbxh2yf+CdM89/glUNnuzr87Q8GIjGEnOktTROemO0Pe0iPAYbqZuOUiA== dependencies: - "@babel/types" "^7.16.7" + "@babel/types" "^7.18.6" "@babel/helper-plugin-utils@7.10.4": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.10.4.tgz#2f75a831269d4f677de49986dff59927533cf375" integrity sha512-O4KCvQA6lLiMU9l2eawBPMf1xPP8xPfB3iEQw150hOVTqj/rfXz0ThTb4HEzqQfs2Bmo5Ay8BzxfzVtBrr9dVg== -"@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.10.4", "@babel/helper-plugin-utils@^7.12.13", "@babel/helper-plugin-utils@^7.13.0", "@babel/helper-plugin-utils@^7.14.5", "@babel/helper-plugin-utils@^7.16.7", "@babel/helper-plugin-utils@^7.8.0", "@babel/helper-plugin-utils@^7.8.3": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.16.7.tgz#aa3a8ab4c3cceff8e65eb9e73d87dc4ff320b2f5" - integrity sha512-Qg3Nk7ZxpgMrsox6HreY1ZNKdBq7K72tDSliA6dCl5f007jR4ne8iD5UzuNnCJH2xBf2BEEVGr+/OL6Gdp7RxA== - -"@babel/helper-remap-async-to-generator@^7.16.8": - version "7.16.8" - resolved "https://registry.yarnpkg.com/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.16.8.tgz#29ffaade68a367e2ed09c90901986918d25e57e3" - integrity sha512-fm0gH7Flb8H51LqJHy3HJ3wnE1+qtYR2A99K06ahwrawLdOFsCEWjZOrYricXJHoPSudNKxrMBUPEIPxiIIvBw== - dependencies: - "@babel/helper-annotate-as-pure" "^7.16.7" - "@babel/helper-wrap-function" "^7.16.8" - "@babel/types" "^7.16.8" - -"@babel/helper-replace-supers@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.16.7.tgz#e9f5f5f32ac90429c1a4bdec0f231ef0c2838ab1" - integrity sha512-y9vsWilTNaVnVh6xiJfABzsNpgDPKev9HnAgz6Gb1p6UUwf9NepdlsV7VXGCftJM+jqD5f7JIEubcpLjZj5dBw== - dependencies: - "@babel/helper-environment-visitor" "^7.16.7" - "@babel/helper-member-expression-to-functions" "^7.16.7" - "@babel/helper-optimise-call-expression" "^7.16.7" - "@babel/traverse" "^7.16.7" - "@babel/types" "^7.16.7" - -"@babel/helper-simple-access@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.16.7.tgz#d656654b9ea08dbb9659b69d61063ccd343ff0f7" - integrity sha512-ZIzHVyoeLMvXMN/vok/a4LWRy8G2v205mNP0XOuf9XRLyX5/u9CnVulUtDgUTama3lT+bf/UqucuZjqiGuTS1g== - dependencies: - "@babel/types" "^7.16.7" - -"@babel/helper-skip-transparent-expression-wrappers@^7.16.0": - version "7.16.0" - resolved "https://registry.yarnpkg.com/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.16.0.tgz#0ee3388070147c3ae051e487eca3ebb0e2e8bb09" - integrity sha512-+il1gTy0oHwUsBQZyJvukbB4vPMdcYBrFHa0Uc4AizLxbq6BOYC51Rv4tWocX9BLBDLZ4kc6qUFpQ6HRgL+3zw== - dependencies: - "@babel/types" "^7.16.0" - -"@babel/helper-split-export-declaration@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.16.7.tgz#0b648c0c42da9d3920d85ad585f2778620b8726b" - integrity sha512-xbWoy/PFoxSWazIToT9Sif+jJTlrMcndIsaOKvTA6u7QEo7ilkRZpjew18/W3c7nm8fXdUDXh02VXTbZ0pGDNw== - dependencies: - "@babel/types" "^7.16.7" - -"@babel/helper-validator-identifier@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.16.7.tgz#e8c602438c4a8195751243da9031d1607d247cad" - integrity sha512-hsEnFemeiW4D08A5gUAZxLBTXpZ39P+a+DGDsHw1yxqyQ/jzFEnxf5uTEGp+3bzAbNOxU1paTgYS4ECU/IgfDw== - -"@babel/helper-validator-option@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.16.7.tgz#b203ce62ce5fe153899b617c08957de860de4d23" - integrity sha512-TRtenOuRUVo9oIQGPC5G9DgK4743cdxvtOw0weQNpZXaS16SCBi5MNjZF8vba3ETURjZpTbVn7Vvcf2eAwFozQ== - -"@babel/helper-wrap-function@^7.16.8": - version "7.16.8" - resolved "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.16.8.tgz#58afda087c4cd235de92f7ceedebca2c41274200" - integrity sha512-8RpyRVIAW1RcDDGTA+GpPAwV22wXCfKOoM9bet6TLkGIFTkRQSkH1nMQ5Yet4MpoXe1ZwHPVtNasc2w0uZMqnw== - dependencies: - "@babel/helper-function-name" "^7.16.7" - "@babel/template" "^7.16.7" - "@babel/traverse" "^7.16.8" - "@babel/types" "^7.16.8" - -"@babel/helpers@^7.12.5", "@babel/helpers@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.16.7.tgz#7e3504d708d50344112767c3542fc5e357fffefc" - integrity sha512-9ZDoqtfY7AuEOt3cxchfii6C7GDyyMBffktR5B2jvWv8u2+efwvpnVKXMWzNehqy68tKgAfSwfdw/lWpthS2bw== - dependencies: - "@babel/template" "^7.16.7" - "@babel/traverse" "^7.16.7" - "@babel/types" "^7.16.7" - -"@babel/highlight@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.16.7.tgz#81a01d7d675046f0d96f82450d9d9578bdfd6b0b" - integrity sha512-aKpPMfLvGO3Q97V0qhw/V2SWNWlwfJknuwAunU7wZLSfrM4xTBvg7E5opUVi1kJTBKihE38CPg4nBiqX83PWYw== - dependencies: - "@babel/helper-validator-identifier" "^7.16.7" +"@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.10.4", "@babel/helper-plugin-utils@^7.12.13", "@babel/helper-plugin-utils@^7.14.5", "@babel/helper-plugin-utils@^7.16.7", "@babel/helper-plugin-utils@^7.18.6", "@babel/helper-plugin-utils@^7.18.9", "@babel/helper-plugin-utils@^7.19.0", "@babel/helper-plugin-utils@^7.20.2", "@babel/helper-plugin-utils@^7.8.0", "@babel/helper-plugin-utils@^7.8.3": + version "7.20.2" + resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.20.2.tgz#d1b9000752b18d0877cff85a5c376ce5c3121629" + integrity sha512-8RvlJG2mj4huQ4pZ+rU9lqKi9ZKiRmuvGuM2HlWmkmgOhbs6zEAw6IEiJ5cQqGbDzGZOhwuOQNtZMi/ENLjZoQ== + +"@babel/helper-remap-async-to-generator@^7.18.6", "@babel/helper-remap-async-to-generator@^7.18.9": + version "7.18.9" + resolved "https://registry.yarnpkg.com/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.18.9.tgz#997458a0e3357080e54e1d79ec347f8a8cd28519" + integrity sha512-dI7q50YKd8BAv3VEfgg7PS7yD3Rtbi2J1XMXaalXO0W0164hYLnh8zpjRS0mte9MfVp/tltvr/cfdXPvJr1opA== + dependencies: + "@babel/helper-annotate-as-pure" "^7.18.6" + "@babel/helper-environment-visitor" "^7.18.9" + "@babel/helper-wrap-function" "^7.18.9" + "@babel/types" "^7.18.9" + +"@babel/helper-replace-supers@^7.18.6", "@babel/helper-replace-supers@^7.19.1": + version "7.19.1" + resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.19.1.tgz#e1592a9b4b368aa6bdb8784a711e0bcbf0612b78" + integrity sha512-T7ahH7wV0Hfs46SFh5Jz3s0B6+o8g3c+7TMxu7xKfmHikg7EAZ3I2Qk9LFhjxXq8sL7UkP5JflezNwoZa8WvWw== + dependencies: + "@babel/helper-environment-visitor" "^7.18.9" + "@babel/helper-member-expression-to-functions" "^7.18.9" + "@babel/helper-optimise-call-expression" "^7.18.6" + "@babel/traverse" "^7.19.1" + "@babel/types" "^7.19.0" + +"@babel/helper-simple-access@^7.19.4", "@babel/helper-simple-access@^7.20.2": + version "7.20.2" + resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.20.2.tgz#0ab452687fe0c2cfb1e2b9e0015de07fc2d62dd9" + integrity sha512-+0woI/WPq59IrqDYbVGfshjT5Dmk/nnbdpcF8SnMhhXObpTq2KNBdLFRFrkVdbDOyUmHBCxzm5FHV1rACIkIbA== + dependencies: + "@babel/types" "^7.20.2" + +"@babel/helper-skip-transparent-expression-wrappers@^7.18.9": + version "7.20.0" + resolved "https://registry.yarnpkg.com/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.20.0.tgz#fbe4c52f60518cab8140d77101f0e63a8a230684" + integrity sha512-5y1JYeNKfvnT8sZcK9DVRtpTbGiomYIHviSP3OQWmDPU3DeH4a1ZlT/N2lyQ5P8egjcRaT/Y9aNqUxK0WsnIIg== + dependencies: + "@babel/types" "^7.20.0" + +"@babel/helper-split-export-declaration@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.18.6.tgz#7367949bc75b20c6d5a5d4a97bba2824ae8ef075" + integrity sha512-bde1etTx6ZyTmobl9LLMMQsaizFVZrquTEHOqKeQESMKo4PlObf+8+JA25ZsIpZhT/WEd39+vOdLXAFG/nELpA== + dependencies: + "@babel/types" "^7.18.6" + +"@babel/helper-string-parser@^7.19.4": + version "7.19.4" + resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.19.4.tgz#38d3acb654b4701a9b77fb0615a96f775c3a9e63" + integrity sha512-nHtDoQcuqFmwYNYPz3Rah5ph2p8PFeFCsZk9A/48dPc/rGocJ5J3hAAZ7pb76VWX3fZKu+uEr/FhH5jLx7umrw== + +"@babel/helper-validator-identifier@^7.18.6", "@babel/helper-validator-identifier@^7.19.1": + version "7.19.1" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.19.1.tgz#7eea834cf32901ffdc1a7ee555e2f9c27e249ca2" + integrity sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w== + +"@babel/helper-validator-option@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.18.6.tgz#bf0d2b5a509b1f336099e4ff36e1a63aa5db4db8" + integrity sha512-XO7gESt5ouv/LRJdrVjkShckw6STTaB7l9BrpBaAHDeF5YZT+01PCwmR0SJHnkW6i8OwW/EVWRShfi4j2x+KQw== + +"@babel/helper-wrap-function@^7.18.9": + version "7.19.0" + resolved "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.19.0.tgz#89f18335cff1152373222f76a4b37799636ae8b1" + integrity sha512-txX8aN8CZyYGTwcLhlk87KRqncAzhh5TpQamZUa0/u3an36NtDpUP6bQgBCBcLeBs09R/OwQu3OjK0k/HwfNDg== + dependencies: + "@babel/helper-function-name" "^7.19.0" + "@babel/template" "^7.18.10" + "@babel/traverse" "^7.19.0" + "@babel/types" "^7.19.0" + +"@babel/helpers@^7.12.5", "@babel/helpers@^7.20.1": + version "7.20.1" + resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.20.1.tgz#2ab7a0fcb0a03b5bf76629196ed63c2d7311f4c9" + integrity sha512-J77mUVaDTUJFZ5BpP6mMn6OIl3rEWymk2ZxDBQJUG3P+PbmyMcF3bYWvz0ma69Af1oobDqT/iAsvzhB58xhQUg== + dependencies: + "@babel/template" "^7.18.10" + "@babel/traverse" "^7.20.1" + "@babel/types" "^7.20.0" + +"@babel/highlight@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.18.6.tgz#81158601e93e2563795adcbfbdf5d64be3f2ecdf" + integrity sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g== + dependencies: + "@babel/helper-validator-identifier" "^7.18.6" chalk "^2.0.0" js-tokens "^4.0.0" -"@babel/parser@^7.12.7", "@babel/parser@^7.16.4", "@babel/parser@^7.16.7", "@babel/parser@^7.16.8": - version "7.16.8" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.16.8.tgz#61c243a3875f7d0b0962b0543a33ece6ff2f1f17" - integrity sha512-i7jDUfrVBWc+7OKcBzEe5n7fbv3i2fWtxKzzCvOjnzSxMfWMigAhtfJ7qzZNGFNMsCCd67+uz553dYKWXPvCKw== +"@babel/parser@^7.12.7", "@babel/parser@^7.18.10", "@babel/parser@^7.18.8", "@babel/parser@^7.20.1", "@babel/parser@^7.20.2": + version "7.20.3" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.20.3.tgz#5358cf62e380cf69efcb87a7bb922ff88bfac6e2" + integrity sha512-OP/s5a94frIPXwjzEcv5S/tpQfc6XhxYUnmWpgdqMWGgYCuErA3SzozaRAMQgSZWKeTJxht9aWAkUY+0UzvOFg== -"@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.16.7.tgz#4eda6d6c2a0aa79c70fa7b6da67763dfe2141050" - integrity sha512-anv/DObl7waiGEnC24O9zqL0pSuI9hljihqiDuFHC8d7/bjr/4RLGPWuc8rYOff/QPzbEPSkzG8wGG9aDuhHRg== +"@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.18.6.tgz#da5b8f9a580acdfbe53494dba45ea389fb09a4d2" + integrity sha512-Dgxsyg54Fx1d4Nge8UnvTrED63vrwOdPmyvPzlNN/boaliRP54pm3pGzZD1SJUwrBA+Cs/xdG8kXX6Mn/RfISQ== dependencies: - "@babel/helper-plugin-utils" "^7.16.7" + "@babel/helper-plugin-utils" "^7.18.6" -"@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.16.7.tgz#cc001234dfc139ac45f6bcf801866198c8c72ff9" - integrity sha512-di8vUHRdf+4aJ7ltXhaDbPoszdkh59AQtJM5soLsuHpQJdFQZOA4uGj0V2u/CZ8bJ/u8ULDL5yq6FO/bCXnKHw== +"@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@^7.18.9": + version "7.18.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.18.9.tgz#a11af19aa373d68d561f08e0a57242350ed0ec50" + integrity sha512-AHrP9jadvH7qlOj6PINbgSuphjQUAK7AOT7DPjBo9EHoLhQTnnK5u45e1Hd4DbSQEO9nqPWtQ89r+XEOWFScKg== dependencies: - "@babel/helper-plugin-utils" "^7.16.7" - "@babel/helper-skip-transparent-expression-wrappers" "^7.16.0" - "@babel/plugin-proposal-optional-chaining" "^7.16.7" + "@babel/helper-plugin-utils" "^7.18.9" + "@babel/helper-skip-transparent-expression-wrappers" "^7.18.9" + "@babel/plugin-proposal-optional-chaining" "^7.18.9" -"@babel/plugin-proposal-async-generator-functions@^7.16.8": - version "7.16.8" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.16.8.tgz#3bdd1ebbe620804ea9416706cd67d60787504bc8" - integrity sha512-71YHIvMuiuqWJQkebWJtdhQTfd4Q4mF76q2IX37uZPkG9+olBxsX+rH1vkhFto4UeJZ9dPY2s+mDvhDm1u2BGQ== +"@babel/plugin-proposal-async-generator-functions@^7.20.1": + version "7.20.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.20.1.tgz#352f02baa5d69f4e7529bdac39aaa02d41146af9" + integrity sha512-Gh5rchzSwE4kC+o/6T8waD0WHEQIsDmjltY8WnWRXHUdH8axZhuH86Ov9M72YhJfDrZseQwuuWaaIT/TmePp3g== dependencies: - "@babel/helper-plugin-utils" "^7.16.7" - "@babel/helper-remap-async-to-generator" "^7.16.8" + "@babel/helper-environment-visitor" "^7.18.9" + "@babel/helper-plugin-utils" "^7.19.0" + "@babel/helper-remap-async-to-generator" "^7.18.9" "@babel/plugin-syntax-async-generators" "^7.8.4" -"@babel/plugin-proposal-class-properties@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.16.7.tgz#925cad7b3b1a2fcea7e59ecc8eb5954f961f91b0" - integrity sha512-IobU0Xme31ewjYOShSIqd/ZGM/r/cuOz2z0MDbNrhF5FW+ZVgi0f2lyeoj9KFPDOAqsYxmLWZte1WOwlvY9aww== +"@babel/plugin-proposal-class-properties@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.18.6.tgz#b110f59741895f7ec21a6fff696ec46265c446a3" + integrity sha512-cumfXOF0+nzZrrN8Rf0t7M+tF6sZc7vhQwYQck9q1/5w2OExlD+b4v4RpMJFaV1Z7WcDRgO6FqvxqxGlwo+RHQ== dependencies: - "@babel/helper-create-class-features-plugin" "^7.16.7" - "@babel/helper-plugin-utils" "^7.16.7" + "@babel/helper-create-class-features-plugin" "^7.18.6" + "@babel/helper-plugin-utils" "^7.18.6" -"@babel/plugin-proposal-class-static-block@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-class-static-block/-/plugin-proposal-class-static-block-7.16.7.tgz#712357570b612106ef5426d13dc433ce0f200c2a" - integrity sha512-dgqJJrcZoG/4CkMopzhPJjGxsIe9A8RlkQLnL/Vhhx8AA9ZuaRwGSlscSh42hazc7WSrya/IK7mTeoF0DP9tEw== +"@babel/plugin-proposal-class-static-block@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-class-static-block/-/plugin-proposal-class-static-block-7.18.6.tgz#8aa81d403ab72d3962fc06c26e222dacfc9b9020" + integrity sha512-+I3oIiNxrCpup3Gi8n5IGMwj0gOCAjcJUSQEcotNnCCPMEnixawOQ+KeJPlgfjzx+FKQ1QSyZOWe7wmoJp7vhw== dependencies: - "@babel/helper-create-class-features-plugin" "^7.16.7" - "@babel/helper-plugin-utils" "^7.16.7" + "@babel/helper-create-class-features-plugin" "^7.18.6" + "@babel/helper-plugin-utils" "^7.18.6" "@babel/plugin-syntax-class-static-block" "^7.14.5" -"@babel/plugin-proposal-dynamic-import@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.16.7.tgz#c19c897eaa46b27634a00fee9fb7d829158704b2" - integrity sha512-I8SW9Ho3/8DRSdmDdH3gORdyUuYnk1m4cMxUAdu5oy4n3OfN8flDEH+d60iG7dUfi0KkYwSvoalHzzdRzpWHTg== +"@babel/plugin-proposal-dynamic-import@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.18.6.tgz#72bcf8d408799f547d759298c3c27c7e7faa4d94" + integrity sha512-1auuwmK+Rz13SJj36R+jqFPMJWyKEDd7lLSdOj4oJK0UTgGueSAtkrCvz9ewmgyU/P941Rv2fQwZJN8s6QruXw== dependencies: - "@babel/helper-plugin-utils" "^7.16.7" + "@babel/helper-plugin-utils" "^7.18.6" "@babel/plugin-syntax-dynamic-import" "^7.8.3" -"@babel/plugin-proposal-export-namespace-from@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.16.7.tgz#09de09df18445a5786a305681423ae63507a6163" - integrity sha512-ZxdtqDXLRGBL64ocZcs7ovt71L3jhC1RGSyR996svrCi3PYqHNkb3SwPJCs8RIzD86s+WPpt2S73+EHCGO+NUA== +"@babel/plugin-proposal-export-namespace-from@^7.18.9": + version "7.18.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.18.9.tgz#5f7313ab348cdb19d590145f9247540e94761203" + integrity sha512-k1NtHyOMvlDDFeb9G5PhUXuGj8m/wiwojgQVEhJ/fsVsMCpLyOP4h0uGEjYJKrRI+EVPlb5Jk+Gt9P97lOGwtA== dependencies: - "@babel/helper-plugin-utils" "^7.16.7" + "@babel/helper-plugin-utils" "^7.18.9" "@babel/plugin-syntax-export-namespace-from" "^7.8.3" -"@babel/plugin-proposal-json-strings@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.16.7.tgz#9732cb1d17d9a2626a08c5be25186c195b6fa6e8" - integrity sha512-lNZ3EEggsGY78JavgbHsK9u5P3pQaW7k4axlgFLYkMd7UBsiNahCITShLjNQschPyjtO6dADrL24757IdhBrsQ== +"@babel/plugin-proposal-json-strings@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.18.6.tgz#7e8788c1811c393aff762817e7dbf1ebd0c05f0b" + integrity sha512-lr1peyn9kOdbYc0xr0OdHTZ5FMqS6Di+H0Fz2I/JwMzGmzJETNeOFq2pBySw6X/KFL5EWDjlJuMsUGRFb8fQgQ== dependencies: - "@babel/helper-plugin-utils" "^7.16.7" + "@babel/helper-plugin-utils" "^7.18.6" "@babel/plugin-syntax-json-strings" "^7.8.3" -"@babel/plugin-proposal-logical-assignment-operators@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.16.7.tgz#be23c0ba74deec1922e639832904be0bea73cdea" - integrity sha512-K3XzyZJGQCr00+EtYtrDjmwX7o7PLK6U9bi1nCwkQioRFVUv6dJoxbQjtWVtP+bCPy82bONBKG8NPyQ4+i6yjg== +"@babel/plugin-proposal-logical-assignment-operators@^7.18.9": + version "7.18.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.18.9.tgz#8148cbb350483bf6220af06fa6db3690e14b2e23" + integrity sha512-128YbMpjCrP35IOExw2Fq+x55LMP42DzhOhX2aNNIdI9avSWl2PI0yuBWarr3RYpZBSPtabfadkH2yeRiMD61Q== dependencies: - "@babel/helper-plugin-utils" "^7.16.7" + "@babel/helper-plugin-utils" "^7.18.9" "@babel/plugin-syntax-logical-assignment-operators" "^7.10.4" -"@babel/plugin-proposal-nullish-coalescing-operator@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.16.7.tgz#141fc20b6857e59459d430c850a0011e36561d99" - integrity sha512-aUOrYU3EVtjf62jQrCj63pYZ7k6vns2h/DQvHPWGmsJRYzWXZ6/AsfgpiRy6XiuIDADhJzP2Q9MwSMKauBQ+UQ== +"@babel/plugin-proposal-nullish-coalescing-operator@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.18.6.tgz#fdd940a99a740e577d6c753ab6fbb43fdb9467e1" + integrity sha512-wQxQzxYeJqHcfppzBDnm1yAY0jSRkUXR2z8RePZYrKwMKgMlE8+Z6LUno+bd6LvbGh8Gltvy74+9pIYkr+XkKA== dependencies: - "@babel/helper-plugin-utils" "^7.16.7" + "@babel/helper-plugin-utils" "^7.18.6" "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.3" -"@babel/plugin-proposal-numeric-separator@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.16.7.tgz#d6b69f4af63fb38b6ca2558442a7fb191236eba9" - integrity sha512-vQgPMknOIgiuVqbokToyXbkY/OmmjAzr/0lhSIbG/KmnzXPGwW/AdhdKpi+O4X/VkWiWjnkKOBiqJrTaC98VKw== +"@babel/plugin-proposal-numeric-separator@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.18.6.tgz#899b14fbafe87f053d2c5ff05b36029c62e13c75" + integrity sha512-ozlZFogPqoLm8WBr5Z8UckIoE4YQ5KESVcNudyXOR8uqIkliTEgJ3RoketfG6pmzLdeZF0H/wjE9/cCEitBl7Q== dependencies: - "@babel/helper-plugin-utils" "^7.16.7" + "@babel/helper-plugin-utils" "^7.18.6" "@babel/plugin-syntax-numeric-separator" "^7.10.4" "@babel/plugin-proposal-object-rest-spread@7.12.1": @@ -519,59 +529,59 @@ "@babel/plugin-syntax-object-rest-spread" "^7.8.0" "@babel/plugin-transform-parameters" "^7.12.1" -"@babel/plugin-proposal-object-rest-spread@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.16.7.tgz#94593ef1ddf37021a25bdcb5754c4a8d534b01d8" - integrity sha512-3O0Y4+dw94HA86qSg9IHfyPktgR7q3gpNVAeiKQd+8jBKFaU5NQS1Yatgo4wY+UFNuLjvxcSmzcsHqrhgTyBUA== +"@babel/plugin-proposal-object-rest-spread@^7.20.2": + version "7.20.2" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.20.2.tgz#a556f59d555f06961df1e572bb5eca864c84022d" + integrity sha512-Ks6uej9WFK+fvIMesSqbAto5dD8Dz4VuuFvGJFKgIGSkJuRGcrwGECPA1fDgQK3/DbExBJpEkTeYeB8geIFCSQ== dependencies: - "@babel/compat-data" "^7.16.4" - "@babel/helper-compilation-targets" "^7.16.7" - "@babel/helper-plugin-utils" "^7.16.7" + "@babel/compat-data" "^7.20.1" + "@babel/helper-compilation-targets" "^7.20.0" + "@babel/helper-plugin-utils" "^7.20.2" "@babel/plugin-syntax-object-rest-spread" "^7.8.3" - "@babel/plugin-transform-parameters" "^7.16.7" + "@babel/plugin-transform-parameters" "^7.20.1" -"@babel/plugin-proposal-optional-catch-binding@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.16.7.tgz#c623a430674ffc4ab732fd0a0ae7722b67cb74cf" - integrity sha512-eMOH/L4OvWSZAE1VkHbr1vckLG1WUcHGJSLqqQwl2GaUqG6QjddvrOaTUMNYiv77H5IKPMZ9U9P7EaHwvAShfA== +"@babel/plugin-proposal-optional-catch-binding@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.18.6.tgz#f9400d0e6a3ea93ba9ef70b09e72dd6da638a2cb" + integrity sha512-Q40HEhs9DJQyaZfUjjn6vE8Cv4GmMHCYuMGIWUnlxH6400VGxOuwWsPt4FxXxJkC/5eOzgn0z21M9gMT4MOhbw== dependencies: - "@babel/helper-plugin-utils" "^7.16.7" + "@babel/helper-plugin-utils" "^7.18.6" "@babel/plugin-syntax-optional-catch-binding" "^7.8.3" -"@babel/plugin-proposal-optional-chaining@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.16.7.tgz#7cd629564724816c0e8a969535551f943c64c39a" - integrity sha512-eC3xy+ZrUcBtP7x+sq62Q/HYd674pPTb/77XZMb5wbDPGWIdUbSr4Agr052+zaUPSb+gGRnjxXfKFvx5iMJ+DA== +"@babel/plugin-proposal-optional-chaining@^7.18.9": + version "7.18.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.18.9.tgz#e8e8fe0723f2563960e4bf5e9690933691915993" + integrity sha512-v5nwt4IqBXihxGsW2QmCWMDS3B3bzGIk/EQVZz2ei7f3NJl8NzAJVvUmpDW5q1CRNY+Beb/k58UAH1Km1N411w== dependencies: - "@babel/helper-plugin-utils" "^7.16.7" - "@babel/helper-skip-transparent-expression-wrappers" "^7.16.0" + "@babel/helper-plugin-utils" "^7.18.9" + "@babel/helper-skip-transparent-expression-wrappers" "^7.18.9" "@babel/plugin-syntax-optional-chaining" "^7.8.3" -"@babel/plugin-proposal-private-methods@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.16.7.tgz#e418e3aa6f86edd6d327ce84eff188e479f571e0" - integrity sha512-7twV3pzhrRxSwHeIvFE6coPgvo+exNDOiGUMg39o2LiLo1Y+4aKpfkcLGcg1UHonzorCt7SNXnoMyCnnIOA8Sw== +"@babel/plugin-proposal-private-methods@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.18.6.tgz#5209de7d213457548a98436fa2882f52f4be6bea" + integrity sha512-nutsvktDItsNn4rpGItSNV2sz1XwS+nfU0Rg8aCx3W3NOKVzdMjJRu0O5OkgDp3ZGICSTbgRpxZoWsxoKRvbeA== dependencies: - "@babel/helper-create-class-features-plugin" "^7.16.7" - "@babel/helper-plugin-utils" "^7.16.7" + "@babel/helper-create-class-features-plugin" "^7.18.6" + "@babel/helper-plugin-utils" "^7.18.6" -"@babel/plugin-proposal-private-property-in-object@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.16.7.tgz#b0b8cef543c2c3d57e59e2c611994861d46a3fce" - integrity sha512-rMQkjcOFbm+ufe3bTZLyOfsOUOxyvLXZJCTARhJr+8UMSoZmqTe1K1BgkFcrW37rAchWg57yI69ORxiWvUINuQ== +"@babel/plugin-proposal-private-property-in-object@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.18.6.tgz#a64137b232f0aca3733a67eb1a144c192389c503" + integrity sha512-9Rysx7FOctvT5ouj5JODjAFAkgGoudQuLPamZb0v1TGLpapdNaftzifU8NTWQm0IRjqoYypdrSmyWgkocDQ8Dw== dependencies: - "@babel/helper-annotate-as-pure" "^7.16.7" - "@babel/helper-create-class-features-plugin" "^7.16.7" - "@babel/helper-plugin-utils" "^7.16.7" + "@babel/helper-annotate-as-pure" "^7.18.6" + "@babel/helper-create-class-features-plugin" "^7.18.6" + "@babel/helper-plugin-utils" "^7.18.6" "@babel/plugin-syntax-private-property-in-object" "^7.14.5" -"@babel/plugin-proposal-unicode-property-regex@^7.16.7", "@babel/plugin-proposal-unicode-property-regex@^7.4.4": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.16.7.tgz#635d18eb10c6214210ffc5ff4932552de08188a2" - integrity sha512-QRK0YI/40VLhNVGIjRNAAQkEHws0cswSdFFjpFyt943YmJIU1da9uW63Iu6NFV6CxTZW5eTDCrwZUstBWgp/Rg== +"@babel/plugin-proposal-unicode-property-regex@^7.18.6", "@babel/plugin-proposal-unicode-property-regex@^7.4.4": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.18.6.tgz#af613d2cd5e643643b65cded64207b15c85cb78e" + integrity sha512-2BShG/d5yoZyXZfVePH91urL5wTG6ASZU9M4o03lKK8u8UW1y08OMttBSOADTcJrnPMpvDXRG3G8fyLh4ovs8w== dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.16.7" - "@babel/helper-plugin-utils" "^7.16.7" + "@babel/helper-create-regexp-features-plugin" "^7.18.6" + "@babel/helper-plugin-utils" "^7.18.6" "@babel/plugin-syntax-async-generators@^7.8.4": version "7.8.4" @@ -608,6 +618,13 @@ dependencies: "@babel/helper-plugin-utils" "^7.8.3" +"@babel/plugin-syntax-import-assertions@^7.20.0": + version "7.20.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.20.0.tgz#bb50e0d4bea0957235390641209394e87bdb9cc4" + integrity sha512-IUh1vakzNoWalR8ch/areW7qFopR2AEw03JlG7BbrDqmQ4X3q9uuipQwSGrUn7oGiemKjtSLDhNtQHzMHr1JdQ== + dependencies: + "@babel/helper-plugin-utils" "^7.19.0" + "@babel/plugin-syntax-json-strings@^7.8.3": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz#01ca21b668cd8218c9e640cb6dd88c5412b2c96a" @@ -622,12 +639,12 @@ dependencies: "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-syntax-jsx@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.16.7.tgz#50b6571d13f764266a113d77c82b4a6508bbe665" - integrity sha512-Esxmk7YjA8QysKeT3VhTXvF6y77f/a91SIs4pWb4H2eWGQkCKFgQaG6hdoEVZtGsrAcb2K5BW66XsOErD4WU3Q== +"@babel/plugin-syntax-jsx@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.18.6.tgz#a8feef63b010150abd97f1649ec296e849943ca0" + integrity sha512-6mmljtAedFGTWu2p/8WIORGwy+61PLgOMPOdazc7YoJ9ZCWUyFy3A6CpPkRKLKD1ToAesxX8KGEViAiLo9N+7Q== dependencies: - "@babel/helper-plugin-utils" "^7.16.7" + "@babel/helper-plugin-utils" "^7.18.6" "@babel/plugin-syntax-logical-assignment-operators@^7.10.4": version "7.10.4" @@ -685,355 +702,356 @@ dependencies: "@babel/helper-plugin-utils" "^7.14.5" -"@babel/plugin-syntax-typescript@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.16.7.tgz#39c9b55ee153151990fb038651d58d3fd03f98f8" - integrity sha512-YhUIJHHGkqPgEcMYkPCKTyGUdoGKWtopIycQyjJH8OjvRgOYsXsaKehLVPScKJWAULPxMa4N1vCe6szREFlZ7A== +"@babel/plugin-syntax-typescript@^7.20.0": + version "7.20.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.20.0.tgz#4e9a0cfc769c85689b77a2e642d24e9f697fc8c7" + integrity sha512-rd9TkG+u1CExzS4SM1BlMEhMXwFLKVjOAFFCDx9PbX5ycJWDoWMcwdJH9RhkPu1dOgn5TrxLot/Gx6lWFuAUNQ== dependencies: - "@babel/helper-plugin-utils" "^7.16.7" + "@babel/helper-plugin-utils" "^7.19.0" -"@babel/plugin-transform-arrow-functions@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.16.7.tgz#44125e653d94b98db76369de9c396dc14bef4154" - integrity sha512-9ffkFFMbvzTvv+7dTp/66xvZAWASuPD5Tl9LK3Z9vhOmANo6j94rik+5YMBt4CwHVMWLWpMsriIc2zsa3WW3xQ== +"@babel/plugin-transform-arrow-functions@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.18.6.tgz#19063fcf8771ec7b31d742339dac62433d0611fe" + integrity sha512-9S9X9RUefzrsHZmKMbDXxweEH+YlE8JJEuat9FdvW9Qh1cw7W64jELCtWNkPBPX5En45uy28KGvA/AySqUh8CQ== dependencies: - "@babel/helper-plugin-utils" "^7.16.7" + "@babel/helper-plugin-utils" "^7.18.6" -"@babel/plugin-transform-async-to-generator@^7.16.8": - version "7.16.8" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.16.8.tgz#b83dff4b970cf41f1b819f8b49cc0cfbaa53a808" - integrity sha512-MtmUmTJQHCnyJVrScNzNlofQJ3dLFuobYn3mwOTKHnSCMtbNsqvF71GQmJfFjdrXSsAA7iysFmYWw4bXZ20hOg== +"@babel/plugin-transform-async-to-generator@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.18.6.tgz#ccda3d1ab9d5ced5265fdb13f1882d5476c71615" + integrity sha512-ARE5wZLKnTgPW7/1ftQmSi1CmkqqHo2DNmtztFhvgtOWSDfq0Cq9/9L+KnZNYSNrydBekhW3rwShduf59RoXag== dependencies: - "@babel/helper-module-imports" "^7.16.7" - "@babel/helper-plugin-utils" "^7.16.7" - "@babel/helper-remap-async-to-generator" "^7.16.8" + "@babel/helper-module-imports" "^7.18.6" + "@babel/helper-plugin-utils" "^7.18.6" + "@babel/helper-remap-async-to-generator" "^7.18.6" -"@babel/plugin-transform-block-scoped-functions@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.16.7.tgz#4d0d57d9632ef6062cdf354bb717102ee042a620" - integrity sha512-JUuzlzmF40Z9cXyytcbZEZKckgrQzChbQJw/5PuEHYeqzCsvebDx0K0jWnIIVcmmDOAVctCgnYs0pMcrYj2zJg== +"@babel/plugin-transform-block-scoped-functions@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.18.6.tgz#9187bf4ba302635b9d70d986ad70f038726216a8" + integrity sha512-ExUcOqpPWnliRcPqves5HJcJOvHvIIWfuS4sroBUenPuMdmW+SMHDakmtS7qOo13sVppmUijqeTv7qqGsvURpQ== dependencies: - "@babel/helper-plugin-utils" "^7.16.7" + "@babel/helper-plugin-utils" "^7.18.6" -"@babel/plugin-transform-block-scoping@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.16.7.tgz#f50664ab99ddeaee5bc681b8f3a6ea9d72ab4f87" - integrity sha512-ObZev2nxVAYA4bhyusELdo9hb3H+A56bxH3FZMbEImZFiEDYVHXQSJ1hQKFlDnlt8G9bBrCZ5ZpURZUrV4G5qQ== +"@babel/plugin-transform-block-scoping@^7.20.2": + version "7.20.2" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.20.2.tgz#f59b1767e6385c663fd0bce655db6ca9c8b236ed" + integrity sha512-y5V15+04ry69OV2wULmwhEA6jwSWXO1TwAtIwiPXcvHcoOQUqpyMVd2bDsQJMW8AurjulIyUV8kDqtjSwHy1uQ== dependencies: - "@babel/helper-plugin-utils" "^7.16.7" + "@babel/helper-plugin-utils" "^7.20.2" -"@babel/plugin-transform-classes@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.16.7.tgz#8f4b9562850cd973de3b498f1218796eb181ce00" - integrity sha512-WY7og38SFAGYRe64BrjKf8OrE6ulEHtr5jEYaZMwox9KebgqPi67Zqz8K53EKk1fFEJgm96r32rkKZ3qA2nCWQ== +"@babel/plugin-transform-classes@^7.20.2": + version "7.20.2" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.20.2.tgz#c0033cf1916ccf78202d04be4281d161f6709bb2" + integrity sha512-9rbPp0lCVVoagvtEyQKSo5L8oo0nQS/iif+lwlAz29MccX2642vWDlSZK+2T2buxbopotId2ld7zZAzRfz9j1g== dependencies: - "@babel/helper-annotate-as-pure" "^7.16.7" - "@babel/helper-environment-visitor" "^7.16.7" - "@babel/helper-function-name" "^7.16.7" - "@babel/helper-optimise-call-expression" "^7.16.7" - "@babel/helper-plugin-utils" "^7.16.7" - "@babel/helper-replace-supers" "^7.16.7" - "@babel/helper-split-export-declaration" "^7.16.7" + "@babel/helper-annotate-as-pure" "^7.18.6" + "@babel/helper-compilation-targets" "^7.20.0" + "@babel/helper-environment-visitor" "^7.18.9" + "@babel/helper-function-name" "^7.19.0" + "@babel/helper-optimise-call-expression" "^7.18.6" + "@babel/helper-plugin-utils" "^7.20.2" + "@babel/helper-replace-supers" "^7.19.1" + "@babel/helper-split-export-declaration" "^7.18.6" globals "^11.1.0" -"@babel/plugin-transform-computed-properties@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.16.7.tgz#66dee12e46f61d2aae7a73710f591eb3df616470" - integrity sha512-gN72G9bcmenVILj//sv1zLNaPyYcOzUho2lIJBMh/iakJ9ygCo/hEF9cpGb61SCMEDxbbyBoVQxrt+bWKu5KGw== +"@babel/plugin-transform-computed-properties@^7.18.9": + version "7.18.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.18.9.tgz#2357a8224d402dad623caf6259b611e56aec746e" + integrity sha512-+i0ZU1bCDymKakLxn5srGHrsAPRELC2WIbzwjLhHW9SIE1cPYkLCL0NlnXMZaM1vhfgA2+M7hySk42VBvrkBRw== dependencies: - "@babel/helper-plugin-utils" "^7.16.7" + "@babel/helper-plugin-utils" "^7.18.9" -"@babel/plugin-transform-destructuring@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.16.7.tgz#ca9588ae2d63978a4c29d3f33282d8603f618e23" - integrity sha512-VqAwhTHBnu5xBVDCvrvqJbtLUa++qZaWC0Fgr2mqokBlulZARGyIvZDoqbPlPaKImQ9dKAcCzbv+ul//uqu70A== +"@babel/plugin-transform-destructuring@^7.20.2": + version "7.20.2" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.20.2.tgz#c23741cfa44ddd35f5e53896e88c75331b8b2792" + integrity sha512-mENM+ZHrvEgxLTBXUiQ621rRXZes3KWUv6NdQlrnr1TkWVw+hUjQBZuP2X32qKlrlG2BzgR95gkuCRSkJl8vIw== dependencies: - "@babel/helper-plugin-utils" "^7.16.7" + "@babel/helper-plugin-utils" "^7.20.2" -"@babel/plugin-transform-dotall-regex@^7.16.7", "@babel/plugin-transform-dotall-regex@^7.4.4": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.16.7.tgz#6b2d67686fab15fb6a7fd4bd895d5982cfc81241" - integrity sha512-Lyttaao2SjZF6Pf4vk1dVKv8YypMpomAbygW+mU5cYP3S5cWTfCJjG8xV6CFdzGFlfWK81IjL9viiTvpb6G7gQ== +"@babel/plugin-transform-dotall-regex@^7.18.6", "@babel/plugin-transform-dotall-regex@^7.4.4": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.18.6.tgz#b286b3e7aae6c7b861e45bed0a2fafd6b1a4fef8" + integrity sha512-6S3jpun1eEbAxq7TdjLotAsl4WpQI9DxfkycRcKrjhQYzU87qpXdknpBg/e+TdcMehqGnLFi7tnFUBR02Vq6wg== dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.16.7" - "@babel/helper-plugin-utils" "^7.16.7" + "@babel/helper-create-regexp-features-plugin" "^7.18.6" + "@babel/helper-plugin-utils" "^7.18.6" -"@babel/plugin-transform-duplicate-keys@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.16.7.tgz#2207e9ca8f82a0d36a5a67b6536e7ef8b08823c9" - integrity sha512-03DvpbRfvWIXyK0/6QiR1KMTWeT6OcQ7tbhjrXyFS02kjuX/mu5Bvnh5SDSWHxyawit2g5aWhKwI86EE7GUnTw== +"@babel/plugin-transform-duplicate-keys@^7.18.9": + version "7.18.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.18.9.tgz#687f15ee3cdad6d85191eb2a372c4528eaa0ae0e" + integrity sha512-d2bmXCtZXYc59/0SanQKbiWINadaJXqtvIQIzd4+hNwkWBgyCd5F/2t1kXoUdvPMrxzPvhK6EMQRROxsue+mfw== dependencies: - "@babel/helper-plugin-utils" "^7.16.7" + "@babel/helper-plugin-utils" "^7.18.9" -"@babel/plugin-transform-exponentiation-operator@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.16.7.tgz#efa9862ef97e9e9e5f653f6ddc7b665e8536fe9b" - integrity sha512-8UYLSlyLgRixQvlYH3J2ekXFHDFLQutdy7FfFAMm3CPZ6q9wHCwnUyiXpQCe3gVVnQlHc5nsuiEVziteRNTXEA== +"@babel/plugin-transform-exponentiation-operator@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.18.6.tgz#421c705f4521888c65e91fdd1af951bfefd4dacd" + integrity sha512-wzEtc0+2c88FVR34aQmiz56dxEkxr2g8DQb/KfaFa1JYXOFVsbhvAonFN6PwVWj++fKmku8NP80plJ5Et4wqHw== dependencies: - "@babel/helper-builder-binary-assignment-operator-visitor" "^7.16.7" - "@babel/helper-plugin-utils" "^7.16.7" + "@babel/helper-builder-binary-assignment-operator-visitor" "^7.18.6" + "@babel/helper-plugin-utils" "^7.18.6" -"@babel/plugin-transform-for-of@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.16.7.tgz#649d639d4617dff502a9a158c479b3b556728d8c" - integrity sha512-/QZm9W92Ptpw7sjI9Nx1mbcsWz33+l8kuMIQnDwgQBG5s3fAfQvkRjQ7NqXhtNcKOnPkdICmUHyCaWW06HCsqg== +"@babel/plugin-transform-for-of@^7.18.8": + version "7.18.8" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.18.8.tgz#6ef8a50b244eb6a0bdbad0c7c61877e4e30097c1" + integrity sha512-yEfTRnjuskWYo0k1mHUqrVWaZwrdq8AYbfrpqULOJOaucGSp4mNMVps+YtA8byoevxS/urwU75vyhQIxcCgiBQ== dependencies: - "@babel/helper-plugin-utils" "^7.16.7" + "@babel/helper-plugin-utils" "^7.18.6" -"@babel/plugin-transform-function-name@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.16.7.tgz#5ab34375c64d61d083d7d2f05c38d90b97ec65cf" - integrity sha512-SU/C68YVwTRxqWj5kgsbKINakGag0KTgq9f2iZEXdStoAbOzLHEBRYzImmA6yFo8YZhJVflvXmIHUO7GWHmxxA== +"@babel/plugin-transform-function-name@^7.18.9": + version "7.18.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.18.9.tgz#cc354f8234e62968946c61a46d6365440fc764e0" + integrity sha512-WvIBoRPaJQ5yVHzcnJFor7oS5Ls0PYixlTYE63lCj2RtdQEl15M68FXQlxnG6wdraJIXRdR7KI+hQ7q/9QjrCQ== dependencies: - "@babel/helper-compilation-targets" "^7.16.7" - "@babel/helper-function-name" "^7.16.7" - "@babel/helper-plugin-utils" "^7.16.7" + "@babel/helper-compilation-targets" "^7.18.9" + "@babel/helper-function-name" "^7.18.9" + "@babel/helper-plugin-utils" "^7.18.9" -"@babel/plugin-transform-literals@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-literals/-/plugin-transform-literals-7.16.7.tgz#254c9618c5ff749e87cb0c0cef1a0a050c0bdab1" - integrity sha512-6tH8RTpTWI0s2sV6uq3e/C9wPo4PTqqZps4uF0kzQ9/xPLFQtipynvmT1g/dOfEJ+0EQsHhkQ/zyRId8J2b8zQ== +"@babel/plugin-transform-literals@^7.18.9": + version "7.18.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-literals/-/plugin-transform-literals-7.18.9.tgz#72796fdbef80e56fba3c6a699d54f0de557444bc" + integrity sha512-IFQDSRoTPnrAIrI5zoZv73IFeZu2dhu6irxQjY9rNjTT53VmKg9fenjvoiOWOkJ6mm4jKVPtdMzBY98Fp4Z4cg== dependencies: - "@babel/helper-plugin-utils" "^7.16.7" + "@babel/helper-plugin-utils" "^7.18.9" -"@babel/plugin-transform-member-expression-literals@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.16.7.tgz#6e5dcf906ef8a098e630149d14c867dd28f92384" - integrity sha512-mBruRMbktKQwbxaJof32LT9KLy2f3gH+27a5XSuXo6h7R3vqltl0PgZ80C8ZMKw98Bf8bqt6BEVi3svOh2PzMw== +"@babel/plugin-transform-member-expression-literals@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.18.6.tgz#ac9fdc1a118620ac49b7e7a5d2dc177a1bfee88e" + integrity sha512-qSF1ihLGO3q+/g48k85tUjD033C29TNTVB2paCwZPVmOsjn9pClvYYrM2VeJpBY2bcNkuny0YUyTNRyRxJ54KA== dependencies: - "@babel/helper-plugin-utils" "^7.16.7" + "@babel/helper-plugin-utils" "^7.18.6" -"@babel/plugin-transform-modules-amd@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.16.7.tgz#b28d323016a7daaae8609781d1f8c9da42b13186" - integrity sha512-KaaEtgBL7FKYwjJ/teH63oAmE3lP34N3kshz8mm4VMAw7U3PxjVwwUmxEFksbgsNUaO3wId9R2AVQYSEGRa2+g== +"@babel/plugin-transform-modules-amd@^7.19.6": + version "7.19.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.19.6.tgz#aca391801ae55d19c4d8d2ebfeaa33df5f2a2cbd" + integrity sha512-uG3od2mXvAtIFQIh0xrpLH6r5fpSQN04gIVovl+ODLdUMANokxQLZnPBHcjmv3GxRjnqwLuHvppjjcelqUFZvg== dependencies: - "@babel/helper-module-transforms" "^7.16.7" - "@babel/helper-plugin-utils" "^7.16.7" - babel-plugin-dynamic-import-node "^2.3.3" + "@babel/helper-module-transforms" "^7.19.6" + "@babel/helper-plugin-utils" "^7.19.0" -"@babel/plugin-transform-modules-commonjs@^7.16.8": - version "7.16.8" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.16.8.tgz#cdee19aae887b16b9d331009aa9a219af7c86afe" - integrity sha512-oflKPvsLT2+uKQopesJt3ApiaIS2HW+hzHFcwRNtyDGieAeC/dIHZX8buJQ2J2X1rxGPy4eRcUijm3qcSPjYcA== +"@babel/plugin-transform-modules-commonjs@^7.19.6": + version "7.19.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.19.6.tgz#25b32feef24df8038fc1ec56038917eacb0b730c" + integrity sha512-8PIa1ym4XRTKuSsOUXqDG0YaOlEuTVvHMe5JCfgBMOtHvJKw/4NGovEGN33viISshG/rZNVrACiBmPQLvWN8xQ== dependencies: - "@babel/helper-module-transforms" "^7.16.7" - "@babel/helper-plugin-utils" "^7.16.7" - "@babel/helper-simple-access" "^7.16.7" - babel-plugin-dynamic-import-node "^2.3.3" + "@babel/helper-module-transforms" "^7.19.6" + "@babel/helper-plugin-utils" "^7.19.0" + "@babel/helper-simple-access" "^7.19.4" -"@babel/plugin-transform-modules-systemjs@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.16.7.tgz#887cefaef88e684d29558c2b13ee0563e287c2d7" - integrity sha512-DuK5E3k+QQmnOqBR9UkusByy5WZWGRxfzV529s9nPra1GE7olmxfqO2FHobEOYSPIjPBTr4p66YDcjQnt8cBmw== +"@babel/plugin-transform-modules-systemjs@^7.19.6": + version "7.19.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.19.6.tgz#59e2a84064b5736a4471b1aa7b13d4431d327e0d" + integrity sha512-fqGLBepcc3kErfR9R3DnVpURmckXP7gj7bAlrTQyBxrigFqszZCkFkcoxzCp2v32XmwXLvbw+8Yq9/b+QqksjQ== dependencies: - "@babel/helper-hoist-variables" "^7.16.7" - "@babel/helper-module-transforms" "^7.16.7" - "@babel/helper-plugin-utils" "^7.16.7" - "@babel/helper-validator-identifier" "^7.16.7" - babel-plugin-dynamic-import-node "^2.3.3" + "@babel/helper-hoist-variables" "^7.18.6" + "@babel/helper-module-transforms" "^7.19.6" + "@babel/helper-plugin-utils" "^7.19.0" + "@babel/helper-validator-identifier" "^7.19.1" -"@babel/plugin-transform-modules-umd@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.16.7.tgz#23dad479fa585283dbd22215bff12719171e7618" - integrity sha512-EMh7uolsC8O4xhudF2F6wedbSHm1HHZ0C6aJ7K67zcDNidMzVcxWdGr+htW9n21klm+bOn+Rx4CBsAntZd3rEQ== +"@babel/plugin-transform-modules-umd@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.18.6.tgz#81d3832d6034b75b54e62821ba58f28ed0aab4b9" + integrity sha512-dcegErExVeXcRqNtkRU/z8WlBLnvD4MRnHgNs3MytRO1Mn1sHRyhbcpYbVMGclAqOjdW+9cfkdZno9dFdfKLfQ== dependencies: - "@babel/helper-module-transforms" "^7.16.7" - "@babel/helper-plugin-utils" "^7.16.7" + "@babel/helper-module-transforms" "^7.18.6" + "@babel/helper-plugin-utils" "^7.18.6" -"@babel/plugin-transform-named-capturing-groups-regex@^7.16.8": - version "7.16.8" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.16.8.tgz#7f860e0e40d844a02c9dcf9d84965e7dfd666252" - integrity sha512-j3Jw+n5PvpmhRR+mrgIh04puSANCk/T/UA3m3P1MjJkhlK906+ApHhDIqBQDdOgL/r1UYpz4GNclTXxyZrYGSw== +"@babel/plugin-transform-named-capturing-groups-regex@^7.19.1": + version "7.19.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.19.1.tgz#ec7455bab6cd8fb05c525a94876f435a48128888" + integrity sha512-oWk9l9WItWBQYS4FgXD4Uyy5kq898lvkXpXQxoJEY1RnvPk4R/Dvu2ebXU9q8lP+rlMwUQTFf2Ok6d78ODa0kw== dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.16.7" + "@babel/helper-create-regexp-features-plugin" "^7.19.0" + "@babel/helper-plugin-utils" "^7.19.0" -"@babel/plugin-transform-new-target@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.16.7.tgz#9967d89a5c243818e0800fdad89db22c5f514244" - integrity sha512-xiLDzWNMfKoGOpc6t3U+etCE2yRnn3SM09BXqWPIZOBpL2gvVrBWUKnsJx0K/ADi5F5YC5f8APFfWrz25TdlGg== +"@babel/plugin-transform-new-target@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.18.6.tgz#d128f376ae200477f37c4ddfcc722a8a1b3246a8" + integrity sha512-DjwFA/9Iu3Z+vrAn+8pBUGcjhxKguSMlsFqeCKbhb9BAV756v0krzVK04CRDi/4aqmk8BsHb4a/gFcaA5joXRw== dependencies: - "@babel/helper-plugin-utils" "^7.16.7" + "@babel/helper-plugin-utils" "^7.18.6" -"@babel/plugin-transform-object-super@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.16.7.tgz#ac359cf8d32cf4354d27a46867999490b6c32a94" - integrity sha512-14J1feiQVWaGvRxj2WjyMuXS2jsBkgB3MdSN5HuC2G5nRspa5RK9COcs82Pwy5BuGcjb+fYaUj94mYcOj7rCvw== +"@babel/plugin-transform-object-super@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.18.6.tgz#fb3c6ccdd15939b6ff7939944b51971ddc35912c" + integrity sha512-uvGz6zk+pZoS1aTZrOvrbj6Pp/kK2mp45t2B+bTDre2UgsZZ8EZLSJtUg7m/no0zOJUWgFONpB7Zv9W2tSaFlA== dependencies: - "@babel/helper-plugin-utils" "^7.16.7" - "@babel/helper-replace-supers" "^7.16.7" + "@babel/helper-plugin-utils" "^7.18.6" + "@babel/helper-replace-supers" "^7.18.6" -"@babel/plugin-transform-parameters@^7.12.1", "@babel/plugin-transform-parameters@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.16.7.tgz#a1721f55b99b736511cb7e0152f61f17688f331f" - integrity sha512-AT3MufQ7zZEhU2hwOA11axBnExW0Lszu4RL/tAlUJBuNoRak+wehQW8h6KcXOcgjY42fHtDxswuMhMjFEuv/aw== +"@babel/plugin-transform-parameters@^7.12.1", "@babel/plugin-transform-parameters@^7.20.1": + version "7.20.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.20.3.tgz#7b3468d70c3c5b62e46be0a47b6045d8590fb748" + integrity sha512-oZg/Fpx0YDrj13KsLyO8I/CX3Zdw7z0O9qOd95SqcoIzuqy/WTGWvePeHAnZCN54SfdyjHcb1S30gc8zlzlHcA== dependencies: - "@babel/helper-plugin-utils" "^7.16.7" + "@babel/helper-plugin-utils" "^7.20.2" -"@babel/plugin-transform-property-literals@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.16.7.tgz#2dadac85155436f22c696c4827730e0fe1057a55" - integrity sha512-z4FGr9NMGdoIl1RqavCqGG+ZuYjfZ/hkCIeuH6Do7tXmSm0ls11nYVSJqFEUOSJbDab5wC6lRE/w6YjVcr6Hqw== +"@babel/plugin-transform-property-literals@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.18.6.tgz#e22498903a483448e94e032e9bbb9c5ccbfc93a3" + integrity sha512-cYcs6qlgafTud3PAzrrRNbQtfpQ8+y/+M5tKmksS9+M1ckbH6kzY8MrexEM9mcA6JDsukE19iIRvAyYl463sMg== dependencies: - "@babel/helper-plugin-utils" "^7.16.7" + "@babel/helper-plugin-utils" "^7.18.6" -"@babel/plugin-transform-react-constant-elements@^7.14.5": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-constant-elements/-/plugin-transform-react-constant-elements-7.16.7.tgz#19e9e4c2df2f6c3e6b3aea11778297d81db8df62" - integrity sha512-lF+cfsyTgwWkcw715J88JhMYJ5GpysYNLhLP1PkvkhTRN7B3e74R/1KsDxFxhRpSn0UUD3IWM4GvdBR2PEbbQQ== +"@babel/plugin-transform-react-constant-elements@^7.18.12": + version "7.20.2" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-constant-elements/-/plugin-transform-react-constant-elements-7.20.2.tgz#3f02c784e0b711970d7d8ccc96c4359d64e27ac7" + integrity sha512-KS/G8YI8uwMGKErLFOHS/ekhqdHhpEloxs43NecQHVgo2QuQSyJhGIY1fL8UGl9wy5ItVwwoUL4YxVqsplGq2g== dependencies: - "@babel/helper-plugin-utils" "^7.16.7" + "@babel/helper-plugin-utils" "^7.20.2" -"@babel/plugin-transform-react-display-name@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.16.7.tgz#7b6d40d232f4c0f550ea348593db3b21e2404340" - integrity sha512-qgIg8BcZgd0G/Cz916D5+9kqX0c7nPZyXaP8R2tLNN5tkyIZdG5fEwBrxwplzSnjC1jvQmyMNVwUCZPcbGY7Pg== +"@babel/plugin-transform-react-display-name@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.18.6.tgz#8b1125f919ef36ebdfff061d664e266c666b9415" + integrity sha512-TV4sQ+T013n61uMoygyMRm+xf04Bd5oqFpv2jAEQwSZ8NwQA7zeRPg1LMVg2PWi3zWBz+CLKD+v5bcpZ/BS0aA== dependencies: - "@babel/helper-plugin-utils" "^7.16.7" + "@babel/helper-plugin-utils" "^7.18.6" -"@babel/plugin-transform-react-jsx-development@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.16.7.tgz#43a00724a3ed2557ed3f276a01a929e6686ac7b8" - integrity sha512-RMvQWvpla+xy6MlBpPlrKZCMRs2AGiHOGHY3xRwl0pEeim348dDyxeH4xBsMPbIMhujeq7ihE702eM2Ew0Wo+A== +"@babel/plugin-transform-react-jsx-development@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.18.6.tgz#dbe5c972811e49c7405b630e4d0d2e1380c0ddc5" + integrity sha512-SA6HEjwYFKF7WDjWcMcMGUimmw/nhNRDWxr+KaLSCrkD/LMDBvWRmHAYgE1HDeF8KUuI8OAu+RT6EOtKxSW2qA== dependencies: - "@babel/plugin-transform-react-jsx" "^7.16.7" + "@babel/plugin-transform-react-jsx" "^7.18.6" -"@babel/plugin-transform-react-jsx@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.16.7.tgz#86a6a220552afd0e4e1f0388a68a372be7add0d4" - integrity sha512-8D16ye66fxiE8m890w0BpPpngG9o9OVBBy0gH2E+2AR7qMR2ZpTYJEqLxAsoroenMId0p/wMW+Blc0meDgu0Ag== +"@babel/plugin-transform-react-jsx@^7.18.6": + version "7.19.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.19.0.tgz#b3cbb7c3a00b92ec8ae1027910e331ba5c500eb9" + integrity sha512-UVEvX3tXie3Szm3emi1+G63jyw1w5IcMY0FSKM+CRnKRI5Mr1YbCNgsSTwoTwKphQEG9P+QqmuRFneJPZuHNhg== dependencies: - "@babel/helper-annotate-as-pure" "^7.16.7" - "@babel/helper-module-imports" "^7.16.7" - "@babel/helper-plugin-utils" "^7.16.7" - "@babel/plugin-syntax-jsx" "^7.16.7" - "@babel/types" "^7.16.7" + "@babel/helper-annotate-as-pure" "^7.18.6" + "@babel/helper-module-imports" "^7.18.6" + "@babel/helper-plugin-utils" "^7.19.0" + "@babel/plugin-syntax-jsx" "^7.18.6" + "@babel/types" "^7.19.0" -"@babel/plugin-transform-react-pure-annotations@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.16.7.tgz#232bfd2f12eb551d6d7d01d13fe3f86b45eb9c67" - integrity sha512-hs71ToC97k3QWxswh2ElzMFABXHvGiJ01IB1TbYQDGeWRKWz/MPUTh5jGExdHvosYKpnJW5Pm3S4+TA3FyX+GA== - dependencies: - "@babel/helper-annotate-as-pure" "^7.16.7" - "@babel/helper-plugin-utils" "^7.16.7" +"@babel/plugin-transform-react-pure-annotations@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.18.6.tgz#561af267f19f3e5d59291f9950fd7b9663d0d844" + integrity sha512-I8VfEPg9r2TRDdvnHgPepTKvuRomzA8+u+nhY7qSI1fR2hRNebasZEETLyM5mAUr0Ku56OkXJ0I7NHJnO6cJiQ== + dependencies: + "@babel/helper-annotate-as-pure" "^7.18.6" + "@babel/helper-plugin-utils" "^7.18.6" -"@babel/plugin-transform-regenerator@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.16.7.tgz#9e7576dc476cb89ccc5096fff7af659243b4adeb" - integrity sha512-mF7jOgGYCkSJagJ6XCujSQg+6xC1M77/03K2oBmVJWoFGNUtnVJO4WHKJk3dnPC8HCcj4xBQP1Egm8DWh3Pb3Q== +"@babel/plugin-transform-regenerator@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.18.6.tgz#585c66cb84d4b4bf72519a34cfce761b8676ca73" + integrity sha512-poqRI2+qiSdeldcz4wTSTXBRryoq3Gc70ye7m7UD5Ww0nE29IXqMl6r7Nd15WBgRd74vloEMlShtH6CKxVzfmQ== dependencies: - regenerator-transform "^0.14.2" + "@babel/helper-plugin-utils" "^7.18.6" + regenerator-transform "^0.15.0" -"@babel/plugin-transform-reserved-words@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.16.7.tgz#1d798e078f7c5958eec952059c460b220a63f586" - integrity sha512-KQzzDnZ9hWQBjwi5lpY5v9shmm6IVG0U9pB18zvMu2i4H90xpT4gmqwPYsn8rObiadYe2M0gmgsiOIF5A/2rtg== +"@babel/plugin-transform-reserved-words@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.18.6.tgz#b1abd8ebf8edaa5f7fe6bbb8d2133d23b6a6f76a" + integrity sha512-oX/4MyMoypzHjFrT1CdivfKZ+XvIPMFXwwxHp/r0Ddy2Vuomt4HDFGmft1TAY2yiTKiNSsh3kjBAzcM8kSdsjA== dependencies: - "@babel/helper-plugin-utils" "^7.16.7" + "@babel/helper-plugin-utils" "^7.18.6" -"@babel/plugin-transform-runtime@^7.16.0": - version "7.16.8" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.16.8.tgz#3339368701103edae708f0fba9e4bfb70a3e5872" - integrity sha512-6Kg2XHPFnIarNweZxmzbgYnnWsXxkx9WQUVk2sksBRL80lBC1RAQV3wQagWxdCHiYHqPN+oenwNIuttlYgIbQQ== +"@babel/plugin-transform-runtime@^7.18.6": + version "7.19.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.19.6.tgz#9d2a9dbf4e12644d6f46e5e75bfbf02b5d6e9194" + integrity sha512-PRH37lz4JU156lYFW1p8OxE5i7d6Sl/zV58ooyr+q1J1lnQPyg5tIiXlIwNVhJaY4W3TmOtdc8jqdXQcB1v5Yw== dependencies: - "@babel/helper-module-imports" "^7.16.7" - "@babel/helper-plugin-utils" "^7.16.7" - babel-plugin-polyfill-corejs2 "^0.3.0" - babel-plugin-polyfill-corejs3 "^0.5.0" - babel-plugin-polyfill-regenerator "^0.3.0" + "@babel/helper-module-imports" "^7.18.6" + "@babel/helper-plugin-utils" "^7.19.0" + babel-plugin-polyfill-corejs2 "^0.3.3" + babel-plugin-polyfill-corejs3 "^0.6.0" + babel-plugin-polyfill-regenerator "^0.4.1" semver "^6.3.0" -"@babel/plugin-transform-shorthand-properties@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.16.7.tgz#e8549ae4afcf8382f711794c0c7b6b934c5fbd2a" - integrity sha512-hah2+FEnoRoATdIb05IOXf+4GzXYTq75TVhIn1PewihbpyrNWUt2JbudKQOETWw6QpLe+AIUpJ5MVLYTQbeeUg== - dependencies: - "@babel/helper-plugin-utils" "^7.16.7" - -"@babel/plugin-transform-spread@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-spread/-/plugin-transform-spread-7.16.7.tgz#a303e2122f9f12e0105daeedd0f30fb197d8ff44" - integrity sha512-+pjJpgAngb53L0iaA5gU/1MLXJIfXcYepLgXB3esVRf4fqmj8f2cxM3/FKaHsZms08hFQJkFccEWuIpm429TXg== - dependencies: - "@babel/helper-plugin-utils" "^7.16.7" - "@babel/helper-skip-transparent-expression-wrappers" "^7.16.0" - -"@babel/plugin-transform-sticky-regex@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.16.7.tgz#c84741d4f4a38072b9a1e2e3fd56d359552e8660" - integrity sha512-NJa0Bd/87QV5NZZzTuZG5BPJjLYadeSZ9fO6oOUoL4iQx+9EEuw/eEM92SrsT19Yc2jgB1u1hsjqDtH02c3Drw== - dependencies: - "@babel/helper-plugin-utils" "^7.16.7" - -"@babel/plugin-transform-template-literals@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.16.7.tgz#f3d1c45d28967c8e80f53666fc9c3e50618217ab" - integrity sha512-VwbkDDUeenlIjmfNeDX/V0aWrQH2QiVyJtwymVQSzItFDTpxfyJh3EVaQiS0rIN/CqbLGr0VcGmuwyTdZtdIsA== - dependencies: - "@babel/helper-plugin-utils" "^7.16.7" - -"@babel/plugin-transform-typeof-symbol@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.16.7.tgz#9cdbe622582c21368bd482b660ba87d5545d4f7e" - integrity sha512-p2rOixCKRJzpg9JB4gjnG4gjWkWa89ZoYUnl9snJ1cWIcTH/hvxZqfO+WjG6T8DRBpctEol5jw1O5rA8gkCokQ== - dependencies: - "@babel/helper-plugin-utils" "^7.16.7" - -"@babel/plugin-transform-typescript@^7.16.7": - version "7.16.8" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.16.8.tgz#591ce9b6b83504903fa9dd3652c357c2ba7a1ee0" - integrity sha512-bHdQ9k7YpBDO2d0NVfkj51DpQcvwIzIusJ7mEUaMlbZq3Kt/U47j24inXZHQ5MDiYpCs+oZiwnXyKedE8+q7AQ== - dependencies: - "@babel/helper-create-class-features-plugin" "^7.16.7" - "@babel/helper-plugin-utils" "^7.16.7" - "@babel/plugin-syntax-typescript" "^7.16.7" - -"@babel/plugin-transform-unicode-escapes@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.16.7.tgz#da8717de7b3287a2c6d659750c964f302b31ece3" - integrity sha512-TAV5IGahIz3yZ9/Hfv35TV2xEm+kaBDaZQCn2S/hG9/CZ0DktxJv9eKfPc7yYCvOYR4JGx1h8C+jcSOvgaaI/Q== - dependencies: - "@babel/helper-plugin-utils" "^7.16.7" - -"@babel/plugin-transform-unicode-regex@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.16.7.tgz#0f7aa4a501198976e25e82702574c34cfebe9ef2" - integrity sha512-oC5tYYKw56HO75KZVLQ+R/Nl3Hro9kf8iG0hXoaHP7tjAyCpvqBiSNe6vGrZni1Z6MggmUOC6A7VP7AVmw225Q== - dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.16.7" - "@babel/helper-plugin-utils" "^7.16.7" - -"@babel/preset-env@^7.15.6", "@babel/preset-env@^7.16.4": - version "7.16.8" - resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.16.8.tgz#e682fa0bcd1cf49621d64a8956318ddfb9a05af9" - integrity sha512-9rNKgVCdwHb3z1IlbMyft6yIXIeP3xz6vWvGaLHrJThuEIqWfHb0DNBH9VuTgnDfdbUDhkmkvMZS/YMCtP7Elg== - dependencies: - "@babel/compat-data" "^7.16.8" - "@babel/helper-compilation-targets" "^7.16.7" - "@babel/helper-plugin-utils" "^7.16.7" - "@babel/helper-validator-option" "^7.16.7" - "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression" "^7.16.7" - "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining" "^7.16.7" - "@babel/plugin-proposal-async-generator-functions" "^7.16.8" - "@babel/plugin-proposal-class-properties" "^7.16.7" - "@babel/plugin-proposal-class-static-block" "^7.16.7" - "@babel/plugin-proposal-dynamic-import" "^7.16.7" - "@babel/plugin-proposal-export-namespace-from" "^7.16.7" - "@babel/plugin-proposal-json-strings" "^7.16.7" - "@babel/plugin-proposal-logical-assignment-operators" "^7.16.7" - "@babel/plugin-proposal-nullish-coalescing-operator" "^7.16.7" - "@babel/plugin-proposal-numeric-separator" "^7.16.7" - "@babel/plugin-proposal-object-rest-spread" "^7.16.7" - "@babel/plugin-proposal-optional-catch-binding" "^7.16.7" - "@babel/plugin-proposal-optional-chaining" "^7.16.7" - "@babel/plugin-proposal-private-methods" "^7.16.7" - "@babel/plugin-proposal-private-property-in-object" "^7.16.7" - "@babel/plugin-proposal-unicode-property-regex" "^7.16.7" +"@babel/plugin-transform-shorthand-properties@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.18.6.tgz#6d6df7983d67b195289be24909e3f12a8f664dc9" + integrity sha512-eCLXXJqv8okzg86ywZJbRn19YJHU4XUa55oz2wbHhaQVn/MM+XhukiT7SYqp/7o00dg52Rj51Ny+Ecw4oyoygw== + dependencies: + "@babel/helper-plugin-utils" "^7.18.6" + +"@babel/plugin-transform-spread@^7.19.0": + version "7.19.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-spread/-/plugin-transform-spread-7.19.0.tgz#dd60b4620c2fec806d60cfaae364ec2188d593b6" + integrity sha512-RsuMk7j6n+r752EtzyScnWkQyuJdli6LdO5Klv8Yx0OfPVTcQkIUfS8clx5e9yHXzlnhOZF3CbQ8C2uP5j074w== + dependencies: + "@babel/helper-plugin-utils" "^7.19.0" + "@babel/helper-skip-transparent-expression-wrappers" "^7.18.9" + +"@babel/plugin-transform-sticky-regex@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.18.6.tgz#c6706eb2b1524028e317720339583ad0f444adcc" + integrity sha512-kfiDrDQ+PBsQDO85yj1icueWMfGfJFKN1KCkndygtu/C9+XUfydLC8Iv5UYJqRwy4zk8EcplRxEOeLyjq1gm6Q== + dependencies: + "@babel/helper-plugin-utils" "^7.18.6" + +"@babel/plugin-transform-template-literals@^7.18.9": + version "7.18.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.18.9.tgz#04ec6f10acdaa81846689d63fae117dd9c243a5e" + integrity sha512-S8cOWfT82gTezpYOiVaGHrCbhlHgKhQt8XH5ES46P2XWmX92yisoZywf5km75wv5sYcXDUCLMmMxOLCtthDgMA== + dependencies: + "@babel/helper-plugin-utils" "^7.18.9" + +"@babel/plugin-transform-typeof-symbol@^7.18.9": + version "7.18.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.18.9.tgz#c8cea68263e45addcd6afc9091429f80925762c0" + integrity sha512-SRfwTtF11G2aemAZWivL7PD+C9z52v9EvMqH9BuYbabyPuKUvSWks3oCg6041pT925L4zVFqaVBeECwsmlguEw== + dependencies: + "@babel/helper-plugin-utils" "^7.18.9" + +"@babel/plugin-transform-typescript@^7.18.6": + version "7.20.2" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.20.2.tgz#91515527b376fc122ba83b13d70b01af8fe98f3f" + integrity sha512-jvS+ngBfrnTUBfOQq8NfGnSbF9BrqlR6hjJ2yVxMkmO5nL/cdifNbI30EfjRlN4g5wYWNnMPyj5Sa6R1pbLeag== + dependencies: + "@babel/helper-create-class-features-plugin" "^7.20.2" + "@babel/helper-plugin-utils" "^7.20.2" + "@babel/plugin-syntax-typescript" "^7.20.0" + +"@babel/plugin-transform-unicode-escapes@^7.18.10": + version "7.18.10" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.18.10.tgz#1ecfb0eda83d09bbcb77c09970c2dd55832aa246" + integrity sha512-kKAdAI+YzPgGY/ftStBFXTI1LZFju38rYThnfMykS+IXy8BVx+res7s2fxf1l8I35DV2T97ezo6+SGrXz6B3iQ== + dependencies: + "@babel/helper-plugin-utils" "^7.18.9" + +"@babel/plugin-transform-unicode-regex@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.18.6.tgz#194317225d8c201bbae103364ffe9e2cea36cdca" + integrity sha512-gE7A6Lt7YLnNOL3Pb9BNeZvi+d8l7tcRrG4+pwJjK9hD2xX4mEvjlQW60G9EEmfXVYRPv9VRQcyegIVHCql/AA== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.18.6" + "@babel/helper-plugin-utils" "^7.18.6" + +"@babel/preset-env@^7.18.6", "@babel/preset-env@^7.19.4": + version "7.20.2" + resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.20.2.tgz#9b1642aa47bb9f43a86f9630011780dab7f86506" + integrity sha512-1G0efQEWR1EHkKvKHqbG+IN/QdgwfByUpM5V5QroDzGV2t3S/WXNQd693cHiHTlCFMpr9B6FkPFXDA2lQcKoDg== + dependencies: + "@babel/compat-data" "^7.20.1" + "@babel/helper-compilation-targets" "^7.20.0" + "@babel/helper-plugin-utils" "^7.20.2" + "@babel/helper-validator-option" "^7.18.6" + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression" "^7.18.6" + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining" "^7.18.9" + "@babel/plugin-proposal-async-generator-functions" "^7.20.1" + "@babel/plugin-proposal-class-properties" "^7.18.6" + "@babel/plugin-proposal-class-static-block" "^7.18.6" + "@babel/plugin-proposal-dynamic-import" "^7.18.6" + "@babel/plugin-proposal-export-namespace-from" "^7.18.9" + "@babel/plugin-proposal-json-strings" "^7.18.6" + "@babel/plugin-proposal-logical-assignment-operators" "^7.18.9" + "@babel/plugin-proposal-nullish-coalescing-operator" "^7.18.6" + "@babel/plugin-proposal-numeric-separator" "^7.18.6" + "@babel/plugin-proposal-object-rest-spread" "^7.20.2" + "@babel/plugin-proposal-optional-catch-binding" "^7.18.6" + "@babel/plugin-proposal-optional-chaining" "^7.18.9" + "@babel/plugin-proposal-private-methods" "^7.18.6" + "@babel/plugin-proposal-private-property-in-object" "^7.18.6" + "@babel/plugin-proposal-unicode-property-regex" "^7.18.6" "@babel/plugin-syntax-async-generators" "^7.8.4" "@babel/plugin-syntax-class-properties" "^7.12.13" "@babel/plugin-syntax-class-static-block" "^7.14.5" "@babel/plugin-syntax-dynamic-import" "^7.8.3" "@babel/plugin-syntax-export-namespace-from" "^7.8.3" + "@babel/plugin-syntax-import-assertions" "^7.20.0" "@babel/plugin-syntax-json-strings" "^7.8.3" "@babel/plugin-syntax-logical-assignment-operators" "^7.10.4" "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.3" @@ -1043,44 +1061,44 @@ "@babel/plugin-syntax-optional-chaining" "^7.8.3" "@babel/plugin-syntax-private-property-in-object" "^7.14.5" "@babel/plugin-syntax-top-level-await" "^7.14.5" - "@babel/plugin-transform-arrow-functions" "^7.16.7" - "@babel/plugin-transform-async-to-generator" "^7.16.8" - "@babel/plugin-transform-block-scoped-functions" "^7.16.7" - "@babel/plugin-transform-block-scoping" "^7.16.7" - "@babel/plugin-transform-classes" "^7.16.7" - "@babel/plugin-transform-computed-properties" "^7.16.7" - "@babel/plugin-transform-destructuring" "^7.16.7" - "@babel/plugin-transform-dotall-regex" "^7.16.7" - "@babel/plugin-transform-duplicate-keys" "^7.16.7" - "@babel/plugin-transform-exponentiation-operator" "^7.16.7" - "@babel/plugin-transform-for-of" "^7.16.7" - "@babel/plugin-transform-function-name" "^7.16.7" - "@babel/plugin-transform-literals" "^7.16.7" - "@babel/plugin-transform-member-expression-literals" "^7.16.7" - "@babel/plugin-transform-modules-amd" "^7.16.7" - "@babel/plugin-transform-modules-commonjs" "^7.16.8" - "@babel/plugin-transform-modules-systemjs" "^7.16.7" - "@babel/plugin-transform-modules-umd" "^7.16.7" - "@babel/plugin-transform-named-capturing-groups-regex" "^7.16.8" - "@babel/plugin-transform-new-target" "^7.16.7" - "@babel/plugin-transform-object-super" "^7.16.7" - "@babel/plugin-transform-parameters" "^7.16.7" - "@babel/plugin-transform-property-literals" "^7.16.7" - "@babel/plugin-transform-regenerator" "^7.16.7" - "@babel/plugin-transform-reserved-words" "^7.16.7" - "@babel/plugin-transform-shorthand-properties" "^7.16.7" - "@babel/plugin-transform-spread" "^7.16.7" - "@babel/plugin-transform-sticky-regex" "^7.16.7" - "@babel/plugin-transform-template-literals" "^7.16.7" - "@babel/plugin-transform-typeof-symbol" "^7.16.7" - "@babel/plugin-transform-unicode-escapes" "^7.16.7" - "@babel/plugin-transform-unicode-regex" "^7.16.7" + "@babel/plugin-transform-arrow-functions" "^7.18.6" + "@babel/plugin-transform-async-to-generator" "^7.18.6" + "@babel/plugin-transform-block-scoped-functions" "^7.18.6" + "@babel/plugin-transform-block-scoping" "^7.20.2" + "@babel/plugin-transform-classes" "^7.20.2" + "@babel/plugin-transform-computed-properties" "^7.18.9" + "@babel/plugin-transform-destructuring" "^7.20.2" + "@babel/plugin-transform-dotall-regex" "^7.18.6" + "@babel/plugin-transform-duplicate-keys" "^7.18.9" + "@babel/plugin-transform-exponentiation-operator" "^7.18.6" + "@babel/plugin-transform-for-of" "^7.18.8" + "@babel/plugin-transform-function-name" "^7.18.9" + "@babel/plugin-transform-literals" "^7.18.9" + "@babel/plugin-transform-member-expression-literals" "^7.18.6" + "@babel/plugin-transform-modules-amd" "^7.19.6" + "@babel/plugin-transform-modules-commonjs" "^7.19.6" + "@babel/plugin-transform-modules-systemjs" "^7.19.6" + "@babel/plugin-transform-modules-umd" "^7.18.6" + "@babel/plugin-transform-named-capturing-groups-regex" "^7.19.1" + "@babel/plugin-transform-new-target" "^7.18.6" + "@babel/plugin-transform-object-super" "^7.18.6" + "@babel/plugin-transform-parameters" "^7.20.1" + "@babel/plugin-transform-property-literals" "^7.18.6" + "@babel/plugin-transform-regenerator" "^7.18.6" + "@babel/plugin-transform-reserved-words" "^7.18.6" + "@babel/plugin-transform-shorthand-properties" "^7.18.6" + "@babel/plugin-transform-spread" "^7.19.0" + "@babel/plugin-transform-sticky-regex" "^7.18.6" + "@babel/plugin-transform-template-literals" "^7.18.9" + "@babel/plugin-transform-typeof-symbol" "^7.18.9" + "@babel/plugin-transform-unicode-escapes" "^7.18.10" + "@babel/plugin-transform-unicode-regex" "^7.18.6" "@babel/preset-modules" "^0.1.5" - "@babel/types" "^7.16.8" - babel-plugin-polyfill-corejs2 "^0.3.0" - babel-plugin-polyfill-corejs3 "^0.5.0" - babel-plugin-polyfill-regenerator "^0.3.0" - core-js-compat "^3.20.2" + "@babel/types" "^7.20.2" + babel-plugin-polyfill-corejs2 "^0.3.3" + babel-plugin-polyfill-corejs3 "^0.6.0" + babel-plugin-polyfill-regenerator "^0.4.1" + core-js-compat "^3.25.1" semver "^6.3.0" "@babel/preset-modules@^0.1.5": @@ -1094,322 +1112,350 @@ "@babel/types" "^7.4.4" esutils "^2.0.2" -"@babel/preset-react@^7.14.5", "@babel/preset-react@^7.16.0": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/preset-react/-/preset-react-7.16.7.tgz#4c18150491edc69c183ff818f9f2aecbe5d93852" - integrity sha512-fWpyI8UM/HE6DfPBzD8LnhQ/OcH8AgTaqcqP2nGOXEUV+VKBR5JRN9hCk9ai+zQQ57vtm9oWeXguBCPNUjytgA== - dependencies: - "@babel/helper-plugin-utils" "^7.16.7" - "@babel/helper-validator-option" "^7.16.7" - "@babel/plugin-transform-react-display-name" "^7.16.7" - "@babel/plugin-transform-react-jsx" "^7.16.7" - "@babel/plugin-transform-react-jsx-development" "^7.16.7" - "@babel/plugin-transform-react-pure-annotations" "^7.16.7" - -"@babel/preset-typescript@^7.15.0", "@babel/preset-typescript@^7.16.0": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/preset-typescript/-/preset-typescript-7.16.7.tgz#ab114d68bb2020afc069cd51b37ff98a046a70b9" - integrity sha512-WbVEmgXdIyvzB77AQjGBEyYPZx+8tTsO50XtfozQrkW8QB2rLJpH2lgx0TRw5EJrBxOZQ+wCcyPVQvS8tjEHpQ== - dependencies: - "@babel/helper-plugin-utils" "^7.16.7" - "@babel/helper-validator-option" "^7.16.7" - "@babel/plugin-transform-typescript" "^7.16.7" - -"@babel/runtime-corejs3@^7.16.3": - version "7.16.8" - resolved "https://registry.yarnpkg.com/@babel/runtime-corejs3/-/runtime-corejs3-7.16.8.tgz#ea533d96eda6fdc76b1812248e9fbd0c11d4a1a7" - integrity sha512-3fKhuICS1lMz0plI5ktOE/yEtBRMVxplzRkdn6mJQ197XiY0JnrzYV0+Mxozq3JZ8SBV9Ecurmw1XsGbwOf+Sg== - dependencies: - core-js-pure "^3.20.2" - regenerator-runtime "^0.13.4" - -"@babel/runtime@^7.1.2", "@babel/runtime@^7.10.2", "@babel/runtime@^7.10.3", "@babel/runtime@^7.12.1", "@babel/runtime@^7.12.13", "@babel/runtime@^7.16.3", "@babel/runtime@^7.8.4": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.16.7.tgz#03ff99f64106588c9c403c6ecb8c3bafbbdff1fa" - integrity sha512-9E9FJowqAsytyOY6LG+1KuueckRL+aQW+mKvXRXnuFGyRAyepJPmEo9vgMfXUA6O9u3IeEdv9MAkppFcaQwogQ== - dependencies: - regenerator-runtime "^0.13.4" - -"@babel/template@^7.12.7", "@babel/template@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.16.7.tgz#8d126c8701fde4d66b264b3eba3d96f07666d155" - integrity sha512-I8j/x8kHUrbYRTUxXrrMbfCa7jxkE7tZre39x3kjr9hvI82cK1FfqLygotcWN5kdPGWcLdWMHpSBavse5tWw3w== - dependencies: - "@babel/code-frame" "^7.16.7" - "@babel/parser" "^7.16.7" - "@babel/types" "^7.16.7" - -"@babel/traverse@^7.12.9", "@babel/traverse@^7.13.0", "@babel/traverse@^7.16.3", "@babel/traverse@^7.16.7", "@babel/traverse@^7.16.8": - version "7.16.8" - resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.16.8.tgz#bab2f2b09a5fe8a8d9cad22cbfe3ba1d126fef9c" - integrity sha512-xe+H7JlvKsDQwXRsBhSnq1/+9c+LlQcCK3Tn/l5sbx02HYns/cn7ibp9+RV1sIUqu7hKg91NWsgHurO9dowITQ== - dependencies: - "@babel/code-frame" "^7.16.7" - "@babel/generator" "^7.16.8" - "@babel/helper-environment-visitor" "^7.16.7" - "@babel/helper-function-name" "^7.16.7" - "@babel/helper-hoist-variables" "^7.16.7" - "@babel/helper-split-export-declaration" "^7.16.7" - "@babel/parser" "^7.16.8" - "@babel/types" "^7.16.8" +"@babel/preset-react@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/preset-react/-/preset-react-7.18.6.tgz#979f76d6277048dc19094c217b507f3ad517dd2d" + integrity sha512-zXr6atUmyYdiWRVLOZahakYmOBHtWc2WGCkP8PYTgZi0iJXDY2CN180TdrIW4OGOAdLc7TifzDIvtx6izaRIzg== + dependencies: + "@babel/helper-plugin-utils" "^7.18.6" + "@babel/helper-validator-option" "^7.18.6" + "@babel/plugin-transform-react-display-name" "^7.18.6" + "@babel/plugin-transform-react-jsx" "^7.18.6" + "@babel/plugin-transform-react-jsx-development" "^7.18.6" + "@babel/plugin-transform-react-pure-annotations" "^7.18.6" + +"@babel/preset-typescript@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/preset-typescript/-/preset-typescript-7.18.6.tgz#ce64be3e63eddc44240c6358daefac17b3186399" + integrity sha512-s9ik86kXBAnD760aybBucdpnLsAt0jK1xqJn2juOn9lkOvSHV60os5hxoVJsPzMQxvnUJFAlkont2DvvaYEBtQ== + dependencies: + "@babel/helper-plugin-utils" "^7.18.6" + "@babel/helper-validator-option" "^7.18.6" + "@babel/plugin-transform-typescript" "^7.18.6" + +"@babel/runtime-corejs3@^7.18.6": + version "7.20.1" + resolved "https://registry.yarnpkg.com/@babel/runtime-corejs3/-/runtime-corejs3-7.20.1.tgz#d0775a49bb5fba77e42cbb7276c9955c7b05af8d" + integrity sha512-CGulbEDcg/ND1Im7fUNRZdGXmX2MTWVVZacQi/6DiKE5HNwZ3aVTm5PV4lO8HHz0B2h8WQyvKKjbX5XgTtydsg== + dependencies: + core-js-pure "^3.25.1" + regenerator-runtime "^0.13.10" + +"@babel/runtime@^7.1.2", "@babel/runtime@^7.10.2", "@babel/runtime@^7.10.3", "@babel/runtime@^7.12.13", "@babel/runtime@^7.12.5", "@babel/runtime@^7.18.6", "@babel/runtime@^7.8.4": + version "7.20.1" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.20.1.tgz#1148bb33ab252b165a06698fde7576092a78b4a9" + integrity sha512-mrzLkl6U9YLF8qpqI7TB82PESyEGjm/0Ly91jG575eVxMMlb8fYfOXFZIJ8XfLrJZQbm7dlKry2bJmXBUEkdFg== + dependencies: + regenerator-runtime "^0.13.10" + +"@babel/template@^7.12.7", "@babel/template@^7.18.10": + version "7.18.10" + resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.18.10.tgz#6f9134835970d1dbf0835c0d100c9f38de0c5e71" + integrity sha512-TI+rCtooWHr3QJ27kJxfjutghu44DLnasDMwpDqCXVTal9RLp3RSYNh4NdBrRP2cQAoG9A8juOQl6P6oZG4JxA== + dependencies: + "@babel/code-frame" "^7.18.6" + "@babel/parser" "^7.18.10" + "@babel/types" "^7.18.10" + +"@babel/traverse@^7.12.9", "@babel/traverse@^7.18.8", "@babel/traverse@^7.19.0", "@babel/traverse@^7.19.1", "@babel/traverse@^7.20.1": + version "7.20.1" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.20.1.tgz#9b15ccbf882f6d107eeeecf263fbcdd208777ec8" + integrity sha512-d3tN8fkVJwFLkHkBN479SOsw4DMZnz8cdbL/gvuDuzy3TS6Nfw80HuQqhw1pITbIruHyh7d1fMA47kWzmcUEGA== + dependencies: + "@babel/code-frame" "^7.18.6" + "@babel/generator" "^7.20.1" + "@babel/helper-environment-visitor" "^7.18.9" + "@babel/helper-function-name" "^7.19.0" + "@babel/helper-hoist-variables" "^7.18.6" + "@babel/helper-split-export-declaration" "^7.18.6" + "@babel/parser" "^7.20.1" + "@babel/types" "^7.20.0" debug "^4.1.0" globals "^11.1.0" -"@babel/types@^7.12.7", "@babel/types@^7.15.6", "@babel/types@^7.16.0", "@babel/types@^7.16.7", "@babel/types@^7.16.8", "@babel/types@^7.4.4": - version "7.16.8" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.16.8.tgz#0ba5da91dd71e0a4e7781a30f22770831062e3c1" - integrity sha512-smN2DQc5s4M7fntyjGtyIPbRJv6wW4rU/94fmYJ7PKQuZkC0qGMHXJbg6sNGt12JmVr4k5YaptI/XtiLJBnmIg== +"@babel/types@^7.12.7", "@babel/types@^7.16.7", "@babel/types@^7.18.10", "@babel/types@^7.18.6", "@babel/types@^7.18.9", "@babel/types@^7.19.0", "@babel/types@^7.20.0", "@babel/types@^7.20.2", "@babel/types@^7.4.4": + version "7.20.2" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.20.2.tgz#67ac09266606190f496322dbaff360fdaa5e7842" + integrity sha512-FnnvsNWgZCr232sqtXggapvlkk/tuwR/qhGzcmxI0GXLCjmPYQPzio2FbdlWuY6y1sHFfQKk+rRbUZ9VStQMog== dependencies: - "@babel/helper-validator-identifier" "^7.16.7" + "@babel/helper-string-parser" "^7.19.4" + "@babel/helper-validator-identifier" "^7.19.1" to-fast-properties "^2.0.0" -"@docsearch/css@3.0.0-alpha.42": - version "3.0.0-alpha.42" - resolved "https://registry.yarnpkg.com/@docsearch/css/-/css-3.0.0-alpha.42.tgz#deb6049e999d6ca9451eba4793cb5b6da28c8773" - integrity sha512-AGwI2AXUacYhVOHmYnsXoYDJKO6Ued2W+QO80GERbMLhC7GH5tfvtW5REs/s7jSdcU3vzFoxT8iPDBCh/PkrlQ== +"@colors/colors@1.5.0": + version "1.5.0" + resolved "https://registry.yarnpkg.com/@colors/colors/-/colors-1.5.0.tgz#bb504579c1cae923e6576a4f5da43d25f97bdbd9" + integrity sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ== + +"@docsearch/css@3.3.0": + version "3.3.0" + resolved "https://registry.yarnpkg.com/@docsearch/css/-/css-3.3.0.tgz#d698e48302d12240d7c2f7452ccb2d2239a8cd80" + integrity sha512-rODCdDtGyudLj+Va8b6w6Y85KE85bXRsps/R4Yjwt5vueXKXZQKYw0aA9knxLBT6a/bI/GMrAcmCR75KYOM6hg== -"@docsearch/react@^3.0.0-alpha.39": - version "3.0.0-alpha.42" - resolved "https://registry.yarnpkg.com/@docsearch/react/-/react-3.0.0-alpha.42.tgz#1d22a2b05779f24d090ff8d7ff2699e4d50dff5c" - integrity sha512-1aOslZJDxwUUcm2QRNmlEePUgL8P5fOAeFdOLDMctHQkV2iTja9/rKVbkP8FZbIUnZxuuCCn8ErLrjD/oXWOag== +"@docsearch/react@^3.1.1": + version "3.3.0" + resolved "https://registry.yarnpkg.com/@docsearch/react/-/react-3.3.0.tgz#b8ac8e7f49b9bf2f96d34c24bc1cfd097ec0eead" + integrity sha512-fhS5adZkae2SSdMYEMVg6pxI5a/cE+tW16ki1V0/ur4Fdok3hBRkmN/H8VvlXnxzggkQIIRIVvYPn00JPjen3A== dependencies: - "@algolia/autocomplete-core" "1.5.0" - "@algolia/autocomplete-preset-algolia" "1.5.0" - "@docsearch/css" "3.0.0-alpha.42" + "@algolia/autocomplete-core" "1.7.2" + "@algolia/autocomplete-preset-algolia" "1.7.2" + "@docsearch/css" "3.3.0" algoliasearch "^4.0.0" -"@docusaurus/core@2.0.0-beta.15", "@docusaurus/core@^2.0.0-beta.15": - version "2.0.0-beta.15" - resolved "https://registry.yarnpkg.com/@docusaurus/core/-/core-2.0.0-beta.15.tgz#1a3f8361803767072e56c77d60332c87e59f1ad0" - integrity sha512-zXhhD0fApMSvq/9Pkm9DQxa//hGOXVCq9yMHiXOkI5D1tLec7PxtnaC5cLfGHljkN9cKIfRDYUVcG1gHymVfpA== +"@docusaurus/core@2.2.0", "@docusaurus/core@^2.0.0-beta.15": + version "2.2.0" + resolved "https://registry.yarnpkg.com/@docusaurus/core/-/core-2.2.0.tgz#64c9ee31502c23b93c869f8188f73afaf5fd4867" + integrity sha512-Vd6XOluKQqzG12fEs9prJgDtyn6DPok9vmUWDR2E6/nV5Fl9SVkhEQOBxwObjk3kQh7OY7vguFaLh0jqdApWsA== dependencies: - "@babel/core" "^7.16.0" - "@babel/generator" "^7.16.0" + "@babel/core" "^7.18.6" + "@babel/generator" "^7.18.7" "@babel/plugin-syntax-dynamic-import" "^7.8.3" - "@babel/plugin-transform-runtime" "^7.16.0" - "@babel/preset-env" "^7.16.4" - "@babel/preset-react" "^7.16.0" - "@babel/preset-typescript" "^7.16.0" - "@babel/runtime" "^7.16.3" - "@babel/runtime-corejs3" "^7.16.3" - "@babel/traverse" "^7.16.3" - "@docusaurus/cssnano-preset" "2.0.0-beta.15" - "@docusaurus/logger" "2.0.0-beta.15" - "@docusaurus/mdx-loader" "2.0.0-beta.15" + "@babel/plugin-transform-runtime" "^7.18.6" + "@babel/preset-env" "^7.18.6" + "@babel/preset-react" "^7.18.6" + "@babel/preset-typescript" "^7.18.6" + "@babel/runtime" "^7.18.6" + "@babel/runtime-corejs3" "^7.18.6" + "@babel/traverse" "^7.18.8" + "@docusaurus/cssnano-preset" "2.2.0" + "@docusaurus/logger" "2.2.0" + "@docusaurus/mdx-loader" "2.2.0" "@docusaurus/react-loadable" "5.5.2" - "@docusaurus/utils" "2.0.0-beta.15" - "@docusaurus/utils-common" "2.0.0-beta.15" - "@docusaurus/utils-validation" "2.0.0-beta.15" - "@slorber/static-site-generator-webpack-plugin" "^4.0.0" - "@svgr/webpack" "^6.0.0" - autoprefixer "^10.3.5" - babel-loader "^8.2.2" - babel-plugin-dynamic-import-node "2.3.0" - boxen "^5.0.1" - chokidar "^3.5.2" - clean-css "^5.1.5" + "@docusaurus/utils" "2.2.0" + "@docusaurus/utils-common" "2.2.0" + "@docusaurus/utils-validation" "2.2.0" + "@slorber/static-site-generator-webpack-plugin" "^4.0.7" + "@svgr/webpack" "^6.2.1" + autoprefixer "^10.4.7" + babel-loader "^8.2.5" + babel-plugin-dynamic-import-node "^2.3.3" + boxen "^6.2.1" + chalk "^4.1.2" + chokidar "^3.5.3" + clean-css "^5.3.0" + cli-table3 "^0.6.2" + combine-promises "^1.1.0" commander "^5.1.0" - copy-webpack-plugin "^10.2.0" - core-js "^3.18.0" - css-loader "^6.5.1" - css-minimizer-webpack-plugin "^3.3.1" - cssnano "^5.0.8" - del "^6.0.0" + copy-webpack-plugin "^11.0.0" + core-js "^3.23.3" + css-loader "^6.7.1" + css-minimizer-webpack-plugin "^4.0.0" + cssnano "^5.1.12" + del "^6.1.1" detect-port "^1.3.0" escape-html "^1.0.3" eta "^1.12.3" file-loader "^6.2.0" - fs-extra "^10.0.0" - html-minifier-terser "^6.0.2" - html-tags "^3.1.0" - html-webpack-plugin "^5.4.0" + fs-extra "^10.1.0" + html-minifier-terser "^6.1.0" + html-tags "^3.2.0" + html-webpack-plugin "^5.5.0" import-fresh "^3.3.0" - is-root "^2.1.0" leven "^3.1.0" - lodash "^4.17.20" - mini-css-extract-plugin "^1.6.0" - nprogress "^0.2.0" - postcss "^8.3.7" - postcss-loader "^6.1.1" - prompts "^2.4.1" - react-dev-utils "^12.0.0" - react-helmet "^6.1.0" + lodash "^4.17.21" + mini-css-extract-plugin "^2.6.1" + postcss "^8.4.14" + postcss-loader "^7.0.0" + prompts "^2.4.2" + react-dev-utils "^12.0.1" + react-helmet-async "^1.3.0" react-loadable "npm:@docusaurus/react-loadable@5.5.2" react-loadable-ssr-addon-v5-slorber "^1.0.1" - react-router "^5.2.0" + react-router "^5.3.3" react-router-config "^5.1.1" - react-router-dom "^5.2.0" - remark-admonitions "^1.2.1" + react-router-dom "^5.3.3" rtl-detect "^1.0.4" - semver "^7.3.4" + semver "^7.3.7" serve-handler "^6.1.3" - shelljs "^0.8.4" - strip-ansi "^6.0.0" - terser-webpack-plugin "^5.2.4" - tslib "^2.3.1" + shelljs "^0.8.5" + terser-webpack-plugin "^5.3.3" + tslib "^2.4.0" update-notifier "^5.1.0" url-loader "^4.1.1" - wait-on "^6.0.0" - webpack "^5.61.0" - webpack-bundle-analyzer "^4.4.2" - webpack-dev-server "^4.7.1" + wait-on "^6.0.1" + webpack "^5.73.0" + webpack-bundle-analyzer "^4.5.0" + webpack-dev-server "^4.9.3" webpack-merge "^5.8.0" webpackbar "^5.0.2" -"@docusaurus/cssnano-preset@2.0.0-beta.15": - version "2.0.0-beta.15" - resolved "https://registry.yarnpkg.com/@docusaurus/cssnano-preset/-/cssnano-preset-2.0.0-beta.15.tgz#033c52815c428f0f66c87eaff93ea12554ea89df" - integrity sha512-55aYURbB5dqrx64lStNcZxDx5R6bKkAawlCB7mDKx3r+Qnp3ofGW7UExLQSCbTu3axT1vJCF5D7H6ljTRYJLtA== +"@docusaurus/cssnano-preset@2.2.0": + version "2.2.0" + resolved "https://registry.yarnpkg.com/@docusaurus/cssnano-preset/-/cssnano-preset-2.2.0.tgz#fc05044659051ae74ab4482afcf4a9936e81d523" + integrity sha512-mAAwCo4n66TMWBH1kXnHVZsakW9VAXJzTO4yZukuL3ro4F+JtkMwKfh42EG75K/J/YIFQG5I/Bzy0UH/hFxaTg== dependencies: - cssnano-preset-advanced "^5.1.4" - postcss "^8.3.7" - postcss-sort-media-queries "^4.1.0" + cssnano-preset-advanced "^5.3.8" + postcss "^8.4.14" + postcss-sort-media-queries "^4.2.1" + tslib "^2.4.0" -"@docusaurus/logger@2.0.0-beta.15": - version "2.0.0-beta.15" - resolved "https://registry.yarnpkg.com/@docusaurus/logger/-/logger-2.0.0-beta.15.tgz#6d17a05fb292d15fdc43b5fa90fd2a49ad5d40ce" - integrity sha512-5bDSHCyLfMtz6QnFfICdL5mgxbGfC7DW1V+/Q17nRdpZSPZgsNKK/Esp0zdDi1oxAyEpXMXx64nLaHL7joJxIg== +"@docusaurus/logger@2.2.0": + version "2.2.0" + resolved "https://registry.yarnpkg.com/@docusaurus/logger/-/logger-2.2.0.tgz#ea2f7feda7b8675485933b87f06d9c976d17423f" + integrity sha512-DF3j1cA5y2nNsu/vk8AG7xwpZu6f5MKkPPMaaIbgXLnWGfm6+wkOeW7kNrxnM95YOhKUkJUophX69nGUnLsm0A== dependencies: chalk "^4.1.2" - tslib "^2.3.1" - -"@docusaurus/mdx-loader@2.0.0-beta.15": - version "2.0.0-beta.15" - resolved "https://registry.yarnpkg.com/@docusaurus/mdx-loader/-/mdx-loader-2.0.0-beta.15.tgz#da23745bc73c93338dd330dad6bbc9d9fe325553" - integrity sha512-MVpytjDDao7hmPF1QSs9B5zoTgevZjiqjnX3FM1yjqdCv+chyUo0gnmYHjeG/4Gqu7jucp+dDdp6yQpzs4g09A== - dependencies: - "@babel/parser" "^7.16.4" - "@babel/traverse" "^7.16.3" - "@docusaurus/logger" "2.0.0-beta.15" - "@docusaurus/utils" "2.0.0-beta.15" - "@mdx-js/mdx" "^1.6.21" + tslib "^2.4.0" + +"@docusaurus/mdx-loader@2.2.0": + version "2.2.0" + resolved "https://registry.yarnpkg.com/@docusaurus/mdx-loader/-/mdx-loader-2.2.0.tgz#fd558f429e5d9403d284bd4214e54d9768b041a0" + integrity sha512-X2bzo3T0jW0VhUU+XdQofcEeozXOTmKQMvc8tUnWRdTnCvj4XEcBVdC3g+/jftceluiwSTNRAX4VBOJdNt18jA== + dependencies: + "@babel/parser" "^7.18.8" + "@babel/traverse" "^7.18.8" + "@docusaurus/logger" "2.2.0" + "@docusaurus/utils" "2.2.0" + "@mdx-js/mdx" "^1.6.22" escape-html "^1.0.3" file-loader "^6.2.0" - fs-extra "^10.0.0" + fs-extra "^10.1.0" image-size "^1.0.1" mdast-util-to-string "^2.0.0" - remark-emoji "^2.1.0" + remark-emoji "^2.2.0" stringify-object "^3.3.0" - tslib "^2.3.1" - unist-util-visit "^2.0.2" + tslib "^2.4.0" + unified "^9.2.2" + unist-util-visit "^2.0.3" url-loader "^4.1.1" - webpack "^5.61.0" - -"@docusaurus/plugin-content-blog@2.0.0-beta.15": - version "2.0.0-beta.15" - resolved "https://registry.yarnpkg.com/@docusaurus/plugin-content-blog/-/plugin-content-blog-2.0.0-beta.15.tgz#6d4bf532ad3dedb4f9fd6398b0fbe481af5b77a9" - integrity sha512-VtEwkgkoNIS8JFPe+huBeBuJ8HG8Lq1JNYM/ItwQg/cwGAgP8EgwbEuKDn428oZKEI2PpgAuf5Gv4AzJWIes9A== - dependencies: - "@docusaurus/core" "2.0.0-beta.15" - "@docusaurus/logger" "2.0.0-beta.15" - "@docusaurus/mdx-loader" "2.0.0-beta.15" - "@docusaurus/utils" "2.0.0-beta.15" - "@docusaurus/utils-common" "2.0.0-beta.15" - "@docusaurus/utils-validation" "2.0.0-beta.15" - cheerio "^1.0.0-rc.10" + webpack "^5.73.0" + +"@docusaurus/module-type-aliases@2.2.0": + version "2.2.0" + resolved "https://registry.yarnpkg.com/@docusaurus/module-type-aliases/-/module-type-aliases-2.2.0.tgz#1e23e54a1bbb6fde1961e4fa395b1b69f4803ba5" + integrity sha512-wDGW4IHKoOr9YuJgy7uYuKWrDrSpsUSDHLZnWQYM9fN7D5EpSmYHjFruUpKWVyxLpD/Wh0rW8hYZwdjJIQUQCQ== + dependencies: + "@docusaurus/react-loadable" "5.5.2" + "@docusaurus/types" "2.2.0" + "@types/history" "^4.7.11" + "@types/react" "*" + "@types/react-router-config" "*" + "@types/react-router-dom" "*" + react-helmet-async "*" + react-loadable "npm:@docusaurus/react-loadable@5.5.2" + +"@docusaurus/plugin-content-blog@2.2.0": + version "2.2.0" + resolved "https://registry.yarnpkg.com/@docusaurus/plugin-content-blog/-/plugin-content-blog-2.2.0.tgz#dc55982e76771f4e678ac10e26d10e1da2011dc1" + integrity sha512-0mWBinEh0a5J2+8ZJXJXbrCk1tSTNf7Nm4tYAl5h2/xx+PvH/Bnu0V+7mMljYm/1QlDYALNIIaT/JcoZQFUN3w== + dependencies: + "@docusaurus/core" "2.2.0" + "@docusaurus/logger" "2.2.0" + "@docusaurus/mdx-loader" "2.2.0" + "@docusaurus/types" "2.2.0" + "@docusaurus/utils" "2.2.0" + "@docusaurus/utils-common" "2.2.0" + "@docusaurus/utils-validation" "2.2.0" + cheerio "^1.0.0-rc.12" feed "^4.2.2" - fs-extra "^10.0.0" - lodash "^4.17.20" + fs-extra "^10.1.0" + lodash "^4.17.21" reading-time "^1.5.0" - remark-admonitions "^1.2.1" - tslib "^2.3.1" + tslib "^2.4.0" + unist-util-visit "^2.0.3" utility-types "^3.10.0" - webpack "^5.61.0" - -"@docusaurus/plugin-content-docs@2.0.0-beta.15": - version "2.0.0-beta.15" - resolved "https://registry.yarnpkg.com/@docusaurus/plugin-content-docs/-/plugin-content-docs-2.0.0-beta.15.tgz#9486bba8abd2a6284e749718bf56743d8e4446f1" - integrity sha512-HSwNZdUKz4rpJiGbFjl/OFhSleeZUSZ6E6lk98i4iL1A5u6fIm4CHsT53yp4UUOse+lFrePTFZsyqwMA4nZZYA== - dependencies: - "@docusaurus/core" "2.0.0-beta.15" - "@docusaurus/logger" "2.0.0-beta.15" - "@docusaurus/mdx-loader" "2.0.0-beta.15" - "@docusaurus/utils" "2.0.0-beta.15" - "@docusaurus/utils-validation" "2.0.0-beta.15" + webpack "^5.73.0" + +"@docusaurus/plugin-content-docs@2.2.0": + version "2.2.0" + resolved "https://registry.yarnpkg.com/@docusaurus/plugin-content-docs/-/plugin-content-docs-2.2.0.tgz#0fcb85226fcdb80dc1e2d4a36ef442a650dcc84d" + integrity sha512-BOazBR0XjzsHE+2K1wpNxz5QZmrJgmm3+0Re0EVPYFGW8qndCWGNtXW/0lGKhecVPML8yyFeAmnUCIs7xM2wPw== + dependencies: + "@docusaurus/core" "2.2.0" + "@docusaurus/logger" "2.2.0" + "@docusaurus/mdx-loader" "2.2.0" + "@docusaurus/module-type-aliases" "2.2.0" + "@docusaurus/types" "2.2.0" + "@docusaurus/utils" "2.2.0" + "@docusaurus/utils-validation" "2.2.0" + "@types/react-router-config" "^5.0.6" combine-promises "^1.1.0" - fs-extra "^10.0.0" - import-fresh "^3.2.2" - js-yaml "^4.0.0" - lodash "^4.17.20" - remark-admonitions "^1.2.1" - shelljs "^0.8.4" - tslib "^2.3.1" + fs-extra "^10.1.0" + import-fresh "^3.3.0" + js-yaml "^4.1.0" + lodash "^4.17.21" + tslib "^2.4.0" utility-types "^3.10.0" - webpack "^5.61.0" - -"@docusaurus/plugin-content-pages@2.0.0-beta.15": - version "2.0.0-beta.15" - resolved "https://registry.yarnpkg.com/@docusaurus/plugin-content-pages/-/plugin-content-pages-2.0.0-beta.15.tgz#e488f7dcdd45cd1d46e8c2c5ff5275327a6a3c65" - integrity sha512-N7YhW5RiOY6J228z4lOoP//qX0Q48cRtxDONZ/Ohd9C5OI2vS6TD8iQuDqOIYHxH+BshjNSsKvbJ+SMIQDwysg== - dependencies: - "@docusaurus/core" "2.0.0-beta.15" - "@docusaurus/mdx-loader" "2.0.0-beta.15" - "@docusaurus/utils" "2.0.0-beta.15" - "@docusaurus/utils-validation" "2.0.0-beta.15" - fs-extra "^10.0.0" - globby "^11.0.2" - remark-admonitions "^1.2.1" - tslib "^2.3.1" - webpack "^5.61.0" - -"@docusaurus/plugin-debug@2.0.0-beta.15": - version "2.0.0-beta.15" - resolved "https://registry.yarnpkg.com/@docusaurus/plugin-debug/-/plugin-debug-2.0.0-beta.15.tgz#b75d706d4f9fc4146f84015097bd837d1afb7c6b" - integrity sha512-Jth11jB/rVqPwCGdkVKSUWeXZPAr/NyPn+yeknTBk2LgQKBJ3YU5dNG0uyt0Ay+UYT01TkousPJkXhLuy4Qrsw== - dependencies: - "@docusaurus/core" "2.0.0-beta.15" - "@docusaurus/utils" "2.0.0-beta.15" - fs-extra "^10.0.0" + webpack "^5.73.0" + +"@docusaurus/plugin-content-pages@2.2.0": + version "2.2.0" + resolved "https://registry.yarnpkg.com/@docusaurus/plugin-content-pages/-/plugin-content-pages-2.2.0.tgz#e3f40408787bbe229545dd50595f87e1393bc3ae" + integrity sha512-+OTK3FQHk5WMvdelz8v19PbEbx+CNT6VSpx7nVOvMNs5yJCKvmqBJBQ2ZSxROxhVDYn+CZOlmyrC56NSXzHf6g== + dependencies: + "@docusaurus/core" "2.2.0" + "@docusaurus/mdx-loader" "2.2.0" + "@docusaurus/types" "2.2.0" + "@docusaurus/utils" "2.2.0" + "@docusaurus/utils-validation" "2.2.0" + fs-extra "^10.1.0" + tslib "^2.4.0" + webpack "^5.73.0" + +"@docusaurus/plugin-debug@2.2.0": + version "2.2.0" + resolved "https://registry.yarnpkg.com/@docusaurus/plugin-debug/-/plugin-debug-2.2.0.tgz#b38741d2c492f405fee01ee0ef2e0029cedb689a" + integrity sha512-p9vOep8+7OVl6r/NREEYxf4HMAjV8JMYJ7Bos5fCFO0Wyi9AZEo0sCTliRd7R8+dlJXZEgcngSdxAUo/Q+CJow== + dependencies: + "@docusaurus/core" "2.2.0" + "@docusaurus/types" "2.2.0" + "@docusaurus/utils" "2.2.0" + fs-extra "^10.1.0" react-json-view "^1.21.3" - tslib "^2.3.1" - -"@docusaurus/plugin-google-analytics@2.0.0-beta.15": - version "2.0.0-beta.15" - resolved "https://registry.yarnpkg.com/@docusaurus/plugin-google-analytics/-/plugin-google-analytics-2.0.0-beta.15.tgz#6ffebe76d9caac5383cfb78d2baa5883c9c2df6c" - integrity sha512-ELAnxNYiC2i7gfu/ViurNIdm1/DdnbEfVDmpffS9niQhOREM1U3jpxkz/ff1GIC6heOLyHTtini/CZBDoroVGw== - dependencies: - "@docusaurus/core" "2.0.0-beta.15" - "@docusaurus/utils-validation" "2.0.0-beta.15" - tslib "^2.3.1" - -"@docusaurus/plugin-google-gtag@2.0.0-beta.15": - version "2.0.0-beta.15" - resolved "https://registry.yarnpkg.com/@docusaurus/plugin-google-gtag/-/plugin-google-gtag-2.0.0-beta.15.tgz#4db3330d302653e8541dc3cb86a4dbfef0cc96f8" - integrity sha512-E5Rm3+dN7i3A9V5uq5sl9xTNA3aXsLwTZEA2SpOkY571dCpd+sfVvz1lR+KRY9Fy6ZHk8PqrNImgCWfIerRuZQ== - dependencies: - "@docusaurus/core" "2.0.0-beta.15" - "@docusaurus/utils-validation" "2.0.0-beta.15" - tslib "^2.3.1" - -"@docusaurus/plugin-sitemap@2.0.0-beta.15", "@docusaurus/plugin-sitemap@^2.0.0-beta.15": - version "2.0.0-beta.15" - resolved "https://registry.yarnpkg.com/@docusaurus/plugin-sitemap/-/plugin-sitemap-2.0.0-beta.15.tgz#0cc083d9e76041897e81b4b82bcd0ccbfa65d6e5" - integrity sha512-PBjeQb2Qpe4uPdRefWL/eXCeYjrgNB/UArExYeUuP4wiY1dpw2unGNCvFUxv4hzJGmARoTLsnRkeYkUim809LQ== - dependencies: - "@docusaurus/core" "2.0.0-beta.15" - "@docusaurus/utils" "2.0.0-beta.15" - "@docusaurus/utils-common" "2.0.0-beta.15" - "@docusaurus/utils-validation" "2.0.0-beta.15" - fs-extra "^10.0.0" - sitemap "^7.0.0" - tslib "^2.3.1" + tslib "^2.4.0" + +"@docusaurus/plugin-google-analytics@2.2.0": + version "2.2.0" + resolved "https://registry.yarnpkg.com/@docusaurus/plugin-google-analytics/-/plugin-google-analytics-2.2.0.tgz#63c7137eff5a1208d2059fea04b5207c037d7954" + integrity sha512-+eZVVxVeEnV5nVQJdey9ZsfyEVMls6VyWTIj8SmX0k5EbqGvnIfET+J2pYEuKQnDIHxy+syRMoRM6AHXdHYGIg== + dependencies: + "@docusaurus/core" "2.2.0" + "@docusaurus/types" "2.2.0" + "@docusaurus/utils-validation" "2.2.0" + tslib "^2.4.0" + +"@docusaurus/plugin-google-gtag@2.2.0": + version "2.2.0" + resolved "https://registry.yarnpkg.com/@docusaurus/plugin-google-gtag/-/plugin-google-gtag-2.2.0.tgz#7b086d169ac5fe9a88aca10ab0fd2bf00c6c6b12" + integrity sha512-6SOgczP/dYdkqUMGTRqgxAS1eTp6MnJDAQMy8VCF1QKbWZmlkx4agHDexihqmYyCujTYHqDAhm1hV26EET54NQ== + dependencies: + "@docusaurus/core" "2.2.0" + "@docusaurus/types" "2.2.0" + "@docusaurus/utils-validation" "2.2.0" + tslib "^2.4.0" + +"@docusaurus/plugin-sitemap@2.2.0", "@docusaurus/plugin-sitemap@^2.0.0-beta.15": + version "2.2.0" + resolved "https://registry.yarnpkg.com/@docusaurus/plugin-sitemap/-/plugin-sitemap-2.2.0.tgz#876da60937886032d63143253d420db6a4b34773" + integrity sha512-0jAmyRDN/aI265CbWZNZuQpFqiZuo+5otk2MylU9iVrz/4J7gSc+ZJ9cy4EHrEsW7PV8s1w18hIEsmcA1YgkKg== + dependencies: + "@docusaurus/core" "2.2.0" + "@docusaurus/logger" "2.2.0" + "@docusaurus/types" "2.2.0" + "@docusaurus/utils" "2.2.0" + "@docusaurus/utils-common" "2.2.0" + "@docusaurus/utils-validation" "2.2.0" + fs-extra "^10.1.0" + sitemap "^7.1.1" + tslib "^2.4.0" "@docusaurus/preset-classic@^2.0.0-beta.15": - version "2.0.0-beta.15" - resolved "https://registry.yarnpkg.com/@docusaurus/preset-classic/-/preset-classic-2.0.0-beta.15.tgz#13d2f3c4fa7c055af35541ae5e93453450efb208" - integrity sha512-3NZIXWTAzk+kOgiB8uAbD+FZv3VFR1qkU6+TW24DRenjRnXof3CkRuldhI1QI0hILm1fuJ319QRkakV8FFtXyA== - dependencies: - "@docusaurus/core" "2.0.0-beta.15" - "@docusaurus/plugin-content-blog" "2.0.0-beta.15" - "@docusaurus/plugin-content-docs" "2.0.0-beta.15" - "@docusaurus/plugin-content-pages" "2.0.0-beta.15" - "@docusaurus/plugin-debug" "2.0.0-beta.15" - "@docusaurus/plugin-google-analytics" "2.0.0-beta.15" - "@docusaurus/plugin-google-gtag" "2.0.0-beta.15" - "@docusaurus/plugin-sitemap" "2.0.0-beta.15" - "@docusaurus/theme-classic" "2.0.0-beta.15" - "@docusaurus/theme-common" "2.0.0-beta.15" - "@docusaurus/theme-search-algolia" "2.0.0-beta.15" + version "2.2.0" + resolved "https://registry.yarnpkg.com/@docusaurus/preset-classic/-/preset-classic-2.2.0.tgz#bece5a043eeb74430f7c6c7510000b9c43669eb7" + integrity sha512-yKIWPGNx7BT8v2wjFIWvYrS+nvN04W+UameSFf8lEiJk6pss0kL6SG2MRvyULiI3BDxH+tj6qe02ncpSPGwumg== + dependencies: + "@docusaurus/core" "2.2.0" + "@docusaurus/plugin-content-blog" "2.2.0" + "@docusaurus/plugin-content-docs" "2.2.0" + "@docusaurus/plugin-content-pages" "2.2.0" + "@docusaurus/plugin-debug" "2.2.0" + "@docusaurus/plugin-google-analytics" "2.2.0" + "@docusaurus/plugin-google-gtag" "2.2.0" + "@docusaurus/plugin-sitemap" "2.2.0" + "@docusaurus/theme-classic" "2.2.0" + "@docusaurus/theme-common" "2.2.0" + "@docusaurus/theme-search-algolia" "2.2.0" + "@docusaurus/types" "2.2.0" "@docusaurus/react-loadable@5.5.2", "react-loadable@npm:@docusaurus/react-loadable@5.5.2": version "5.5.2" @@ -1419,115 +1465,144 @@ "@types/react" "*" prop-types "^15.6.2" -"@docusaurus/theme-classic@2.0.0-beta.15": - version "2.0.0-beta.15" - resolved "https://registry.yarnpkg.com/@docusaurus/theme-classic/-/theme-classic-2.0.0-beta.15.tgz#35d04232f2d5fcb2007675339b0e6d0e8681be95" - integrity sha512-WwNRcQvMtQ7KDhOEHFKFHxXCdoZwLg66hT3vhqNIFMfGQuPzOP91MX5LUSo1QWHhlrD3H3Og+r7Ik/fy2bf5lQ== - dependencies: - "@docusaurus/core" "2.0.0-beta.15" - "@docusaurus/plugin-content-blog" "2.0.0-beta.15" - "@docusaurus/plugin-content-docs" "2.0.0-beta.15" - "@docusaurus/plugin-content-pages" "2.0.0-beta.15" - "@docusaurus/theme-common" "2.0.0-beta.15" - "@docusaurus/theme-translations" "2.0.0-beta.15" - "@docusaurus/utils" "2.0.0-beta.15" - "@docusaurus/utils-common" "2.0.0-beta.15" - "@docusaurus/utils-validation" "2.0.0-beta.15" - "@mdx-js/react" "^1.6.21" - clsx "^1.1.1" +"@docusaurus/theme-classic@2.2.0": + version "2.2.0" + resolved "https://registry.yarnpkg.com/@docusaurus/theme-classic/-/theme-classic-2.2.0.tgz#a048bb1bc077dee74b28bec25f4b84b481863742" + integrity sha512-kjbg/qJPwZ6H1CU/i9d4l/LcFgnuzeiGgMQlt6yPqKo0SOJIBMPuz7Rnu3r/WWbZFPi//o8acclacOzmXdUUEg== + dependencies: + "@docusaurus/core" "2.2.0" + "@docusaurus/mdx-loader" "2.2.0" + "@docusaurus/module-type-aliases" "2.2.0" + "@docusaurus/plugin-content-blog" "2.2.0" + "@docusaurus/plugin-content-docs" "2.2.0" + "@docusaurus/plugin-content-pages" "2.2.0" + "@docusaurus/theme-common" "2.2.0" + "@docusaurus/theme-translations" "2.2.0" + "@docusaurus/types" "2.2.0" + "@docusaurus/utils" "2.2.0" + "@docusaurus/utils-common" "2.2.0" + "@docusaurus/utils-validation" "2.2.0" + "@mdx-js/react" "^1.6.22" + clsx "^1.2.1" copy-text-to-clipboard "^3.0.1" - infima "0.2.0-alpha.37" - lodash "^4.17.20" - postcss "^8.3.7" - prism-react-renderer "^1.2.1" - prismjs "^1.23.0" - react-router-dom "^5.2.0" - rtlcss "^3.3.0" - -"@docusaurus/theme-common@2.0.0-beta.15": - version "2.0.0-beta.15" - resolved "https://registry.yarnpkg.com/@docusaurus/theme-common/-/theme-common-2.0.0-beta.15.tgz#5bd338d483e2c19d6d74d133572988241518398a" - integrity sha512-+pvarmzcyECE4nWxw+dCMKRIoes0NegrRuM9+nRsUrS/E5ywsF539kpupKIEqaMjq6AuM0CJtDoHxHHPNe0KaQ== - dependencies: - "@docusaurus/plugin-content-blog" "2.0.0-beta.15" - "@docusaurus/plugin-content-docs" "2.0.0-beta.15" - "@docusaurus/plugin-content-pages" "2.0.0-beta.15" - clsx "^1.1.1" + infima "0.2.0-alpha.42" + lodash "^4.17.21" + nprogress "^0.2.0" + postcss "^8.4.14" + prism-react-renderer "^1.3.5" + prismjs "^1.28.0" + react-router-dom "^5.3.3" + rtlcss "^3.5.0" + tslib "^2.4.0" + utility-types "^3.10.0" + +"@docusaurus/theme-common@2.2.0": + version "2.2.0" + resolved "https://registry.yarnpkg.com/@docusaurus/theme-common/-/theme-common-2.2.0.tgz#2303498d80448aafdd588b597ce9d6f4cfa930e4" + integrity sha512-R8BnDjYoN90DCL75gP7qYQfSjyitXuP9TdzgsKDmSFPNyrdE3twtPNa2dIN+h+p/pr+PagfxwWbd6dn722A1Dw== + dependencies: + "@docusaurus/mdx-loader" "2.2.0" + "@docusaurus/module-type-aliases" "2.2.0" + "@docusaurus/plugin-content-blog" "2.2.0" + "@docusaurus/plugin-content-docs" "2.2.0" + "@docusaurus/plugin-content-pages" "2.2.0" + "@docusaurus/utils" "2.2.0" + "@types/history" "^4.7.11" + "@types/react" "*" + "@types/react-router-config" "*" + clsx "^1.2.1" parse-numeric-range "^1.3.0" - tslib "^2.3.1" + prism-react-renderer "^1.3.5" + tslib "^2.4.0" utility-types "^3.10.0" -"@docusaurus/theme-search-algolia@2.0.0-beta.15": - version "2.0.0-beta.15" - resolved "https://registry.yarnpkg.com/@docusaurus/theme-search-algolia/-/theme-search-algolia-2.0.0-beta.15.tgz#c3ad7fd8e27fcb3e072990031c08768c602cb9a4" - integrity sha512-XrrQKyjOPzmEuOcdsaAn1tzNJkNMA3PC86PwPZUaah0cYPpBGptcJYDlIW4VHIrCBfkQvhvmg/B3qKF6bMMi8g== - dependencies: - "@docsearch/react" "^3.0.0-alpha.39" - "@docusaurus/core" "2.0.0-beta.15" - "@docusaurus/logger" "2.0.0-beta.15" - "@docusaurus/theme-common" "2.0.0-beta.15" - "@docusaurus/theme-translations" "2.0.0-beta.15" - "@docusaurus/utils" "2.0.0-beta.15" - "@docusaurus/utils-validation" "2.0.0-beta.15" - algoliasearch "^4.10.5" - algoliasearch-helper "^3.5.5" - clsx "^1.1.1" +"@docusaurus/theme-search-algolia@2.2.0": + version "2.2.0" + resolved "https://registry.yarnpkg.com/@docusaurus/theme-search-algolia/-/theme-search-algolia-2.2.0.tgz#77fd9f7a600917e6024fe3ac7fb6cfdf2ce84737" + integrity sha512-2h38B0tqlxgR2FZ9LpAkGrpDWVdXZ7vltfmTdX+4RsDs3A7khiNsmZB+x/x6sA4+G2V2CvrsPMlsYBy5X+cY1w== + dependencies: + "@docsearch/react" "^3.1.1" + "@docusaurus/core" "2.2.0" + "@docusaurus/logger" "2.2.0" + "@docusaurus/plugin-content-docs" "2.2.0" + "@docusaurus/theme-common" "2.2.0" + "@docusaurus/theme-translations" "2.2.0" + "@docusaurus/utils" "2.2.0" + "@docusaurus/utils-validation" "2.2.0" + algoliasearch "^4.13.1" + algoliasearch-helper "^3.10.0" + clsx "^1.2.1" eta "^1.12.3" - lodash "^4.17.20" - tslib "^2.3.1" + fs-extra "^10.1.0" + lodash "^4.17.21" + tslib "^2.4.0" utility-types "^3.10.0" -"@docusaurus/theme-translations@2.0.0-beta.15": - version "2.0.0-beta.15" - resolved "https://registry.yarnpkg.com/@docusaurus/theme-translations/-/theme-translations-2.0.0-beta.15.tgz#658397ab4c0d7784043e3cec52cef7ae09d2fb59" - integrity sha512-Lu2JDsnZaB2BcJe8Hpq5nrbS7+7bd09jT08b9vztQyvzR8PgzsthnzlLN4ilOeamRIuYJKo1pUGm0EsQBOP6Nw== +"@docusaurus/theme-translations@2.2.0": + version "2.2.0" + resolved "https://registry.yarnpkg.com/@docusaurus/theme-translations/-/theme-translations-2.2.0.tgz#5fbd4693679806f80c26eeae1381e1f2c23d83e7" + integrity sha512-3T140AG11OjJrtKlY4pMZ5BzbGRDjNs2co5hJ6uYJG1bVWlhcaFGqkaZ5lCgKflaNHD7UHBHU9Ec5f69jTdd6w== + dependencies: + fs-extra "^10.1.0" + tslib "^2.4.0" + +"@docusaurus/types@2.2.0": + version "2.2.0" + resolved "https://registry.yarnpkg.com/@docusaurus/types/-/types-2.2.0.tgz#02c577a4041ab7d058a3c214ccb13647e21a9857" + integrity sha512-b6xxyoexfbRNRI8gjblzVOnLr4peCJhGbYGPpJ3LFqpi5nsFfoK4mmDLvWdeah0B7gmJeXabN7nQkFoqeSdmOw== dependencies: - fs-extra "^10.0.0" - tslib "^2.3.1" + "@types/history" "^4.7.11" + "@types/react" "*" + commander "^5.1.0" + joi "^17.6.0" + react-helmet-async "^1.3.0" + utility-types "^3.10.0" + webpack "^5.73.0" + webpack-merge "^5.8.0" -"@docusaurus/utils-common@2.0.0-beta.15": - version "2.0.0-beta.15" - resolved "https://registry.yarnpkg.com/@docusaurus/utils-common/-/utils-common-2.0.0-beta.15.tgz#5549b329fc750bd5e9f24952c9e3ff7cf1f63e08" - integrity sha512-kIGlSIvbE/oniUpUjI8GOkSpH8o4NXbYqAh9dqPn+TJ0KbEFY3fc80gzZQU+9SunCwJMJbIxIGevX9Ry+nackw== +"@docusaurus/utils-common@2.2.0": + version "2.2.0" + resolved "https://registry.yarnpkg.com/@docusaurus/utils-common/-/utils-common-2.2.0.tgz#a401c1b93a8697dd566baf6ac64f0fdff1641a78" + integrity sha512-qebnerHp+cyovdUseDQyYFvMW1n1nv61zGe5JJfoNQUnjKuApch3IVsz+/lZ9a38pId8kqehC1Ao2bW/s0ntDA== dependencies: - tslib "^2.3.1" + tslib "^2.4.0" -"@docusaurus/utils-validation@2.0.0-beta.15": - version "2.0.0-beta.15" - resolved "https://registry.yarnpkg.com/@docusaurus/utils-validation/-/utils-validation-2.0.0-beta.15.tgz#c664bc021194db9254eb45e6b48cb7c2af269041" - integrity sha512-1oOVBCkRrsTXSYrBTsMdnj3a/R56zrx11rjF4xo0+dmm8C01Xw4msFtc3uA7VLX0HQvgHsk8xPzU5GERNdsNpg== +"@docusaurus/utils-validation@2.2.0": + version "2.2.0" + resolved "https://registry.yarnpkg.com/@docusaurus/utils-validation/-/utils-validation-2.2.0.tgz#04d4d103137ad0145883971d3aa497f4a1315f25" + integrity sha512-I1hcsG3yoCkasOL5qQAYAfnmVoLei7apugT6m4crQjmDGxq+UkiRrq55UqmDDyZlac/6ax/JC0p+usZ6W4nVyg== dependencies: - "@docusaurus/logger" "2.0.0-beta.15" - "@docusaurus/utils" "2.0.0-beta.15" - joi "^17.4.2" - tslib "^2.3.1" + "@docusaurus/logger" "2.2.0" + "@docusaurus/utils" "2.2.0" + joi "^17.6.0" + js-yaml "^4.1.0" + tslib "^2.4.0" -"@docusaurus/utils@2.0.0-beta.15": - version "2.0.0-beta.15" - resolved "https://registry.yarnpkg.com/@docusaurus/utils/-/utils-2.0.0-beta.15.tgz#60868046700d5585cfa6ffc57c5f3fbed00b61fc" - integrity sha512-xkoPmFxCBkDqbZR4U3SE752OcXtWTGgZnc/pZWxItzb1IYRGNZHrzdIr7CnI7rppriuZzsyivDGiC4Ud9MWhkA== +"@docusaurus/utils@2.2.0": + version "2.2.0" + resolved "https://registry.yarnpkg.com/@docusaurus/utils/-/utils-2.2.0.tgz#3d6f9b7a69168d5c92d371bf21c556a4f50d1da6" + integrity sha512-oNk3cjvx7Tt1Lgh/aeZAmFpGV2pDr5nHKrBVx6hTkzGhrnMuQqLt6UPlQjdYQ3QHXwyF/ZtZMO1D5Pfi0lu7SA== dependencies: - "@docusaurus/logger" "2.0.0-beta.15" - "@mdx-js/runtime" "^1.6.22" - "@svgr/webpack" "^6.0.0" + "@docusaurus/logger" "2.2.0" + "@svgr/webpack" "^6.2.1" file-loader "^6.2.0" - fs-extra "^10.0.0" + fs-extra "^10.1.0" github-slugger "^1.4.0" - globby "^11.0.4" + globby "^11.1.0" gray-matter "^4.0.3" - js-yaml "^4.0.0" - lodash "^4.17.20" - micromatch "^4.0.4" - remark-mdx-remove-exports "^1.6.22" - remark-mdx-remove-imports "^1.6.22" + js-yaml "^4.1.0" + lodash "^4.17.21" + micromatch "^4.0.5" resolve-pathname "^3.0.0" - tslib "^2.3.1" + shelljs "^0.8.5" + tslib "^2.4.0" url-loader "^4.1.1" + webpack "^5.73.0" "@hapi/hoek@^9.0.0": - version "9.2.1" - resolved "https://registry.yarnpkg.com/@hapi/hoek/-/hoek-9.2.1.tgz#9551142a1980503752536b5050fd99f4a7f13b17" - integrity sha512-gfta+H8aziZsm8pZa0vj04KO6biEiisppNgA1kbJvFrrWu9Vm7eaUEy76DIxsuTaWvti5fkJVhllWc6ZTE+Mdw== + version "9.3.0" + resolved "https://registry.yarnpkg.com/@hapi/hoek/-/hoek-9.3.0.tgz#8368869dcb735be2e7f5cb7647de78e167a251fb" + integrity sha512-/c6rf4UJlmHlC9b5BaNvzAcFv7HZ2QHaV0D4/HNlBdvFnvQq8RI4kYdhyPCl7Xj+oWvTWQ8ujhqS53LIgAe6KQ== "@hapi/topo@^5.0.0": version "5.1.0" @@ -1536,7 +1611,79 @@ dependencies: "@hapi/hoek" "^9.0.0" -"@mdx-js/mdx@1.6.22", "@mdx-js/mdx@^1.6.21": +"@jest/schemas@^29.0.0": + version "29.0.0" + resolved "https://registry.yarnpkg.com/@jest/schemas/-/schemas-29.0.0.tgz#5f47f5994dd4ef067fb7b4188ceac45f77fe952a" + integrity sha512-3Ab5HgYIIAnS0HjqJHQYZS+zXc4tUmTmBH3z83ajI6afXp8X3ZtdLX+nXx+I7LNkJD7uN9LAVhgnjDgZa2z0kA== + dependencies: + "@sinclair/typebox" "^0.24.1" + +"@jest/types@^29.3.1": + version "29.3.1" + resolved "https://registry.yarnpkg.com/@jest/types/-/types-29.3.1.tgz#7c5a80777cb13e703aeec6788d044150341147e3" + integrity sha512-d0S0jmmTpjnhCmNpApgX3jrUZgZ22ivKJRvL2lli5hpCRoNnp1f85r2/wpKfXuYu8E7Jjh1hGfhPyup1NM5AmA== + dependencies: + "@jest/schemas" "^29.0.0" + "@types/istanbul-lib-coverage" "^2.0.0" + "@types/istanbul-reports" "^3.0.0" + "@types/node" "*" + "@types/yargs" "^17.0.8" + chalk "^4.0.0" + +"@jridgewell/gen-mapping@^0.1.0": + version "0.1.1" + resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz#e5d2e450306a9491e3bd77e323e38d7aff315996" + integrity sha512-sQXCasFk+U8lWYEe66WxRDOE9PjVz4vSM51fTu3Hw+ClTpUSQb718772vH3pyS5pShp6lvQM7SxgIDXXXmOX7w== + dependencies: + "@jridgewell/set-array" "^1.0.0" + "@jridgewell/sourcemap-codec" "^1.4.10" + +"@jridgewell/gen-mapping@^0.3.0", "@jridgewell/gen-mapping@^0.3.2": + version "0.3.2" + resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz#c1aedc61e853f2bb9f5dfe6d4442d3b565b253b9" + integrity sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A== + dependencies: + "@jridgewell/set-array" "^1.0.1" + "@jridgewell/sourcemap-codec" "^1.4.10" + "@jridgewell/trace-mapping" "^0.3.9" + +"@jridgewell/resolve-uri@3.1.0": + version "3.1.0" + resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz#2203b118c157721addfe69d47b70465463066d78" + integrity sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w== + +"@jridgewell/set-array@^1.0.0", "@jridgewell/set-array@^1.0.1": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.1.2.tgz#7c6cf998d6d20b914c0a55a91ae928ff25965e72" + integrity sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw== + +"@jridgewell/source-map@^0.3.2": + version "0.3.2" + resolved "https://registry.yarnpkg.com/@jridgewell/source-map/-/source-map-0.3.2.tgz#f45351aaed4527a298512ec72f81040c998580fb" + integrity sha512-m7O9o2uR8k2ObDysZYzdfhb08VuEml5oWGiosa1VdaPZ/A6QyPkAJuwN0Q1lhULOf6B7MtQmHENS743hWtCrgw== + dependencies: + "@jridgewell/gen-mapping" "^0.3.0" + "@jridgewell/trace-mapping" "^0.3.9" + +"@jridgewell/sourcemap-codec@1.4.14", "@jridgewell/sourcemap-codec@^1.4.10": + version "1.4.14" + resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz#add4c98d341472a289190b424efbdb096991bb24" + integrity sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw== + +"@jridgewell/trace-mapping@^0.3.14", "@jridgewell/trace-mapping@^0.3.9": + version "0.3.17" + resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.17.tgz#793041277af9073b0951a7fe0f0d8c4c98c36985" + integrity sha512-MCNzAp77qzKca9+W/+I0+sEpaUnZoeasnghNeVc41VZCEKaCH73Vq3BZZ/SzWIgrqE4H4ceI+p+b6C0mHf9T4g== + dependencies: + "@jridgewell/resolve-uri" "3.1.0" + "@jridgewell/sourcemap-codec" "1.4.14" + +"@leichtgewicht/ip-codec@^2.0.1": + version "2.0.4" + resolved "https://registry.yarnpkg.com/@leichtgewicht/ip-codec/-/ip-codec-2.0.4.tgz#b2ac626d6cb9c8718ab459166d4bb405b8ffa78b" + integrity sha512-Hcv+nVC0kZnQ3tD9GVu5xSMR4VVYOteQIr/hwFPVEvPdlXqgGEuRjiheChHgdM+JyqdgNcmzZOX/tnl0JOiI7A== + +"@mdx-js/mdx@^1.6.22": version "1.6.22" resolved "https://registry.yarnpkg.com/@mdx-js/mdx/-/mdx-1.6.22.tgz#8a723157bf90e78f17dc0f27995398e6c731f1ba" integrity sha512-AMxuLxPz2j5/6TpF/XSdKpQP1NlG0z11dFOlq+2IP/lSgl11GY8ji6S/rgsViN/L0BDvHvUMruRb7ub+24LUYA== @@ -1561,20 +1708,11 @@ unist-builder "2.0.3" unist-util-visit "2.0.3" -"@mdx-js/react@1.6.22", "@mdx-js/react@^1.6.21": +"@mdx-js/react@^1.6.21", "@mdx-js/react@^1.6.22": version "1.6.22" resolved "https://registry.yarnpkg.com/@mdx-js/react/-/react-1.6.22.tgz#ae09b4744fddc74714ee9f9d6f17a66e77c43573" integrity sha512-TDoPum4SHdfPiGSAaRBw7ECyI8VaHpK8GJugbJIJuqyh6kzw9ZLJZW3HGL3NNrJGxcAixUvqROm+YuQOo5eXtg== -"@mdx-js/runtime@^1.6.22": - version "1.6.22" - resolved "https://registry.yarnpkg.com/@mdx-js/runtime/-/runtime-1.6.22.tgz#3edd388bf68a519ffa1aaf9c446b548165102345" - integrity sha512-p17spaO2+55VLCuxXA3LVHC4phRx60NR2XMdZ+qgVU1lKvEX4y88dmFNOzGDCPLJ03IZyKrJ/rPWWRiBrd9JrQ== - dependencies: - "@mdx-js/mdx" "1.6.22" - "@mdx-js/react" "1.6.22" - buble-jsx-only "^0.19.8" - "@mdx-js/util@1.6.22": version "1.6.22" resolved "https://registry.yarnpkg.com/@mdx-js/util/-/util-1.6.22.tgz#219dfd89ae5b97a8801f015323ffa4b62f45718b" @@ -1607,9 +1745,9 @@ integrity sha512-a5Sab1C4/icpTZVzZc5Ghpz88yQtGOyNqYXcZgOssB2uuAr+wF/MvN6bgtW32q7HHrvBki+BsZ0OuNv6EV3K9g== "@sideway/address@^4.1.3": - version "4.1.3" - resolved "https://registry.yarnpkg.com/@sideway/address/-/address-4.1.3.tgz#d93cce5d45c5daec92ad76db492cc2ee3c64ab27" - integrity sha512-8ncEUtmnTsMmL7z1YPB47kPUq7LpKWJNFPsRzHiIajGC5uXlWGn+AmkYPcHNl8S4tcEGx+cnORnNYaw2wvL+LQ== + version "4.1.4" + resolved "https://registry.yarnpkg.com/@sideway/address/-/address-4.1.4.tgz#03dccebc6ea47fdc226f7d3d1ad512955d4783f0" + integrity sha512-7vwq+rOHVWjyXxVlR76Agnvhy8I9rpzjosTESvmhNeXOXdZZB15Fl+TI9x1SiHZH5Jv2wTGduSxFDIaq0m3DUw== dependencies: "@hapi/hoek" "^9.0.0" @@ -1623,125 +1761,130 @@ resolved "https://registry.yarnpkg.com/@sideway/pinpoint/-/pinpoint-2.0.0.tgz#cff8ffadc372ad29fd3f78277aeb29e632cc70df" integrity sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ== +"@sinclair/typebox@^0.24.1": + version "0.24.51" + resolved "https://registry.yarnpkg.com/@sinclair/typebox/-/typebox-0.24.51.tgz#645f33fe4e02defe26f2f5c0410e1c094eac7f5f" + integrity sha512-1P1OROm/rdubP5aFDSZQILU0vrLCJ4fvHt6EoqHEM+2D/G5MK3bIaymUKLit8Js9gbns5UyJnkP/TZROLw4tUA== + "@sindresorhus/is@^0.14.0": version "0.14.0" resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-0.14.0.tgz#9fb3a3cf3132328151f353de4632e01e52102bea" integrity sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ== -"@slorber/static-site-generator-webpack-plugin@^4.0.0": - version "4.0.1" - resolved "https://registry.yarnpkg.com/@slorber/static-site-generator-webpack-plugin/-/static-site-generator-webpack-plugin-4.0.1.tgz#0c8852146441aaa683693deaa5aee2f991d94841" - integrity sha512-PSv4RIVO1Y3kvHxjvqeVisk3E9XFoO04uwYBDWe217MFqKspplYswTuKLiJu0aLORQWzuQjfVsSlLPojwfYsLw== +"@slorber/static-site-generator-webpack-plugin@^4.0.7": + version "4.0.7" + resolved "https://registry.yarnpkg.com/@slorber/static-site-generator-webpack-plugin/-/static-site-generator-webpack-plugin-4.0.7.tgz#fc1678bddefab014e2145cbe25b3ce4e1cfc36f3" + integrity sha512-Ug7x6z5lwrz0WqdnNFOMYrDQNTPAprvHLSh6+/fmml3qUiz6l5eq+2MzLKWtn/q5K5NpSiFsZTP/fck/3vjSxA== dependencies: - bluebird "^3.7.1" - cheerio "^0.22.0" - eval "^0.1.4" - url "^0.11.0" - webpack-sources "^1.4.3" + eval "^0.1.8" + p-map "^4.0.0" + webpack-sources "^3.2.2" -"@svgr/babel-plugin-add-jsx-attribute@^6.0.0": - version "6.0.0" - resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-add-jsx-attribute/-/babel-plugin-add-jsx-attribute-6.0.0.tgz#bd6d1ff32a31b82b601e73672a789cc41e84fe18" - integrity sha512-MdPdhdWLtQsjd29Wa4pABdhWbaRMACdM1h31BY+c6FghTZqNGT7pEYdBoaGeKtdTOBC/XNFQaKVj+r/Ei2ryWA== +"@svgr/babel-plugin-add-jsx-attribute@^6.5.1": + version "6.5.1" + resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-add-jsx-attribute/-/babel-plugin-add-jsx-attribute-6.5.1.tgz#74a5d648bd0347bda99d82409d87b8ca80b9a1ba" + integrity sha512-9PYGcXrAxitycIjRmZB+Q0JaN07GZIWaTBIGQzfaZv+qr1n8X1XUEJ5rZ/vx6OVD9RRYlrNnXWExQXcmZeD/BQ== -"@svgr/babel-plugin-remove-jsx-attribute@^6.0.0": - version "6.0.0" - resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-remove-jsx-attribute/-/babel-plugin-remove-jsx-attribute-6.0.0.tgz#58654908beebfa069681a83332544b17e5237e89" - integrity sha512-aVdtfx9jlaaxc3unA6l+M9YRnKIZjOhQPthLKqmTXC8UVkBLDRGwPKo+r8n3VZN8B34+yVajzPTZ+ptTSuZZCw== +"@svgr/babel-plugin-remove-jsx-attribute@*": + version "6.5.0" + resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-remove-jsx-attribute/-/babel-plugin-remove-jsx-attribute-6.5.0.tgz#652bfd4ed0a0699843585cda96faeb09d6e1306e" + integrity sha512-8zYdkym7qNyfXpWvu4yq46k41pyNM9SOstoWhKlm+IfdCE1DdnRKeMUPsWIEO/DEkaWxJ8T9esNdG3QwQ93jBA== -"@svgr/babel-plugin-remove-jsx-empty-expression@^6.0.0": - version "6.0.0" - resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-remove-jsx-empty-expression/-/babel-plugin-remove-jsx-empty-expression-6.0.0.tgz#d06dd6e8a8f603f92f9979bb9990a1f85a4f57ba" - integrity sha512-Ccj42ApsePD451AZJJf1QzTD1B/BOU392URJTeXFxSK709i0KUsGtbwyiqsKu7vsYxpTM0IA5clAKDyf9RCZyA== +"@svgr/babel-plugin-remove-jsx-empty-expression@*": + version "6.5.0" + resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-remove-jsx-empty-expression/-/babel-plugin-remove-jsx-empty-expression-6.5.0.tgz#4b78994ab7d39032c729903fc2dd5c0fa4565cb8" + integrity sha512-NFdxMq3xA42Kb1UbzCVxplUc0iqSyM9X8kopImvFnB+uSDdzIHOdbs1op8ofAvVRtbg4oZiyRl3fTYeKcOe9Iw== -"@svgr/babel-plugin-replace-jsx-attribute-value@^6.0.0": - version "6.0.0" - resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-replace-jsx-attribute-value/-/babel-plugin-replace-jsx-attribute-value-6.0.0.tgz#0b85837577b02c31c09c758a12932820f5245cee" - integrity sha512-88V26WGyt1Sfd1emBYmBJRWMmgarrExpKNVmI9vVozha4kqs6FzQJ/Kp5+EYli1apgX44518/0+t9+NU36lThQ== +"@svgr/babel-plugin-replace-jsx-attribute-value@^6.5.1": + version "6.5.1" + resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-replace-jsx-attribute-value/-/babel-plugin-replace-jsx-attribute-value-6.5.1.tgz#fb9d22ea26d2bc5e0a44b763d4c46d5d3f596c60" + integrity sha512-8DPaVVE3fd5JKuIC29dqyMB54sA6mfgki2H2+swh+zNJoynC8pMPzOkidqHOSc6Wj032fhl8Z0TVn1GiPpAiJg== -"@svgr/babel-plugin-svg-dynamic-title@^6.0.0": - version "6.0.0" - resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-svg-dynamic-title/-/babel-plugin-svg-dynamic-title-6.0.0.tgz#28236ec26f7ab9d486a487d36ae52d58ba15676f" - integrity sha512-F7YXNLfGze+xv0KMQxrl2vkNbI9kzT9oDK55/kUuymh1ACyXkMV+VZWX1zEhSTfEKh7VkHVZGmVtHg8eTZ6PRg== +"@svgr/babel-plugin-svg-dynamic-title@^6.5.1": + version "6.5.1" + resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-svg-dynamic-title/-/babel-plugin-svg-dynamic-title-6.5.1.tgz#01b2024a2b53ffaa5efceaa0bf3e1d5a4c520ce4" + integrity sha512-FwOEi0Il72iAzlkaHrlemVurgSQRDFbk0OC8dSvD5fSBPHltNh7JtLsxmZUhjYBZo2PpcU/RJvvi6Q0l7O7ogw== -"@svgr/babel-plugin-svg-em-dimensions@^6.0.0": - version "6.0.0" - resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-svg-em-dimensions/-/babel-plugin-svg-em-dimensions-6.0.0.tgz#40267c5dea1b43c4f83a0eb6169e08b43d8bafce" - integrity sha512-+rghFXxdIqJNLQK08kwPBD3Z22/0b2tEZ9lKiL/yTfuyj1wW8HUXu4bo/XkogATIYuXSghVQOOCwURXzHGKyZA== +"@svgr/babel-plugin-svg-em-dimensions@^6.5.1": + version "6.5.1" + resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-svg-em-dimensions/-/babel-plugin-svg-em-dimensions-6.5.1.tgz#dd3fa9f5b24eb4f93bcf121c3d40ff5facecb217" + integrity sha512-gWGsiwjb4tw+ITOJ86ndY/DZZ6cuXMNE/SjcDRg+HLuCmwpcjOktwRF9WgAiycTqJD/QXqL2f8IzE2Rzh7aVXA== -"@svgr/babel-plugin-transform-react-native-svg@^6.0.0": - version "6.0.0" - resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-transform-react-native-svg/-/babel-plugin-transform-react-native-svg-6.0.0.tgz#eb688d0a5f539e34d268d8a516e81f5d7fede7c9" - integrity sha512-VaphyHZ+xIKv5v0K0HCzyfAaLhPGJXSk2HkpYfXIOKb7DjLBv0soHDxNv6X0vr2titsxE7klb++u7iOf7TSrFQ== +"@svgr/babel-plugin-transform-react-native-svg@^6.5.1": + version "6.5.1" + resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-transform-react-native-svg/-/babel-plugin-transform-react-native-svg-6.5.1.tgz#1d8e945a03df65b601551097d8f5e34351d3d305" + integrity sha512-2jT3nTayyYP7kI6aGutkyfJ7UMGtuguD72OjeGLwVNyfPRBD8zQthlvL+fAbAKk5n9ZNcvFkp/b1lZ7VsYqVJg== -"@svgr/babel-plugin-transform-svg-component@^6.2.0": - version "6.2.0" - resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-transform-svg-component/-/babel-plugin-transform-svg-component-6.2.0.tgz#7ba61d9fc1fb42b0ba1a04e4630019fa7e993c4f" - integrity sha512-bhYIpsORb++wpsp91fymbFkf09Z/YEKR0DnFjxvN+8JHeCUD2unnh18jIMKnDJTWtvpTaGYPXELVe4OOzFI0xg== +"@svgr/babel-plugin-transform-svg-component@^6.5.1": + version "6.5.1" + resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-transform-svg-component/-/babel-plugin-transform-svg-component-6.5.1.tgz#48620b9e590e25ff95a80f811544218d27f8a250" + integrity sha512-a1p6LF5Jt33O3rZoVRBqdxL350oge54iZWHNI6LJB5tQ7EelvD/Mb1mfBiZNAan0dt4i3VArkFRjA4iObuNykQ== -"@svgr/babel-preset@^6.2.0": - version "6.2.0" - resolved "https://registry.yarnpkg.com/@svgr/babel-preset/-/babel-preset-6.2.0.tgz#1d3ad8c7664253a4be8e4a0f0e6872f30d8af627" - integrity sha512-4WQNY0J71JIaL03DRn0vLiz87JXx0b9dYm2aA8XHlQJQoixMl4r/soYHm8dsaJZ3jWtkCiOYy48dp9izvXhDkQ== - dependencies: - "@svgr/babel-plugin-add-jsx-attribute" "^6.0.0" - "@svgr/babel-plugin-remove-jsx-attribute" "^6.0.0" - "@svgr/babel-plugin-remove-jsx-empty-expression" "^6.0.0" - "@svgr/babel-plugin-replace-jsx-attribute-value" "^6.0.0" - "@svgr/babel-plugin-svg-dynamic-title" "^6.0.0" - "@svgr/babel-plugin-svg-em-dimensions" "^6.0.0" - "@svgr/babel-plugin-transform-react-native-svg" "^6.0.0" - "@svgr/babel-plugin-transform-svg-component" "^6.2.0" - -"@svgr/core@^6.2.0": - version "6.2.0" - resolved "https://registry.yarnpkg.com/@svgr/core/-/core-6.2.0.tgz#187a7930695635382c1ab42f476a1d4d45a65994" - integrity sha512-n5PrYAPoTpWGykqa8U05/TVTHOrVR/TxrUJ5EWHP9Db6vR3qnqzwAVLiFT1+slA7zQoJTXafQb+akwThf9SxGw== +"@svgr/babel-preset@^6.5.1": + version "6.5.1" + resolved "https://registry.yarnpkg.com/@svgr/babel-preset/-/babel-preset-6.5.1.tgz#b90de7979c8843c5c580c7e2ec71f024b49eb828" + integrity sha512-6127fvO/FF2oi5EzSQOAjo1LE3OtNVh11R+/8FXa+mHx1ptAaS4cknIjnUA7e6j6fwGGJ17NzaTJFUwOV2zwCw== + dependencies: + "@svgr/babel-plugin-add-jsx-attribute" "^6.5.1" + "@svgr/babel-plugin-remove-jsx-attribute" "*" + "@svgr/babel-plugin-remove-jsx-empty-expression" "*" + "@svgr/babel-plugin-replace-jsx-attribute-value" "^6.5.1" + "@svgr/babel-plugin-svg-dynamic-title" "^6.5.1" + "@svgr/babel-plugin-svg-em-dimensions" "^6.5.1" + "@svgr/babel-plugin-transform-react-native-svg" "^6.5.1" + "@svgr/babel-plugin-transform-svg-component" "^6.5.1" + +"@svgr/core@^6.5.1": + version "6.5.1" + resolved "https://registry.yarnpkg.com/@svgr/core/-/core-6.5.1.tgz#d3e8aa9dbe3fbd747f9ee4282c1c77a27410488a" + integrity sha512-/xdLSWxK5QkqG524ONSjvg3V/FkNyCv538OIBdQqPNaAta3AsXj/Bd2FbvR87yMbXO2hFSWiAe/Q6IkVPDw+mw== dependencies: - "@svgr/plugin-jsx" "^6.2.0" + "@babel/core" "^7.19.6" + "@svgr/babel-preset" "^6.5.1" + "@svgr/plugin-jsx" "^6.5.1" camelcase "^6.2.0" cosmiconfig "^7.0.1" -"@svgr/hast-util-to-babel-ast@^6.0.0": - version "6.0.0" - resolved "https://registry.yarnpkg.com/@svgr/hast-util-to-babel-ast/-/hast-util-to-babel-ast-6.0.0.tgz#423329ad866b6c169009cc82b5e28ffee80c857c" - integrity sha512-S+TxtCdDyRGafH1VG1t/uPZ87aOYOHzWL8kqz4FoSZcIbzWA6rnOmjNViNiDzqmEpzp2PW5o5mZfvC9DiVZhTQ== +"@svgr/hast-util-to-babel-ast@^6.5.1": + version "6.5.1" + resolved "https://registry.yarnpkg.com/@svgr/hast-util-to-babel-ast/-/hast-util-to-babel-ast-6.5.1.tgz#81800bd09b5bcdb968bf6ee7c863d2288fdb80d2" + integrity sha512-1hnUxxjd83EAxbL4a0JDJoD3Dao3hmjvyvyEV8PzWmLK3B9m9NPlW7GKjFyoWE8nM7HnXzPcmmSyOW8yOddSXw== dependencies: - "@babel/types" "^7.15.6" - entities "^3.0.1" + "@babel/types" "^7.20.0" + entities "^4.4.0" -"@svgr/plugin-jsx@^6.2.0": - version "6.2.0" - resolved "https://registry.yarnpkg.com/@svgr/plugin-jsx/-/plugin-jsx-6.2.0.tgz#5e41a75b12b34cb66509e63e535606161770ff42" - integrity sha512-QJDEe7K5Hkd4Eewu4pcjiOKTCtjB47Ol6lDLXVhf+jEewi+EKJAaAmM+bNixfW6LSNEg8RwOYQN3GZcprqKfHw== +"@svgr/plugin-jsx@^6.5.1": + version "6.5.1" + resolved "https://registry.yarnpkg.com/@svgr/plugin-jsx/-/plugin-jsx-6.5.1.tgz#0e30d1878e771ca753c94e69581c7971542a7072" + integrity sha512-+UdQxI3jgtSjCykNSlEMuy1jSRQlGC7pqBCPvkG/2dATdWo082zHTTK3uhnAju2/6XpE6B5mZ3z4Z8Ns01S8Gw== dependencies: - "@babel/core" "^7.15.5" - "@svgr/babel-preset" "^6.2.0" - "@svgr/hast-util-to-babel-ast" "^6.0.0" - svg-parser "^2.0.2" + "@babel/core" "^7.19.6" + "@svgr/babel-preset" "^6.5.1" + "@svgr/hast-util-to-babel-ast" "^6.5.1" + svg-parser "^2.0.4" -"@svgr/plugin-svgo@^6.2.0": - version "6.2.0" - resolved "https://registry.yarnpkg.com/@svgr/plugin-svgo/-/plugin-svgo-6.2.0.tgz#4cbe6a33ccccdcae4e3b63ded64cc1cbe1faf48c" - integrity sha512-oDdMQONKOJEbuKwuy4Np6VdV6qoaLLvoY86hjvQEgU82Vx1MSWRyYms6Sl0f+NtqxLI/rDVufATbP/ev996k3Q== +"@svgr/plugin-svgo@^6.5.1": + version "6.5.1" + resolved "https://registry.yarnpkg.com/@svgr/plugin-svgo/-/plugin-svgo-6.5.1.tgz#0f91910e988fc0b842f88e0960c2862e022abe84" + integrity sha512-omvZKf8ixP9z6GWgwbtmP9qQMPX4ODXi+wzbVZgomNFsUIlHA1sf4fThdwTWSsZGgvGAG6yE+b/F5gWUkcZ/iQ== dependencies: cosmiconfig "^7.0.1" deepmerge "^4.2.2" - svgo "^2.5.0" + svgo "^2.8.0" -"@svgr/webpack@^6.0.0": - version "6.2.0" - resolved "https://registry.yarnpkg.com/@svgr/webpack/-/webpack-6.2.0.tgz#00fafd32e1d59add7b554c40aa2e97e83f975686" - integrity sha512-KlLdGe93A8GDs19g8kjEmHwArgMAP6cUfegr2Nx+yDAYY32IPtjzm3SoqNP+I+cnOF1CToJu1clWTPEmdd8dXg== - dependencies: - "@babel/core" "^7.15.5" - "@babel/plugin-transform-react-constant-elements" "^7.14.5" - "@babel/preset-env" "^7.15.6" - "@babel/preset-react" "^7.14.5" - "@babel/preset-typescript" "^7.15.0" - "@svgr/core" "^6.2.0" - "@svgr/plugin-jsx" "^6.2.0" - "@svgr/plugin-svgo" "^6.2.0" +"@svgr/webpack@^6.2.1": + version "6.5.1" + resolved "https://registry.yarnpkg.com/@svgr/webpack/-/webpack-6.5.1.tgz#ecf027814fc1cb2decc29dc92f39c3cf691e40e8" + integrity sha512-cQ/AsnBkXPkEK8cLbv4Dm7JGXq2XrumKnL1dRpJD9rIO2fTIlJI9a1uCciYG1F2aUsox/hJQyNGbt3soDxSRkA== + dependencies: + "@babel/core" "^7.19.6" + "@babel/plugin-transform-react-constant-elements" "^7.18.12" + "@babel/preset-env" "^7.19.4" + "@babel/preset-react" "^7.18.6" + "@babel/preset-typescript" "^7.18.6" + "@svgr/core" "^6.5.1" + "@svgr/plugin-jsx" "^6.5.1" + "@svgr/plugin-svgo" "^6.5.1" "@szmarczak/http-timer@^1.1.2": version "1.1.2" @@ -1790,40 +1933,45 @@ dependencies: "@types/node" "*" -"@types/eslint-scope@^3.7.0": - version "3.7.3" - resolved "https://registry.yarnpkg.com/@types/eslint-scope/-/eslint-scope-3.7.3.tgz#125b88504b61e3c8bc6f870882003253005c3224" - integrity sha512-PB3ldyrcnAicT35TWPs5IcwKD8S333HMaa2VVv4+wdvebJkjWuW/xESoB8IwRcog8HYVYamb1g/R31Qv5Bx03g== +"@types/eslint-scope@^3.7.3": + version "3.7.4" + resolved "https://registry.yarnpkg.com/@types/eslint-scope/-/eslint-scope-3.7.4.tgz#37fc1223f0786c39627068a12e94d6e6fc61de16" + integrity sha512-9K4zoImiZc3HlIp6AVUDE4CWYx22a+lhSZMYNpbjW04+YF0KWj4pJXnEMjdnFTiQibFFmElcsasJXDbdI/EPhA== dependencies: "@types/eslint" "*" "@types/estree" "*" "@types/eslint@*": - version "8.2.2" - resolved "https://registry.yarnpkg.com/@types/eslint/-/eslint-8.2.2.tgz#b64dbdb64b1957cfc8a698c68297fcf8983e94c7" - integrity sha512-nQxgB8/Sg+QKhnV8e0WzPpxjIGT3tuJDDzybkDi8ItE/IgTlHo07U0shaIjzhcvQxlq9SDRE42lsJ23uvEgJ2A== + version "8.4.10" + resolved "https://registry.yarnpkg.com/@types/eslint/-/eslint-8.4.10.tgz#19731b9685c19ed1552da7052b6f668ed7eb64bb" + integrity sha512-Sl/HOqN8NKPmhWo2VBEPm0nvHnu2LL3v9vKo8MEq0EtbJ4eVzGPl41VNPvn5E1i5poMk4/XD8UriLHpJvEP/Nw== dependencies: "@types/estree" "*" "@types/json-schema" "*" -"@types/estree@*", "@types/estree@^0.0.50": - version "0.0.50" - resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.50.tgz#1e0caa9364d3fccd2931c3ed96fdbeaa5d4cca83" - integrity sha512-C6N5s2ZFtuZRj54k2/zyRhNDjJwwcViAM3Nbm8zjBpbqAdZ00mr0CFxvSKeO8Y/e03WVFLpQMdHYVfUd6SB+Hw== +"@types/estree@*": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.0.tgz#5fb2e536c1ae9bf35366eed879e827fa59ca41c2" + integrity sha512-WulqXMDUTYAXCjZnk6JtIHPigp55cVtDgDrO2gHRwhyJto21+1zbVCtOYB2L1F9w4qCQ0rOGWBnBe0FNTiEJIQ== + +"@types/estree@^0.0.51": + version "0.0.51" + resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.51.tgz#cfd70924a25a3fd32b218e5e420e6897e1ac4f40" + integrity sha512-CuPgU6f3eT/XgKKPqKd/gLZV1Xmvf1a2R5POBOGQa6uv82xpls89HU5zKeVoyR8XzHd1RGNOlQlvUe3CFkjWNQ== "@types/express-serve-static-core@*", "@types/express-serve-static-core@^4.17.18": - version "4.17.28" - resolved "https://registry.yarnpkg.com/@types/express-serve-static-core/-/express-serve-static-core-4.17.28.tgz#c47def9f34ec81dc6328d0b1b5303d1ec98d86b8" - integrity sha512-P1BJAEAW3E2DJUlkgq4tOL3RyMunoWXqbSCygWo5ZIWTjUgN1YnaXWW4VWl/oc8vs/XoYibEGBKP0uZyF4AHig== + version "4.17.31" + resolved "https://registry.yarnpkg.com/@types/express-serve-static-core/-/express-serve-static-core-4.17.31.tgz#a1139efeab4e7323834bb0226e62ac019f474b2f" + integrity sha512-DxMhY+NAsTwMMFHBTtJFNp5qiHKJ7TeqOo23zVEM9alT1Ml27Q3xcTH0xwxn7Q0BbMcVEJOs/7aQtUWupUQN3Q== dependencies: "@types/node" "*" "@types/qs" "*" "@types/range-parser" "*" -"@types/express@*": - version "4.17.13" - resolved "https://registry.yarnpkg.com/@types/express/-/express-4.17.13.tgz#a76e2995728999bab51a33fabce1d705a3709034" - integrity sha512-6bSZTPaTIACxn48l50SR+axgrqm6qXFIxrdAKaG6PaJk3+zuUr35hBlgT7vOmJcum+OEaIBLtHV/qloEAFITeA== +"@types/express@*", "@types/express@^4.17.13": + version "4.17.14" + resolved "https://registry.yarnpkg.com/@types/express/-/express-4.17.14.tgz#143ea0557249bc1b3b54f15db4c81c3d4eb3569c" + integrity sha512-TEbt+vaPFQ+xpxFLFssxUDXj5cWCxZJjIcB7Yg0k0GMHGtgtQgpvx/MUQUeAkNbA9AAGrwkAsoeItdTgS7FMyg== dependencies: "@types/body-parser" "*" "@types/express-serve-static-core" "^4.17.18" @@ -1837,22 +1985,46 @@ dependencies: "@types/unist" "*" +"@types/history@^4.7.11": + version "4.7.11" + resolved "https://registry.yarnpkg.com/@types/history/-/history-4.7.11.tgz#56588b17ae8f50c53983a524fc3cc47437969d64" + integrity sha512-qjDJRrmvBMiTx+jyLxvLfJU7UznFuokDv4f3WRuriHKERccVpFU+8XMQUAbDzoiJCsmexxRExQeMwwCdamSKDA== + "@types/html-minifier-terser@^6.0.0": version "6.1.0" resolved "https://registry.yarnpkg.com/@types/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz#4fc33a00c1d0c16987b1a20cf92d20614c55ac35" integrity sha512-oh/6byDPnL1zeNXFrDXFLyZjkr1MsBG667IM792caf1L2UPOOMf65NFzjUH/ltyfwjAGfs1rsX1eftK0jC/KIg== -"@types/http-proxy@^1.17.5": - version "1.17.8" - resolved "https://registry.yarnpkg.com/@types/http-proxy/-/http-proxy-1.17.8.tgz#968c66903e7e42b483608030ee85800f22d03f55" - integrity sha512-5kPLG5BKpWYkw/LVOGWpiq3nEVqxiN32rTgI53Sk12/xHFQ2rG3ehI9IO+O3W2QoKeyB92dJkoka8SUm6BX1pA== +"@types/http-proxy@^1.17.8": + version "1.17.9" + resolved "https://registry.yarnpkg.com/@types/http-proxy/-/http-proxy-1.17.9.tgz#7f0e7931343761efde1e2bf48c40f02f3f75705a" + integrity sha512-QsbSjA/fSk7xB+UXlCT3wHBy5ai9wOcNDWwZAtud+jXhwOM3l+EYZh8Lng4+/6n8uar0J7xILzqftJdJ/Wdfkw== dependencies: "@types/node" "*" +"@types/istanbul-lib-coverage@*", "@types/istanbul-lib-coverage@^2.0.0": + version "2.0.4" + resolved "https://registry.yarnpkg.com/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz#8467d4b3c087805d63580480890791277ce35c44" + integrity sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g== + +"@types/istanbul-lib-report@*": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz#c14c24f18ea8190c118ee7562b7ff99a36552686" + integrity sha512-plGgXAPfVKFoYfa9NpYDAkseG+g6Jr294RqeqcqDixSbU34MZVJRi/P+7Y8GDpzkEwLaGZZOpKIEmeVZNtKsrg== + dependencies: + "@types/istanbul-lib-coverage" "*" + +"@types/istanbul-reports@^3.0.0": + version "3.0.1" + resolved "https://registry.yarnpkg.com/@types/istanbul-reports/-/istanbul-reports-3.0.1.tgz#9153fe98bba2bd565a63add9436d6f0d7f8468ff" + integrity sha512-c3mAZEuK0lvBp8tmuL74XRKn1+y2dcwOUpH7x4WrF6gk1GIgiluDRgMYQtw2OFcBvAJWlt6ASU3tSqxp0Uu0Aw== + dependencies: + "@types/istanbul-lib-report" "*" + "@types/json-schema@*", "@types/json-schema@^7.0.4", "@types/json-schema@^7.0.5", "@types/json-schema@^7.0.8", "@types/json-schema@^7.0.9": - version "7.0.9" - resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.9.tgz#97edc9037ea0c38585320b28964dde3b39e4660d" - integrity sha512-qcUXuemtEu+E5wZSJHNxUXeCZhAfXKQ41D+duX+VYPde7xyEVZci+/oXKJL13tnRs9lR2pr4fod59GT6/X1/yQ== + version "7.0.11" + resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.11.tgz#d421b6c527a3037f7c84433fd2c4229e016863d3" + integrity sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ== "@types/katex@^0.11.0": version "0.11.1" @@ -1871,15 +2043,20 @@ dependencies: "@types/unist" "*" -"@types/mime@^1": - version "1.3.2" - resolved "https://registry.yarnpkg.com/@types/mime/-/mime-1.3.2.tgz#93e25bf9ee75fe0fd80b594bc4feb0e862111b5a" - integrity sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw== +"@types/mime@*": + version "3.0.1" + resolved "https://registry.yarnpkg.com/@types/mime/-/mime-3.0.1.tgz#5f8f2bca0a5863cb69bc0b0acd88c96cb1d4ae10" + integrity sha512-Y4XFY5VJAuw0FgAqPNd6NNoV44jbq9Bz2L7Rh/J6jLTiHBSBJa9fxqQIvkIld4GsoDOcCbvzOUAbLPsSKKg+uA== -"@types/node@*", "@types/node@^17.0.5": - version "17.0.8" - resolved "https://registry.yarnpkg.com/@types/node/-/node-17.0.8.tgz#50d680c8a8a78fe30abe6906453b21ad8ab0ad7b" - integrity sha512-YofkM6fGv4gDJq78g4j0mMuGMkZVxZDgtU0JRdx6FgiJDG+0fY0GKVolOV8WqVmEhLCXkQRjwDdKyPxJp/uucg== +"@types/node@*": + version "18.11.9" + resolved "https://registry.yarnpkg.com/@types/node/-/node-18.11.9.tgz#02d013de7058cea16d36168ef2fc653464cfbad4" + integrity sha512-CRpX21/kGdzjOpFsZSkcrXMGIBWMGNIHXXBVFSH+ggkftxg+XYP20TESbh+zFvFj3EQOl5byk0HTRn1IL6hbqg== + +"@types/node@^17.0.5": + version "17.0.45" + resolved "https://registry.yarnpkg.com/@types/node/-/node-17.0.45.tgz#2c0fafd78705e7a18b7906b5201a522719dc5190" + integrity sha512-w+tIMs3rq2afQdsPJlODhoUEKzFP1ayaoyl1CcnwtIlsVe7K7bA1NGm4s3PraqTLlXnbIN84zuBlxBWo1u9BLw== "@types/parse-json@^4.0.0": version "4.0.0" @@ -1892,9 +2069,9 @@ integrity sha512-kUNnecmtkunAoQ3CnjmMkzNU/gtxG8guhi+Fk2U/kOpIKjIMKnXGp4IJCgQJrXSgMsWYimYG4TGjz/UzbGEBTw== "@types/prop-types@*": - version "15.7.4" - resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.4.tgz#fcf7205c25dff795ee79af1e30da2c9790808f11" - integrity sha512-rZ5drC/jWjrArrS8BR6SIr4cWpW09RNTYt9AMZo3Jwwif+iacXAqgVjm0B0Bv/S1jhDXKHqRVNCbACkJ89RAnQ== + version "15.7.5" + resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.5.tgz#5f19d2b85a98e9558036f6a3cacc8819420f05cf" + integrity sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w== "@types/qs@*": version "6.9.7" @@ -1906,19 +2083,45 @@ resolved "https://registry.yarnpkg.com/@types/range-parser/-/range-parser-1.2.4.tgz#cd667bcfdd025213aafb7ca5915a932590acdcdc" integrity sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw== +"@types/react-router-config@*", "@types/react-router-config@^5.0.6": + version "5.0.6" + resolved "https://registry.yarnpkg.com/@types/react-router-config/-/react-router-config-5.0.6.tgz#87c5c57e72d241db900d9734512c50ccec062451" + integrity sha512-db1mx37a1EJDf1XeX8jJN7R3PZABmJQXR8r28yUjVMFSjkmnQo6X6pOEEmNl+Tp2gYQOGPdYbFIipBtdElZ3Yg== + dependencies: + "@types/history" "^4.7.11" + "@types/react" "*" + "@types/react-router" "*" + +"@types/react-router-dom@*": + version "5.3.3" + resolved "https://registry.yarnpkg.com/@types/react-router-dom/-/react-router-dom-5.3.3.tgz#e9d6b4a66fcdbd651a5f106c2656a30088cc1e83" + integrity sha512-kpqnYK4wcdm5UaWI3fLcELopqLrHgLqNsdpHauzlQktfkHL3npOSwtj1Uz9oKBAzs7lFtVkV8j83voAz2D8fhw== + dependencies: + "@types/history" "^4.7.11" + "@types/react" "*" + "@types/react-router" "*" + +"@types/react-router@*": + version "5.1.19" + resolved "https://registry.yarnpkg.com/@types/react-router/-/react-router-5.1.19.tgz#9b404246fba7f91474d7008a3d48c17b6e075ad6" + integrity sha512-Fv/5kb2STAEMT3wHzdKQK2z8xKq38EDIGVrutYLmQVVLe+4orDFquU52hQrULnEHinMKv9FSA6lf9+uNT1ITtA== + dependencies: + "@types/history" "^4.7.11" + "@types/react" "*" + "@types/react@*": - version "17.0.38" - resolved "https://registry.yarnpkg.com/@types/react/-/react-17.0.38.tgz#f24249fefd89357d5fa71f739a686b8d7c7202bd" - integrity sha512-SI92X1IA+FMnP3qM5m4QReluXzhcmovhZnLNm3pyeQlooi02qI7sLiepEYqT678uNiyc25XfCqxREFpy3W7YhQ== + version "18.0.25" + resolved "https://registry.yarnpkg.com/@types/react/-/react-18.0.25.tgz#8b1dcd7e56fe7315535a4af25435e0bb55c8ae44" + integrity sha512-xD6c0KDT4m7n9uD4ZHi02lzskaiqcBxf4zi+tXZY98a04wvc0hi/TcCPC2FOESZi51Nd7tlUeOJY8RofL799/g== dependencies: "@types/prop-types" "*" "@types/scheduler" "*" csstype "^3.0.2" -"@types/retry@^0.12.0": - version "0.12.1" - resolved "https://registry.yarnpkg.com/@types/retry/-/retry-0.12.1.tgz#d8f1c0d0dc23afad6dc16a9e993a0865774b4065" - integrity sha512-xoDlM2S4ortawSWORYqsdU+2rxdh4LRW9ytc3zmT37RIKQh6IHyKwwtKhKis9ah8ol07DCkZxPt8BBvPjC6v4g== +"@types/retry@0.12.0": + version "0.12.0" + resolved "https://registry.yarnpkg.com/@types/retry/-/retry-0.12.0.tgz#2b35eccfcee7d38cd72ad99232fbd58bffb3c84d" + integrity sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA== "@types/sax@^1.2.1": version "1.2.4" @@ -1939,12 +2142,12 @@ dependencies: "@types/express" "*" -"@types/serve-static@*": - version "1.13.10" - resolved "https://registry.yarnpkg.com/@types/serve-static/-/serve-static-1.13.10.tgz#f5e0ce8797d2d7cc5ebeda48a52c96c4fa47a8d9" - integrity sha512-nCkHGI4w7ZgAdNkrEu0bv+4xNV/XDqW+DydknebMOQwkpDGx8G+HTlj7R7ABI8i8nKxVw0wtKPi1D+lPOkh4YQ== +"@types/serve-static@*", "@types/serve-static@^1.13.10": + version "1.15.0" + resolved "https://registry.yarnpkg.com/@types/serve-static/-/serve-static-1.15.0.tgz#c7930ff61afb334e121a9da780aac0d9b8f34155" + integrity sha512-z5xyF6uh8CbjAu9760KDKsH2FcDxZ2tFCsA4HIMWE6IkiYMXfVoa+4f9KX+FN0ZLsaMw1WNG2ETLA6N+/YA+cg== dependencies: - "@types/mime" "^1" + "@types/mime" "*" "@types/node" "*" "@types/sockjs@^0.3.33": @@ -1964,13 +2167,25 @@ resolved "https://registry.yarnpkg.com/@types/web/-/web-0.0.46.tgz#7f447e5eb3c511dbdc6f69e435f7ec4311d18b48" integrity sha512-ki0OmbjSdAEfvmy5AYWFpMkRsPW+6h4ibQ4tzk8SJsS9dkrrD3B/U1eVvdNNWxAzntjq6o2sjSia6UBCoPH+Yg== -"@types/ws@^8.2.2": - version "8.2.2" - resolved "https://registry.yarnpkg.com/@types/ws/-/ws-8.2.2.tgz#7c5be4decb19500ae6b3d563043cd407bf366c21" - integrity sha512-NOn5eIcgWLOo6qW8AcuLZ7G8PycXu0xTxxkS6Q18VWFxgPUSOwV0pBj2a/4viNZVu25i7RIB7GttdkAIUUXOOg== +"@types/ws@^8.5.1": + version "8.5.3" + resolved "https://registry.yarnpkg.com/@types/ws/-/ws-8.5.3.tgz#7d25a1ffbecd3c4f2d35068d0b283c037003274d" + integrity sha512-6YOoWjruKj1uLf3INHH7D3qTXwFfEsg1kf3c0uDdSBJwfa/llkwIjrAGV7j7mVgGNbzTQ3HiHKKDXl6bJPD97w== dependencies: "@types/node" "*" +"@types/yargs-parser@*": + version "21.0.0" + resolved "https://registry.yarnpkg.com/@types/yargs-parser/-/yargs-parser-21.0.0.tgz#0c60e537fa790f5f9472ed2776c2b71ec117351b" + integrity sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA== + +"@types/yargs@^17.0.8": + version "17.0.13" + resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-17.0.13.tgz#34cced675ca1b1d51fcf4d34c3c6f0fa142a5c76" + integrity sha512-9sWaruZk2JGxIQU+IhI1fhPYRcQ0UuTNuKuCW9bR5fp7qi2Llf7WDzNa17Cy7TKnh3cdxDOiyTu6gaLS0eDatg== + dependencies: + "@types/yargs-parser" "*" + "@webassemblyjs/ast@1.11.1": version "1.11.1" resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.11.1.tgz#2bfd767eae1a6996f432ff7e8d7fc75679c0b6a7" @@ -2102,28 +2317,18 @@ resolved "https://registry.yarnpkg.com/@xtuc/long/-/long-4.2.2.tgz#d291c6a4e97989b5c61d9acf396ae4fe133a718d" integrity sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ== -abab@^2.0.3, abab@^2.0.5: - version "2.0.5" - resolved "https://registry.yarnpkg.com/abab/-/abab-2.0.5.tgz#c0b678fb32d60fc1219c784d6a826fe385aeb79a" - integrity sha512-9IK9EadsbHo6jLWIpxpR6pL0sazTXV6+SQv25ZB+F7Bj9mJNaOc4nCRabwd5M/JwmUa8idz6Eci6eKfJryPs6Q== - -abbrev@1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" - integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q== +abab@^2.0.5, abab@^2.0.6: + version "2.0.6" + resolved "https://registry.yarnpkg.com/abab/-/abab-2.0.6.tgz#41b80f2c871d19686216b82309231cfd3cb3d291" + integrity sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA== -accepts@~1.3.4, accepts@~1.3.5, accepts@~1.3.7: - version "1.3.7" - resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.7.tgz#531bc726517a3b2b41f850021c6cc15eaab507cd" - integrity sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA== +accepts@~1.3.4, accepts@~1.3.5, accepts@~1.3.8: + version "1.3.8" + resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.8.tgz#0bf0be125b67014adcb0b0921e62db7bffe16b2e" + integrity sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw== dependencies: - mime-types "~2.1.24" - negotiator "0.6.2" - -acorn-dynamic-import@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/acorn-dynamic-import/-/acorn-dynamic-import-4.0.0.tgz#482210140582a36b83c3e342e1cfebcaa9240948" - integrity sha512-d3OEjQV4ROpoflsnUA8HozoIR504TFxNivYEUi6uwz0IYhBkTDXGuWlNdMtybRt3nqVx/L6XqMt0FxkXuWKZhw== + mime-types "~2.1.34" + negotiator "0.6.3" acorn-globals@^6.0.0: version "6.0.0" @@ -2138,11 +2343,6 @@ acorn-import-assertions@^1.7.6: resolved "https://registry.yarnpkg.com/acorn-import-assertions/-/acorn-import-assertions-1.8.0.tgz#ba2b5939ce62c238db6d93d81c9b111b29b855e9" integrity sha512-m7VZ3jwz4eK6A4Vtt8Ew1/mNbP24u0FhdyfA7fSvnJR6LMdfOYnmuIrrJAgrYfYJ10F/otaHTtrtrtmHdMNzEw== -acorn-jsx@^5.0.1: - version "5.3.2" - resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937" - integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ== - acorn-walk@^7.1.1: version "7.2.0" resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-7.2.0.tgz#0de889a601203909b0fbe07b8938dc21d2e967bc" @@ -2153,25 +2353,20 @@ acorn-walk@^8.0.0: resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-8.2.0.tgz#741210f2e2426454508853a2f44d0ab83b7f69c1" integrity sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA== -acorn@^6.1.1: - version "6.4.2" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.4.2.tgz#35866fd710528e92de10cf06016498e47e39e1e6" - integrity sha512-XtGIhXwF8YM8bJhGxG5kXgjkEuNGLTkoYqVE+KMR+aspr4KGYmKYg7yUe3KghyQ9yheNwLnjmzh/7+gfDBmHCQ== - acorn@^7.1.1: version "7.4.1" resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.4.1.tgz#feaed255973d2e77555b83dbc08851a6c63520fa" integrity sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A== -acorn@^8.0.4, acorn@^8.4.1, acorn@^8.5.0: - version "8.7.0" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.7.0.tgz#90951fde0f8f09df93549481e5fc141445b791cf" - integrity sha512-V/LGr1APy+PXIwKebEWrkZPwoeoF+w1jiOBUmuxuiUIaOHtob8Qc9BTrYo7VuI5fR8tqsy+buA2WFooR5olqvQ== +acorn@^8.0.4, acorn@^8.5.0, acorn@^8.7.1: + version "8.8.1" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.8.1.tgz#0a3f9cbecc4ec3bea6f0a80b66ae8dd2da250b73" + integrity sha512-7zFpHzhnqYKrkYdUjF1HI1bzd0VygEGX8lFk4k5zVMqHEoES+P+7TKI+EvLO9WVMJ8eekdO0aDEK044xTXwPPA== address@^1.0.1, address@^1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/address/-/address-1.1.2.tgz#bf1116c9c758c51b7a933d296b72c221ed9428b6" - integrity sha512-aT6camzM4xEA54YVJYSqxz1kv4IHnQZRtThJJHhUMRExaU5spC7jX5ugSwTaTgJliIgs4VhZOk7htClvQ/LmRA== + version "1.2.1" + resolved "https://registry.yarnpkg.com/address/-/address-1.2.1.tgz#25bb61095b7522d65b357baa11bc05492d4c8acd" + integrity sha512-B+6bi5D34+fDYENiH5qOlA0cV2rAGKuWZ9LeyUUehbXy8e0VS9e498yO0Jeeh+iM+6KbfudHTFjXw2MmJD4QRA== agent-base@6: version "6.0.2" @@ -2218,48 +2413,43 @@ ajv@^6.12.2, ajv@^6.12.4, ajv@^6.12.5: uri-js "^4.2.2" ajv@^8.0.0, ajv@^8.8.0: - version "8.8.2" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.8.2.tgz#01b4fef2007a28bf75f0b7fc009f62679de4abbb" - integrity sha512-x9VuX+R/jcFj1DHo/fCp99esgGDWiHENrKxaCENuCxpoMCmAt/COCGVDwA7kleEpEzJjDnvh3yGoOuLu0Dtllw== + version "8.11.2" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.11.2.tgz#aecb20b50607acf2569b6382167b65a96008bb78" + integrity sha512-E4bfmKAhGiSTvMfL1Myyycaub+cUEU2/IvpylXkUu7CHBkBj1f/ikdzbD7YQ6FKUbixDxeYvB/xY4fvyroDlQg== dependencies: fast-deep-equal "^3.1.1" json-schema-traverse "^1.0.0" require-from-string "^2.0.2" uri-js "^4.2.2" -algoliasearch-helper@^3.5.5: - version "3.7.0" - resolved "https://registry.yarnpkg.com/algoliasearch-helper/-/algoliasearch-helper-3.7.0.tgz#c0a0493df84d850360f664ad7a9d4fc78a94fd78" - integrity sha512-XJ3QfERBLfeVCyTVx80gon7r3/rgm/CE8Ha1H7cbablRe/X7SfYQ14g/eO+MhjVKIQp+gy9oC6G5ilmLwS1k6w== +algoliasearch-helper@^3.10.0: + version "3.11.1" + resolved "https://registry.yarnpkg.com/algoliasearch-helper/-/algoliasearch-helper-3.11.1.tgz#d83ab7f1a2a374440686ef7a144b3c288b01188a" + integrity sha512-mvsPN3eK4E0bZG0/WlWJjeqe/bUD2KOEVOl0GyL/TGXn6wcpZU8NOuztGHCUKXkyg5gq6YzUakVTmnmSSO5Yiw== dependencies: "@algolia/events" "^4.0.1" -algoliasearch@^4.0.0, algoliasearch@^4.10.5: - version "4.12.0" - resolved "https://registry.yarnpkg.com/algoliasearch/-/algoliasearch-4.12.0.tgz#30f2619b6e3a5b79b6aa0f18ab66fbce88240aba" - integrity sha512-fZOMMm+F3Bi5M/MoFIz7hiuyCitJza0Hu+r8Wzz4LIQClC6YGMRq7kT6NNU1fSSoFDSeJIwMfedbbi5G9dJoVQ== - dependencies: - "@algolia/cache-browser-local-storage" "4.12.0" - "@algolia/cache-common" "4.12.0" - "@algolia/cache-in-memory" "4.12.0" - "@algolia/client-account" "4.12.0" - "@algolia/client-analytics" "4.12.0" - "@algolia/client-common" "4.12.0" - "@algolia/client-personalization" "4.12.0" - "@algolia/client-search" "4.12.0" - "@algolia/logger-common" "4.12.0" - "@algolia/logger-console" "4.12.0" - "@algolia/requester-browser-xhr" "4.12.0" - "@algolia/requester-common" "4.12.0" - "@algolia/requester-node-http" "4.12.0" - "@algolia/transporter" "4.12.0" - -alphanum-sort@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/alphanum-sort/-/alphanum-sort-1.0.2.tgz#97a1119649b211ad33691d9f9f486a8ec9fbe0a3" - integrity sha1-l6ERlkmyEa0zaR2fn0hqjsn74KM= - -ansi-align@^3.0.0: +algoliasearch@^4.0.0, algoliasearch@^4.13.1: + version "4.14.2" + resolved "https://registry.yarnpkg.com/algoliasearch/-/algoliasearch-4.14.2.tgz#63f142583bfc3a9bd3cd4a1b098bf6fe58e56f6c" + integrity sha512-ngbEQonGEmf8dyEh5f+uOIihv4176dgbuOZspiuhmTTBRBuzWu3KCGHre6uHj5YyuC7pNvQGzB6ZNJyZi0z+Sg== + dependencies: + "@algolia/cache-browser-local-storage" "4.14.2" + "@algolia/cache-common" "4.14.2" + "@algolia/cache-in-memory" "4.14.2" + "@algolia/client-account" "4.14.2" + "@algolia/client-analytics" "4.14.2" + "@algolia/client-common" "4.14.2" + "@algolia/client-personalization" "4.14.2" + "@algolia/client-search" "4.14.2" + "@algolia/logger-common" "4.14.2" + "@algolia/logger-console" "4.14.2" + "@algolia/requester-browser-xhr" "4.14.2" + "@algolia/requester-common" "4.14.2" + "@algolia/requester-node-http" "4.14.2" + "@algolia/transporter" "4.14.2" + +ansi-align@^3.0.0, ansi-align@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/ansi-align/-/ansi-align-3.0.1.tgz#0cdf12e111ace773a86e9a1fad1225c43cb19a59" integrity sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w== @@ -2295,6 +2485,11 @@ ansi-styles@^4.0.0, ansi-styles@^4.1.0: dependencies: color-convert "^2.0.1" +ansi-styles@^6.1.0: + version "6.2.1" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-6.2.1.tgz#0e62320cf99c21afff3b3012192546aacbfb05c5" + integrity sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug== + anymatch@~3.1.2: version "3.1.2" resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.2.tgz#c0557c096af32f106198f4f4e2a383537e378716" @@ -2303,15 +2498,10 @@ anymatch@~3.1.2: normalize-path "^3.0.0" picomatch "^2.0.4" -"aproba@^1.0.3 || ^2.0.0": - version "2.0.0" - resolved "https://registry.yarnpkg.com/aproba/-/aproba-2.0.0.tgz#52520b8ae5b569215b354efc0caa3fe1e45a8adc" - integrity sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ== - arg@^5.0.0: - version "5.0.1" - resolved "https://registry.yarnpkg.com/arg/-/arg-5.0.1.tgz#eb0c9a8f77786cad2af8ff2b862899842d7b6adb" - integrity sha512-e0hDa9H2Z9AwFkk2qDlwhoMYE4eToKarchkQHovNdLTCYMHZHeRjI71crOh+dio4K6u1IcwubQqo79Ga4CyAQA== + version "5.0.2" + resolved "https://registry.yarnpkg.com/arg/-/arg-5.0.2.tgz#c81433cc427c92c4dcf4865142dbca6f15acd59c" + integrity sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg== argparse@^1.0.7: version "1.0.10" @@ -2328,9 +2518,9 @@ argparse@^2.0.1: array-flatten@1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2" - integrity sha1-ml9pkFGx5wczKPKgCJaLZOopVdI= + integrity sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg== -array-flatten@^2.1.0: +array-flatten@^2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-2.1.2.tgz#24ef80a28c1a893617e2149b0c6d0d788293b099" integrity sha512-hNfzcOV8W4NdualtqBFPyVO+54DSJuZGY9qT4pRroB6S9e3iiido2ISIC5h9R2sPJ8H3FHCIiEnsv1lPXO3KtQ== @@ -2340,66 +2530,47 @@ array-union@^2.1.0: resolved "https://registry.yarnpkg.com/array-union/-/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d" integrity sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw== -array-union@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/array-union/-/array-union-3.0.1.tgz#da52630d327f8b88cfbfb57728e2af5cd9b6b975" - integrity sha512-1OvF9IbWwaeiM9VhzYXVQacMibxpXOMYVNIvMtKRyX9SImBXpKcFr8XvFDeEslCyuH/t6KRt7HEO94AlP8Iatw== - asap@~2.0.3: version "2.0.6" resolved "https://registry.yarnpkg.com/asap/-/asap-2.0.6.tgz#e50347611d7e690943208bbdafebcbc2fb866d46" - integrity sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY= - -async@^2.6.2: - version "2.6.3" - resolved "https://registry.yarnpkg.com/async/-/async-2.6.3.tgz#d72625e2344a3656e3a3ad4fa749fa83299d82ff" - integrity sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg== - dependencies: - lodash "^4.17.14" + integrity sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA== asynckit@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" - integrity sha1-x57Zf380y48robyXkLzDZkdLS3k= + integrity sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q== at-least-node@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/at-least-node/-/at-least-node-1.0.0.tgz#602cd4b46e844ad4effc92a8011a3c46e0238dc2" integrity sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg== -autocomplete.js@^0.37.0: - version "0.37.1" - resolved "https://registry.yarnpkg.com/autocomplete.js/-/autocomplete.js-0.37.1.tgz#a29a048d827e7d2bf8f7df8b831766e5cc97df01" - integrity sha512-PgSe9fHYhZEsm/9jggbjtVsGXJkPLvd+9mC7gZJ662vVL5CRWEtm/mIrrzCx0MrNxHVwxD5d00UOn6NsmL2LUQ== +autoprefixer@^10.4.12, autoprefixer@^10.4.7: + version "10.4.13" + resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-10.4.13.tgz#b5136b59930209a321e9fa3dca2e7c4d223e83a8" + integrity sha512-49vKpMqcZYsJjwotvt4+h/BCjJVnhGwcLpDt5xkcaOG3eLrG/HUYLagrihYsQ+qrIBgIzX1Rw7a6L8I/ZA1Atg== dependencies: - immediate "^3.2.3" - -autoprefixer@^10.3.5, autoprefixer@^10.3.7: - version "10.4.2" - resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-10.4.2.tgz#25e1df09a31a9fba5c40b578936b90d35c9d4d3b" - integrity sha512-9fOPpHKuDW1w/0EKfRmVnxTDt8166MAnLI3mgZ1JCnhNtYWxcJ6Ud5CO/AVOZi/AvFa8DY9RTy3h3+tFBlrrdQ== - dependencies: - browserslist "^4.19.1" - caniuse-lite "^1.0.30001297" - fraction.js "^4.1.2" + browserslist "^4.21.4" + caniuse-lite "^1.0.30001426" + fraction.js "^4.2.0" normalize-range "^0.1.2" picocolors "^1.0.0" postcss-value-parser "^4.2.0" -axios@^0.21.1: - version "0.21.4" - resolved "https://registry.yarnpkg.com/axios/-/axios-0.21.4.tgz#c67b90dc0568e5c1cf2b0b858c43ba28e2eda575" - integrity sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg== +axios@^0.25.0: + version "0.25.0" + resolved "https://registry.yarnpkg.com/axios/-/axios-0.25.0.tgz#349cfbb31331a9b4453190791760a8d35b093e0a" + integrity sha512-cD8FOb0tRH3uuEe6+evtAbgJtfxr7ly3fQjYcMcuPlgkwVS9xboaVIpcDV+cYQe+yGykgwZCs1pzjntcGa6l5g== dependencies: - follow-redirects "^1.14.0" + follow-redirects "^1.14.7" -babel-loader@^8.2.2: - version "8.2.3" - resolved "https://registry.yarnpkg.com/babel-loader/-/babel-loader-8.2.3.tgz#8986b40f1a64cacfcb4b8429320085ef68b1342d" - integrity sha512-n4Zeta8NC3QAsuyiizu0GkmRcQ6clkV9WFUnUf1iXP//IeSKbWjofW3UHyZVwlOB4y039YQKefawyTn64Zwbuw== +babel-loader@^8.2.5: + version "8.3.0" + resolved "https://registry.yarnpkg.com/babel-loader/-/babel-loader-8.3.0.tgz#124936e841ba4fe8176786d6ff28add1f134d6a8" + integrity sha512-H8SvsMF+m9t15HNLMipppzkC+Y2Yq+v3SonZyU70RBL/h1gxPkH08Ot8pEE9Z4Kd+czyWJClmFS8qzIP9OZ04Q== dependencies: find-cache-dir "^3.3.1" - loader-utils "^1.4.0" + loader-utils "^2.0.0" make-dir "^3.1.0" schema-utils "^2.6.5" @@ -2411,13 +2582,6 @@ babel-plugin-apply-mdx-type-prop@1.6.22: "@babel/helper-plugin-utils" "7.10.4" "@mdx-js/util" "1.6.22" -babel-plugin-dynamic-import-node@2.3.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.0.tgz#f00f507bdaa3c3e3ff6e7e5e98d90a7acab96f7f" - integrity sha512-o6qFkpeQEBxcqt0XYlWzAVxNCSCZdUgcR8IRlhD/8DylxjjO4foPcvTW0GGKa/cVt3rvxZ7o5ippJ+/0nvLhlQ== - dependencies: - object.assign "^4.1.0" - babel-plugin-dynamic-import-node@^2.3.3: version "2.3.3" resolved "https://registry.yarnpkg.com/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.3.tgz#84fda19c976ec5c6defef57f9427b3def66e17a3" @@ -2432,29 +2596,29 @@ babel-plugin-extract-import-names@1.6.22: dependencies: "@babel/helper-plugin-utils" "7.10.4" -babel-plugin-polyfill-corejs2@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.3.0.tgz#407082d0d355ba565af24126fb6cb8e9115251fd" - integrity sha512-wMDoBJ6uG4u4PNFh72Ty6t3EgfA91puCuAwKIazbQlci+ENb/UU9A3xG5lutjUIiXCIn1CY5L15r9LimiJyrSA== +babel-plugin-polyfill-corejs2@^0.3.3: + version "0.3.3" + resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.3.3.tgz#5d1bd3836d0a19e1b84bbf2d9640ccb6f951c122" + integrity sha512-8hOdmFYFSZhqg2C/JgLUQ+t52o5nirNwaWM2B9LWteozwIvM14VSwdsCAUET10qT+kmySAlseadmfeeSWFCy+Q== dependencies: - "@babel/compat-data" "^7.13.11" - "@babel/helper-define-polyfill-provider" "^0.3.0" + "@babel/compat-data" "^7.17.7" + "@babel/helper-define-polyfill-provider" "^0.3.3" semver "^6.1.1" -babel-plugin-polyfill-corejs3@^0.5.0: - version "0.5.0" - resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.5.0.tgz#f81371be3fe499d39e074e272a1ef86533f3d268" - integrity sha512-Hcrgnmkf+4JTj73GbK3bBhlVPiLL47owUAnoJIf69Hakl3q+KfodbDXiZWGMM7iqCZTxCG3Z2VRfPNYES4rXqQ== +babel-plugin-polyfill-corejs3@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.6.0.tgz#56ad88237137eade485a71b52f72dbed57c6230a" + integrity sha512-+eHqR6OPcBhJOGgsIar7xoAB1GcSwVUA3XjAd7HJNzOXT4wv6/H7KIdA/Nc60cvUlDbKApmqNvD1B1bzOt4nyA== dependencies: - "@babel/helper-define-polyfill-provider" "^0.3.0" - core-js-compat "^3.20.0" + "@babel/helper-define-polyfill-provider" "^0.3.3" + core-js-compat "^3.25.1" -babel-plugin-polyfill-regenerator@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.3.0.tgz#9ebbcd7186e1a33e21c5e20cae4e7983949533be" - integrity sha512-dhAPTDLGoMW5/84wkgwiLRwMnio2i1fUe53EuvtKMv0pn2p3S8OCoV1xAzfJPl0KOX7IB89s2ib85vbYiea3jg== +babel-plugin-polyfill-regenerator@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.4.1.tgz#390f91c38d90473592ed43351e801a9d3e0fd747" + integrity sha512-NtQGmyQDXjQqQ+IzRkBVwEOz9lQ4zxAQZgoAYEtU9dJjnl1Oc98qnN7jcp+bE7O7aYzVpavXE3/VKXNzUbh7aw== dependencies: - "@babel/helper-define-polyfill-provider" "^0.3.0" + "@babel/helper-define-polyfill-provider" "^0.3.3" bail@^1.0.0: version "1.0.5" @@ -2474,17 +2638,12 @@ balanced-match@^1.0.0: base16@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/base16/-/base16-1.0.0.tgz#e297f60d7ec1014a7a971a39ebc8a98c0b681e70" - integrity sha1-4pf2DX7BAUp6lxo568ipjAtoHnA= + integrity sha512-pNdYkNPiJUnEhnfXV56+sQy8+AaPcG3POZAUnwr4EeqCUZFz4u2PePbo3e5Gj4ziYPCWGUZT9RHisvJKnwFuBQ== batch@0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/batch/-/batch-0.6.1.tgz#dc34314f4e679318093fc760272525f94bf25c16" - integrity sha1-3DQxT05nkxgJP8dgJyUl+UvyXBY= - -bcp-47-match@^1.0.0: - version "1.0.3" - resolved "https://registry.yarnpkg.com/bcp-47-match/-/bcp-47-match-1.0.3.tgz#cb8d03071389a10aff2062b862d6575ffd7cd7ef" - integrity sha512-LggQ4YTdjWQSKELZF5JwchnBa1u0pIQSZf5lSdOHEdbVP55h0qICA/FUp3+W99q0xqxYa1ZQizTUH87gecII5w== + integrity sha512-x+VAiMRL6UPkx+kudNvxTl6hB2XNNCG2r+7wixVfIYwu/2HKRXimwQyaumLjMveWvT2Hkd/cAJw+QBMfJ/EKVw== big.js@^5.2.2: version "5.2.2" @@ -2496,45 +2655,40 @@ binary-extensions@^2.0.0: resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d" integrity sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA== -bluebird@^3.7.1: - version "3.7.2" - resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.7.2.tgz#9f229c15be272454ffa973ace0dbee79a1b0c36f" - integrity sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg== - -body-parser@1.19.1: - version "1.19.1" - resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.19.1.tgz#1499abbaa9274af3ecc9f6f10396c995943e31d4" - integrity sha512-8ljfQi5eBk8EJfECMrgqNGWPEY5jWP+1IzkzkGdFFEwFQZZyaZ21UqdaHktgiMlH0xLHqIFtE/u2OYE5dOtViA== +body-parser@1.20.1: + version "1.20.1" + resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.20.1.tgz#b1812a8912c195cd371a3ee5e66faa2338a5c668" + integrity sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw== dependencies: - bytes "3.1.1" + bytes "3.1.2" content-type "~1.0.4" debug "2.6.9" - depd "~1.1.2" - http-errors "1.8.1" + depd "2.0.0" + destroy "1.2.0" + http-errors "2.0.0" iconv-lite "0.4.24" - on-finished "~2.3.0" - qs "6.9.6" - raw-body "2.4.2" + on-finished "2.4.1" + qs "6.11.0" + raw-body "2.5.1" type-is "~1.6.18" + unpipe "1.0.0" -bonjour@^3.5.0: - version "3.5.0" - resolved "https://registry.yarnpkg.com/bonjour/-/bonjour-3.5.0.tgz#8e890a183d8ee9a2393b3844c691a42bcf7bc9f5" - integrity sha1-jokKGD2O6aI5OzhExpGkK897yfU= +bonjour-service@^1.0.11: + version "1.0.14" + resolved "https://registry.yarnpkg.com/bonjour-service/-/bonjour-service-1.0.14.tgz#c346f5bc84e87802d08f8d5a60b93f758e514ee7" + integrity sha512-HIMbgLnk1Vqvs6B4Wq5ep7mxvj9sGz5d1JJyDNSGNIdA/w2MCz6GTjWTdjqOJV1bEPj+6IkxDvWNFKEBxNt4kQ== dependencies: - array-flatten "^2.1.0" - deep-equal "^1.0.1" + array-flatten "^2.1.2" dns-equal "^1.0.0" - dns-txt "^2.0.2" - multicast-dns "^6.0.1" - multicast-dns-service-types "^1.1.0" + fast-deep-equal "^3.1.3" + multicast-dns "^7.2.5" -boolbase@^1.0.0, boolbase@~1.0.0: +boolbase@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/boolbase/-/boolbase-1.0.0.tgz#68dff5fbe60c51eb37725ea9e3ed310dcc1e776e" - integrity sha1-aN/1++YMUes3cl6p4+0xDcwed24= + integrity sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww== -boxen@^5.0.0, boxen@^5.0.1: +boxen@^5.0.0: version "5.1.2" resolved "https://registry.yarnpkg.com/boxen/-/boxen-5.1.2.tgz#788cb686fc83c1f486dfa8a40c68fc2b831d2b50" integrity sha512-9gYgQKXx+1nP8mP7CzFyaUARhg7D3n1dF/FnErWmu9l6JvGpNUN278h0aSb+QjoiKSWG+iZ3uHrcqk0qrY9RQQ== @@ -2548,6 +2702,20 @@ boxen@^5.0.0, boxen@^5.0.1: widest-line "^3.1.0" wrap-ansi "^7.0.0" +boxen@^6.2.1: + version "6.2.1" + resolved "https://registry.yarnpkg.com/boxen/-/boxen-6.2.1.tgz#b098a2278b2cd2845deef2dff2efc38d329b434d" + integrity sha512-H4PEsJXfFI/Pt8sjDWbHlQPx4zL/bvSQjcilJmaulGt5mLDorHOHpmdXAJcBcmru7PhYSp/cDMWRko4ZUMFkSw== + dependencies: + ansi-align "^3.0.1" + camelcase "^6.2.0" + chalk "^4.1.2" + cli-boxes "^3.0.0" + string-width "^5.0.1" + type-fest "^2.5.0" + widest-line "^4.0.1" + wrap-ansi "^8.0.1" + brace-expansion@^1.1.7: version "1.1.11" resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" @@ -2556,7 +2724,7 @@ brace-expansion@^1.1.7: balanced-match "^1.0.0" concat-map "0.0.1" -braces@^3.0.1, braces@~3.0.2: +braces@^3.0.2, braces@~3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== @@ -2568,49 +2736,30 @@ browser-process-hrtime@^1.0.0: resolved "https://registry.yarnpkg.com/browser-process-hrtime/-/browser-process-hrtime-1.0.0.tgz#3c9b4b7d782c8121e56f10106d84c0d0ffc94626" integrity sha512-9o5UecI3GhkpM6DrXr69PblIuWxPKk9Y0jHBRhdocZ2y7YECBFCsHm79Pr3OyR2AvjhDkabFJaDJMYRazHgsow== -browserslist@^4.0.0, browserslist@^4.14.5, browserslist@^4.16.0, browserslist@^4.16.6, browserslist@^4.17.5, browserslist@^4.18.1, browserslist@^4.19.1: - version "4.19.1" - resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.19.1.tgz#4ac0435b35ab655896c31d53018b6dd5e9e4c9a3" - integrity sha512-u2tbbG5PdKRTUoctO3NBD8FQ5HdPh1ZXPHzp1rwaa5jTc+RV9/+RlWiAIKmjRPQF+xbGM9Kklj5bZQFa2s/38A== - dependencies: - caniuse-lite "^1.0.30001286" - electron-to-chromium "^1.4.17" - escalade "^3.1.1" - node-releases "^2.0.1" - picocolors "^1.0.0" - -buble-jsx-only@^0.19.8: - version "0.19.8" - resolved "https://registry.yarnpkg.com/buble-jsx-only/-/buble-jsx-only-0.19.8.tgz#6e3524aa0f1c523de32496ac9aceb9cc2b493867" - integrity sha512-7AW19pf7PrKFnGTEDzs6u9+JZqQwM1VnLS19OlqYDhXomtFFknnoQJAPHeg84RMFWAvOhYrG7harizJNwUKJsA== +browserslist@^4.0.0, browserslist@^4.14.5, browserslist@^4.16.6, browserslist@^4.18.1, browserslist@^4.21.3, browserslist@^4.21.4: + version "4.21.4" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.21.4.tgz#e7496bbc67b9e39dd0f98565feccdcb0d4ff6987" + integrity sha512-CBHJJdDmgjl3daYjN5Cp5kbTf1mUhZoS+beLklHIvkOWscs83YAhLlF3Wsh/lciQYAcbBJgTOD44VtG31ZM4Hw== dependencies: - acorn "^6.1.1" - acorn-dynamic-import "^4.0.0" - acorn-jsx "^5.0.1" - chalk "^2.4.2" - magic-string "^0.25.3" - minimist "^1.2.0" - regexpu-core "^4.5.4" + caniuse-lite "^1.0.30001400" + electron-to-chromium "^1.4.251" + node-releases "^2.0.6" + update-browserslist-db "^1.0.9" buffer-from@^1.0.0: version "1.1.2" resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5" integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ== -buffer-indexof@^1.0.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/buffer-indexof/-/buffer-indexof-1.1.1.tgz#52fabcc6a606d1a00302802648ef68f639da268c" - integrity sha512-4/rOEg86jivtPTeOUUT61jJO1Ya1TrR/OkqCSZDyq84WJh3LuuiphBYJN+fm5xufIk4XAFcEwte/8WzC8If/1g== - bytes@3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.0.0.tgz#d32815404d689699f85a4ea4fa8755dd13a96048" - integrity sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg= + integrity sha512-pMhOfFDPiv9t5jjIXkHosWmkSyQbvsgEVNkz0ERHbuLh2T/7j4Mqqpz523Fe8MVY89KC6Sh/QfS2sM+SjgFDcw== -bytes@3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.1.tgz#3f018291cb4cbad9accb6e6970bca9c8889e879a" - integrity sha512-dWe4nWO/ruEOY7HkUJ5gFt1DCFV9zPRoJr8pV0/ASQermOZjtq8jMjOprC0Kd10GLN+l7xaUPvxzJFWtxGu8Fg== +bytes@3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.2.tgz#8b0beeb98605adf1b128fa4386403c009e0221a5" + integrity sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg== cacheable-request@^6.0.0: version "6.1.0" @@ -2666,17 +2815,17 @@ caniuse-api@^3.0.0: lodash.memoize "^4.1.2" lodash.uniq "^4.5.0" -caniuse-lite@^1.0.0, caniuse-lite@^1.0.30001286, caniuse-lite@^1.0.30001297: - version "1.0.30001299" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001299.tgz#d753bf6444ed401eb503cbbe17aa3e1451b5a68c" - integrity sha512-iujN4+x7QzqA2NCSrS5VUy+4gLmRd4xv6vbBBsmfVqTx8bLAD8097euLqQgKxSVLvxjSDcvF1T/i9ocgnUFexw== +caniuse-lite@^1.0.0, caniuse-lite@^1.0.30001400, caniuse-lite@^1.0.30001426: + version "1.0.30001434" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001434.tgz#ec1ec1cfb0a93a34a0600d37903853030520a4e5" + integrity sha512-aOBHrLmTQw//WFa2rcF1If9fa3ypkC1wzqqiKHgfdrXTWcU8C4gKVZT77eQAPWN1APys3+uQ0Df07rKauXGEYA== -ccount@^1.0.0, ccount@^1.0.3: +ccount@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/ccount/-/ccount-1.1.0.tgz#246687debb6014735131be8abab2d93898f8d043" integrity sha512-vlNK021QdI7PNeiUh/lKkC/mNHHfV0m/Ad5JoI0TYtlBnJAslM/JIkm/tGC88bkLIwO6OQ5uV6ztS6kVAtCDlg== -chalk@^2.0.0, chalk@^2.4.2: +chalk@^2.0.0: version "2.4.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== @@ -2685,7 +2834,7 @@ chalk@^2.0.0, chalk@^2.4.2: escape-string-regexp "^1.0.5" supports-color "^5.3.0" -chalk@^4.1.0, chalk@^4.1.2: +chalk@^4.0.0, chalk@^4.1.0, chalk@^4.1.2: version "4.1.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== @@ -2708,56 +2857,35 @@ character-reference-invalid@^1.0.0: resolved "https://registry.yarnpkg.com/character-reference-invalid/-/character-reference-invalid-1.1.4.tgz#083329cda0eae272ab3dbbf37e9a382c13af1560" integrity sha512-mKKUkUbhPpQlCOfIuZkvSEgktjPFIsZKRRbC6KWVEMvlzblj3i3asQv5ODsrwt0N3pHAEvjP8KTQPHkp0+6jOg== -cheerio-select@^1.5.0: - version "1.5.0" - resolved "https://registry.yarnpkg.com/cheerio-select/-/cheerio-select-1.5.0.tgz#faf3daeb31b17c5e1a9dabcee288aaf8aafa5823" - integrity sha512-qocaHPv5ypefh6YNxvnbABM07KMxExbtbfuJoIie3iZXX1ERwYmJcIiRrr9H05ucQP1k28dav8rpdDgjQd8drg== +cheerio-select@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/cheerio-select/-/cheerio-select-2.1.0.tgz#4d8673286b8126ca2a8e42740d5e3c4884ae21b4" + integrity sha512-9v9kG0LvzrlcungtnJtpGNxY+fzECQKhK4EGJX2vByejiMX84MFNQw4UxPJl3bFbTMw+Dfs37XaIkCwTZfLh4g== dependencies: - css-select "^4.1.3" - css-what "^5.0.1" - domelementtype "^2.2.0" - domhandler "^4.2.0" - domutils "^2.7.0" - -cheerio@^0.22.0: - version "0.22.0" - resolved "https://registry.yarnpkg.com/cheerio/-/cheerio-0.22.0.tgz#a9baa860a3f9b595a6b81b1a86873121ed3a269e" - integrity sha1-qbqoYKP5tZWmuBsahocxIe06Jp4= - dependencies: - css-select "~1.2.0" - dom-serializer "~0.1.0" - entities "~1.1.1" - htmlparser2 "^3.9.1" - lodash.assignin "^4.0.9" - lodash.bind "^4.1.4" - lodash.defaults "^4.0.1" - lodash.filter "^4.4.0" - lodash.flatten "^4.2.0" - lodash.foreach "^4.3.0" - lodash.map "^4.4.0" - lodash.merge "^4.4.0" - lodash.pick "^4.2.1" - lodash.reduce "^4.4.0" - lodash.reject "^4.4.0" - lodash.some "^4.4.0" - -cheerio@^1.0.0-rc.10: - version "1.0.0-rc.10" - resolved "https://registry.yarnpkg.com/cheerio/-/cheerio-1.0.0-rc.10.tgz#2ba3dcdfcc26e7956fc1f440e61d51c643379f3e" - integrity sha512-g0J0q/O6mW8z5zxQ3A8E8J1hUgp4SMOvEoW/x84OwyHKe/Zccz83PVT4y5Crcr530FV6NgmKI1qvGTKVl9XXVw== - dependencies: - cheerio-select "^1.5.0" - dom-serializer "^1.3.2" - domhandler "^4.2.0" - htmlparser2 "^6.1.0" - parse5 "^6.0.1" - parse5-htmlparser2-tree-adapter "^6.0.1" - tslib "^2.2.0" - -chokidar@^3.4.2, chokidar@^3.5.2: - version "3.5.2" - resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.2.tgz#dba3976fcadb016f66fd365021d91600d01c1e75" - integrity sha512-ekGhOnNVPgT77r4K/U3GDhu+FQ2S8TnK/s2KbIGXi0SZWuwkZ2QNyfWdZW+TVfn84DpEP7rLeCt2UI6bJ8GwbQ== + boolbase "^1.0.0" + css-select "^5.1.0" + css-what "^6.1.0" + domelementtype "^2.3.0" + domhandler "^5.0.3" + domutils "^3.0.1" + +cheerio@^1.0.0-rc.12: + version "1.0.0-rc.12" + resolved "https://registry.yarnpkg.com/cheerio/-/cheerio-1.0.0-rc.12.tgz#788bf7466506b1c6bf5fae51d24a2c4d62e47683" + integrity sha512-VqR8m68vM46BNnuZ5NtnGBKIE/DfN0cRIzg9n40EIq9NOv90ayxLBXA8fXC5gquFRGJSTRqBq25Jt2ECLR431Q== + dependencies: + cheerio-select "^2.1.0" + dom-serializer "^2.0.0" + domhandler "^5.0.3" + domutils "^3.0.1" + htmlparser2 "^8.0.1" + parse5 "^7.0.0" + parse5-htmlparser2-tree-adapter "^7.0.0" + +chokidar@^3.4.2, chokidar@^3.5.3: + version "3.5.3" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.3.tgz#1cf37c8707b932bd1af1ae22c0432e2acd1903bd" + integrity sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw== dependencies: anymatch "~3.1.2" braces "~3.0.2" @@ -2779,15 +2907,15 @@ ci-info@^2.0.0: resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-2.0.0.tgz#67a9e964be31a51e15e5010d58e6f12834002f46" integrity sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ== -classnames@^2.2.6: - version "2.3.1" - resolved "https://registry.yarnpkg.com/classnames/-/classnames-2.3.1.tgz#dfcfa3891e306ec1dad105d0e88f4417b8535e8e" - integrity sha512-OlQdbZ7gLfGarSqxesMesDa5uz7KFbID8Kpq/SxIoNGDqY8lSYs0D+hhtBXhcdB3rcbXArFr7vlHheLk1voeNA== +ci-info@^3.2.0: + version "3.6.1" + resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-3.6.1.tgz#7594f1c95cb7fdfddee7af95a13af7dbc67afdcf" + integrity sha512-up5ggbaDqOqJ4UqLKZ2naVkyqSJQgJi5lwD6b6mM748ysrghDBX0bx/qJTUHzw7zu6Mq4gycviSF5hJnwceD8w== -clean-css@^5.1.5, clean-css@^5.2.2: - version "5.2.2" - resolved "https://registry.yarnpkg.com/clean-css/-/clean-css-5.2.2.tgz#d3a7c6ee2511011e051719838bdcf8314dc4548d" - integrity sha512-/eR8ru5zyxKzpBLv9YZvMXgTSSQn7AdkMItMYynsFgGwTveCRVam9IUPFloE85B4vAIj05IuKmmEoV7/AQjT0w== +clean-css@^5.2.2, clean-css@^5.3.0: + version "5.3.1" + resolved "https://registry.yarnpkg.com/clean-css/-/clean-css-5.3.1.tgz#d0610b0b90d125196a2894d35366f734e5d7aa32" + integrity sha512-lCr8OHhiWCTw4v8POJovCoh4T7I9U11yVsPjMWWnnMmp9ZowCxyad1Pathle/9HjaDp+fdQKjO9fQydE6RHTZg== dependencies: source-map "~0.6.0" @@ -2801,6 +2929,20 @@ cli-boxes@^2.2.1: resolved "https://registry.yarnpkg.com/cli-boxes/-/cli-boxes-2.2.1.tgz#ddd5035d25094fce220e9cab40a45840a440318f" integrity sha512-y4coMcylgSCdVinjiDBuR8PCC2bLjyGTwEmPb9NHR/QaNU6EUOXcTY/s6VjGMD6ENSEaeQYHCY0GNGS5jfMwPw== +cli-boxes@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/cli-boxes/-/cli-boxes-3.0.0.tgz#71a10c716feeba005e4504f36329ef0b17cf3145" + integrity sha512-/lzGpEWL/8PfI0BmBOPRwp0c/wFNX1RdUML3jK/RcSBA9T8mZDdQpqYBKtCFTOfQbwPqWEOpjqW+Fnayc0969g== + +cli-table3@^0.6.2: + version "0.6.3" + resolved "https://registry.yarnpkg.com/cli-table3/-/cli-table3-0.6.3.tgz#61ab765aac156b52f222954ffc607a6f01dbeeb2" + integrity sha512-w5Jac5SykAeZJKntOxJCrm63Eg5/4dhMWIcuTbo9rpE+brgaSZo0RuNJZeOyMgsUdhDeojvgyQLmjI+K50ZGyg== + dependencies: + string-width "^4.2.0" + optionalDependencies: + "@colors/colors" "1.5.0" + clone-deep@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/clone-deep/-/clone-deep-4.0.1.tgz#c19fd9bdbbf85942b4fd979c84dcf7d5f07c2387" @@ -2811,16 +2953,16 @@ clone-deep@^4.0.1: shallow-clone "^3.0.0" clone-response@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/clone-response/-/clone-response-1.0.2.tgz#d1dc973920314df67fbeb94223b4ee350239e96b" - integrity sha1-0dyXOSAxTfZ/vrlCI7TuNQI56Ws= + version "1.0.3" + resolved "https://registry.yarnpkg.com/clone-response/-/clone-response-1.0.3.tgz#af2032aa47816399cf5f0a1d0db902f517abb8c3" + integrity sha512-ROoL94jJH2dUVML2Y/5PEDNaSHgeOdSDicUyS7izcF63G6sTc/FTjLub4b8Il9S8S0beOfYt0TaA5qvFK+w0wA== dependencies: mimic-response "^1.0.0" -clsx@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/clsx/-/clsx-1.1.1.tgz#98b3134f9abbdf23b2663491ace13c5c03a73188" - integrity sha512-6/bPho624p3S2pMyvP5kKBPXnI3ufHLObBFCfgx+LkeR5lg2XYy2hqZqUf45ypD8COn2bhgGJSUE+l5dhNBieA== +clsx@^1.1.1, clsx@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/clsx/-/clsx-1.2.1.tgz#0ddc4a20a549b59c93a4116bb26f5294ca17dc12" + integrity sha512-EcR6r5a8bj6pu3ycsa/E/cKVGuTgZJZdsyUYHOksG/UHIiKfjxzRxYJpyVBwYaQeOvghal9fcc4PidlgzugAQg== collapse-white-space@^1.0.2: version "1.0.6" @@ -2844,27 +2986,22 @@ color-convert@^2.0.1: color-name@1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" - integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU= + integrity sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw== color-name@~1.1.4: version "1.1.4" resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== -color-support@^1.1.2: - version "1.1.3" - resolved "https://registry.yarnpkg.com/color-support/-/color-support-1.1.3.tgz#93834379a1cc9a0c61f82f52f0d04322251bd5a2" - integrity sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg== - colord@^2.9.1: - version "2.9.2" - resolved "https://registry.yarnpkg.com/colord/-/colord-2.9.2.tgz#25e2bacbbaa65991422c07ea209e2089428effb1" - integrity sha512-Uqbg+J445nc1TKn4FoDPS6ZZqAvEDnwrH42yo8B40JSOgSLxMZ/gt3h4nmCtPLQeXhjJJkqBx7SCY35WnIixaQ== + version "2.9.3" + resolved "https://registry.yarnpkg.com/colord/-/colord-2.9.3.tgz#4f8ce919de456f1d5c1c368c307fe20f3e59fb43" + integrity sha512-jeC1axXpnb0/2nn/Y1LPuLdgXBLH7aDcHu4KEKfqw3CUhX7ZpfBSlPKyqXE6btIgEzfWtrX3/tyBCaCvXvMkOw== colorette@^2.0.10: - version "2.0.16" - resolved "https://registry.yarnpkg.com/colorette/-/colorette-2.0.16.tgz#713b9af84fdb000139f04546bd4a93f62a5085da" - integrity sha512-hUewv7oMjCp+wkBv5Rm0v87eJhq4woh5rSR+42YSQJKecCqgIqNkZ6lAlQms/BwHPJA5NKMRlpxPRv0n8HQW6g== + version "2.0.19" + resolved "https://registry.yarnpkg.com/colorette/-/colorette-2.0.19.tgz#cdf044f47ad41a0f4b56b3a0d5b4e6e1a2d5a798" + integrity sha512-3tlv/dIP7FWvj3BsbHrGLJ6l/oKh1O3TcgBqMn+yyCagOxc23fyzDS6HypQbgxWbkpDnf52p1LuR4eWDQ/K9WQ== combine-promises@^1.1.0: version "1.1.0" @@ -2884,14 +3021,14 @@ comma-separated-tokens@^1.0.0: integrity sha512-GHuDRO12Sypu2cV70d1dkA2EUmXHgntrzbpvOB+Qy+49ypNfGgFQIC2fhhXbnyrJRynDCAARsT7Ou0M6hirpfw== comma-separated-tokens@^2.0.0: - version "2.0.2" - resolved "https://registry.yarnpkg.com/comma-separated-tokens/-/comma-separated-tokens-2.0.2.tgz#d4c25abb679b7751c880be623c1179780fe1dd98" - integrity sha512-G5yTt3KQN4Yn7Yk4ed73hlZ1evrFKXeUW3086p3PRFNp7m2vIjI6Pg+Kgb+oyzhd9F2qdcoj67+y3SdxL5XWsg== + version "2.0.3" + resolved "https://registry.yarnpkg.com/comma-separated-tokens/-/comma-separated-tokens-2.0.3.tgz#4e89c9458acb61bc8fef19f4529973b2392839ee" + integrity sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg== -commander@>=7.0.0, commander@^8.0.0, commander@^8.3.0: - version "8.3.0" - resolved "https://registry.yarnpkg.com/commander/-/commander-8.3.0.tgz#4837ea1b2da67b9c616a67afbb0fafee567bca66" - integrity sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww== +commander@9.2.0: + version "9.2.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-9.2.0.tgz#6e21014b2ed90d8b7c9647230d8b7a94a4a419a9" + integrity sha512-e2i4wANQiSXgnrBlIatyHtP1odfUp0BbV5Y5nEGbxtIrStkEOAAzCUirvLBNXHLr7kwLvJl6V+4V3XV9x7Wd9w== commander@^2.20.0: version "2.20.3" @@ -2908,10 +3045,15 @@ commander@^7.2.0: resolved "https://registry.yarnpkg.com/commander/-/commander-7.2.0.tgz#a36cb57d0b501ce108e4d20559a150a391d97ab7" integrity sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw== +commander@^8.0.0, commander@^8.3.0: + version "8.3.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-8.3.0.tgz#4837ea1b2da67b9c616a67afbb0fafee567bca66" + integrity sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww== + commondir@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b" - integrity sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs= + integrity sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg== compressible@~2.0.16: version "2.0.18" @@ -2936,7 +3078,7 @@ compression@^1.7.4: concat-map@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" - integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= + integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg== configstore@^5.0.1: version "5.0.1" @@ -2950,25 +3092,20 @@ configstore@^5.0.1: write-file-atomic "^3.0.0" xdg-basedir "^4.0.0" -connect-history-api-fallback@^1.6.0: - version "1.6.0" - resolved "https://registry.yarnpkg.com/connect-history-api-fallback/-/connect-history-api-fallback-1.6.0.tgz#8b32089359308d111115d81cad3fceab888f97bc" - integrity sha512-e54B99q/OUoH64zYYRf3HBP5z24G38h5D3qXu23JGRoigpX5Ss4r9ZnDk3g0Z8uQC2x2lPaJ+UlWBc1ZWBWdLg== +connect-history-api-fallback@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/connect-history-api-fallback/-/connect-history-api-fallback-2.0.0.tgz#647264845251a0daf25b97ce87834cace0f5f1c8" + integrity sha512-U73+6lQFmfiNPrYbXqr6kZ1i1wiRqXnp2nhMsINseWXO8lDau0LGEffJ8kQi4EjLZympVgRdvqjAgiZ1tgzDDA== consola@^2.15.3: version "2.15.3" resolved "https://registry.yarnpkg.com/consola/-/consola-2.15.3.tgz#2e11f98d6a4be71ff72e0bdf07bd23e12cb61550" integrity sha512-9vAdYbHj6x2fLKC4+oPH0kFzY/orMZyG2Aj+kNylHxKGJ/Ed4dpNyAQYwJOdqO4zdM7XpVHmyejQDcQHrnuXbw== -console-control-strings@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e" - integrity sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4= - content-disposition@0.5.2: version "0.5.2" resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.2.tgz#0cf68bb9ddf5f2be7961c3a85178cb85dba78cb4" - integrity sha1-DPaLud318r55YcOoUXjLhdunjLQ= + integrity sha512-kRGRZw3bLlFISDBgwTSA1TMBFN6J6GWDeubmDE3AF+3+yXL8hTWv8r5rkLbqYXY4RjPk/EzHnClI3zQf1cFmHA== content-disposition@0.5.4: version "0.5.4" @@ -2983,56 +3120,53 @@ content-type@~1.0.4: integrity sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA== convert-source-map@^1.7.0: - version "1.8.0" - resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.8.0.tgz#f3373c32d21b4d780dd8004514684fb791ca4369" - integrity sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA== - dependencies: - safe-buffer "~5.1.1" + version "1.9.0" + resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.9.0.tgz#7faae62353fb4213366d0ca98358d22e8368b05f" + integrity sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A== cookie-signature@1.0.6: version "1.0.6" resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c" - integrity sha1-4wOogrNCzD7oylE6eZmXNNqzriw= + integrity sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ== -cookie@0.4.1: - version "0.4.1" - resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.4.1.tgz#afd713fe26ebd21ba95ceb61f9a8116e50a537d1" - integrity sha512-ZwrFkGJxUR3EIoXtO+yVE69Eb7KlixbaeAWfBQB9vVsNn/o+Yw69gBWSSDK825hQNdN+wF8zELf3dFNl/kxkUA== +cookie@0.5.0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.5.0.tgz#d1f5d71adec6558c58f389987c366aa47e994f8b" + integrity sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw== copy-text-to-clipboard@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/copy-text-to-clipboard/-/copy-text-to-clipboard-3.0.1.tgz#8cbf8f90e0a47f12e4a24743736265d157bce69c" integrity sha512-rvVsHrpFcL4F2P8ihsoLdFHmd404+CMg71S756oRSeQgqk51U3kicGdnvfkrxva0xXH92SjGS62B0XIJsbh+9Q== -copy-webpack-plugin@^10.2.0: - version "10.2.1" - resolved "https://registry.yarnpkg.com/copy-webpack-plugin/-/copy-webpack-plugin-10.2.1.tgz#115a41f913070ac236a1b576066204cbf35341a1" - integrity sha512-nr81NhCAIpAWXGCK5thrKmfCQ6GDY0L5RN0U+BnIn/7Us55+UCex5ANNsNKmIVtDRnk0Ecf+/kzp9SUVrrBMLg== +copy-webpack-plugin@^11.0.0: + version "11.0.0" + resolved "https://registry.yarnpkg.com/copy-webpack-plugin/-/copy-webpack-plugin-11.0.0.tgz#96d4dbdb5f73d02dd72d0528d1958721ab72e04a" + integrity sha512-fX2MWpamkW0hZxMEg0+mYnA40LTosOSa5TqZ9GYIBzyJa9C3QUaMPSE2xAi/buNr8u89SfD9wHSQVBzrRa/SOQ== dependencies: - fast-glob "^3.2.7" + fast-glob "^3.2.11" glob-parent "^6.0.1" - globby "^12.0.2" + globby "^13.1.1" normalize-path "^3.0.0" schema-utils "^4.0.0" serialize-javascript "^6.0.0" -core-js-compat@^3.20.0, core-js-compat@^3.20.2: - version "3.20.2" - resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.20.2.tgz#d1ff6936c7330959b46b2e08b122a8b14e26140b" - integrity sha512-qZEzVQ+5Qh6cROaTPFLNS4lkvQ6mBzE3R6A6EEpssj7Zr2egMHgsy4XapdifqJDGC9CBiNv7s+ejI96rLNQFdg== +core-js-compat@^3.25.1: + version "3.26.1" + resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.26.1.tgz#0e710b09ebf689d719545ac36e49041850f943df" + integrity sha512-622/KzTudvXCDLRw70iHW4KKs1aGpcRcowGWyYJr2DEBfRrd6hNJybxSWJFuZYD4ma86xhrwDDHxmDaIq4EA8A== dependencies: - browserslist "^4.19.1" - semver "7.0.0" + browserslist "^4.21.4" -core-js-pure@^3.20.2: - version "3.20.2" - resolved "https://registry.yarnpkg.com/core-js-pure/-/core-js-pure-3.20.2.tgz#5d263565f0e34ceeeccdc4422fae3e84ca6b8c0f" - integrity sha512-CmWHvSKn2vNL6p6StNp1EmMIfVY/pqn3JLAjfZQ8WZGPOlGoO92EkX9/Mk81i6GxvoPXjUqEQnpM3rJ5QxxIOg== +core-js-pure@^3.25.1: + version "3.26.1" + resolved "https://registry.yarnpkg.com/core-js-pure/-/core-js-pure-3.26.1.tgz#653f4d7130c427820dcecd3168b594e8bb095a33" + integrity sha512-VVXcDpp/xJ21KdULRq/lXdLzQAtX7+37LzpyfFM973il0tWSsDEoyzG38G14AjTpK9VTfiNM9jnFauq/CpaWGQ== -core-js@^3.18.0: - version "3.20.2" - resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.20.2.tgz#46468d8601eafc8b266bd2dd6bf9dee622779581" - integrity sha512-nuqhq11DcOAbFBV4zCbKeGbKQsUDRqTX0oqx7AttUBuqe3h20ixsE039QHelbL6P4h+9kytVqyEtyZ6gsiwEYw== +core-js@^3.23.3: + version "3.26.1" + resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.26.1.tgz#7a9816dabd9ee846c1c0fe0e8fcad68f3709134e" + integrity sha512-21491RRQVzUn0GGM9Z1Jrpr6PNPxPi+Za8OM9q4tksTSnlbXXGKK1nXNg/QvwFYettXvSX6zWKCtHHfjN4puyA== core-util-is@~1.0.0: version "1.0.3" @@ -3051,9 +3185,9 @@ cosmiconfig@^6.0.0: yaml "^1.7.2" cosmiconfig@^7.0.0, cosmiconfig@^7.0.1: - version "7.0.1" - resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-7.0.1.tgz#714d756522cace867867ccb4474c5d01bbae5d6d" - integrity sha512-a1YWNUV2HwGimB7dU2s1wUMurNKjpx60HxBB6xUM8Re+2s1g1IIfJvFR0/iCF+XHdE0GMTKTuLR32UQff4TEyQ== + version "7.1.0" + resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-7.1.0.tgz#1443b9afa596b670082ea46cbd8f6a62b84635f6" + integrity sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA== dependencies: "@types/parse-json" "^4.0.0" import-fresh "^3.2.1" @@ -3061,12 +3195,12 @@ cosmiconfig@^7.0.0, cosmiconfig@^7.0.1: path-type "^4.0.0" yaml "^1.10.0" -cross-fetch@^3.0.4: - version "3.1.4" - resolved "https://registry.yarnpkg.com/cross-fetch/-/cross-fetch-3.1.4.tgz#9723f3a3a247bf8b89039f3a380a9244e8fa2f39" - integrity sha512-1eAtFWdIubi6T4XPy6ei9iUFoKpUkIF971QLN8lIvvvwueI65+Nw5haMNKUwfJxabqlIIDODJKGrQ66gxC0PbQ== +cross-fetch@^3.1.5: + version "3.1.5" + resolved "https://registry.yarnpkg.com/cross-fetch/-/cross-fetch-3.1.5.tgz#e1389f44d9e7ba767907f7af8454787952ab534f" + integrity sha512-lvb1SBsI0Z7GDwmuid+mU3kWVBwTVUbe7S0H52yaaAdQOXq2YktTCZdlAcNKFzE6QtRz0snpw9bNiPeOIkkQvw== dependencies: - node-fetch "2.6.1" + node-fetch "2.6.7" cross-spawn@^7.0.3: version "7.0.3" @@ -3082,64 +3216,58 @@ crypto-random-string@^2.0.0: resolved "https://registry.yarnpkg.com/crypto-random-string/-/crypto-random-string-2.0.0.tgz#ef2a7a966ec11083388369baa02ebead229b30d5" integrity sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA== -css-declaration-sorter@^6.0.3: - version "6.1.4" - resolved "https://registry.yarnpkg.com/css-declaration-sorter/-/css-declaration-sorter-6.1.4.tgz#b9bfb4ed9a41f8dcca9bf7184d849ea94a8294b4" - integrity sha512-lpfkqS0fctcmZotJGhnxkIyJWvBXgpyi2wsFd4J8VB7wzyrT6Ch/3Q+FMNJpjK4gu1+GN5khOnpU2ZVKrLbhCw== - dependencies: - timsort "^0.3.0" +css-declaration-sorter@^6.3.1: + version "6.3.1" + resolved "https://registry.yarnpkg.com/css-declaration-sorter/-/css-declaration-sorter-6.3.1.tgz#be5e1d71b7a992433fb1c542c7a1b835e45682ec" + integrity sha512-fBffmak0bPAnyqc/HO8C3n2sHrp9wcqQz6ES9koRF2/mLOVAx9zIQ3Y7R29sYCteTPqMCwns4WYQoCX91Xl3+w== -css-loader@^6.5.1: - version "6.5.1" - resolved "https://registry.yarnpkg.com/css-loader/-/css-loader-6.5.1.tgz#0c43d4fbe0d97f699c91e9818cb585759091d1b1" - integrity sha512-gEy2w9AnJNnD9Kuo4XAP9VflW/ujKoS9c/syO+uWMlm5igc7LysKzPXaDoR2vroROkSwsTS2tGr1yGGEbZOYZQ== +css-loader@^6.7.1: + version "6.7.2" + resolved "https://registry.yarnpkg.com/css-loader/-/css-loader-6.7.2.tgz#26bc22401b5921686a10fbeba75d124228302304" + integrity sha512-oqGbbVcBJkm8QwmnNzrFrWTnudnRZC+1eXikLJl0n4ljcfotgRifpg2a1lKy8jTrc4/d9A/ap1GFq1jDKG7J+Q== dependencies: icss-utils "^5.1.0" - postcss "^8.2.15" + postcss "^8.4.18" postcss-modules-extract-imports "^3.0.0" postcss-modules-local-by-default "^4.0.0" postcss-modules-scope "^3.0.0" postcss-modules-values "^4.0.0" - postcss-value-parser "^4.1.0" - semver "^7.3.5" + postcss-value-parser "^4.2.0" + semver "^7.3.8" -css-minimizer-webpack-plugin@^3.3.1: - version "3.4.1" - resolved "https://registry.yarnpkg.com/css-minimizer-webpack-plugin/-/css-minimizer-webpack-plugin-3.4.1.tgz#ab78f781ced9181992fe7b6e4f3422e76429878f" - integrity sha512-1u6D71zeIfgngN2XNRJefc/hY7Ybsxd74Jm4qngIXyUEk7fss3VUzuHxLAq/R8NAba4QU9OUSaMZlbpRc7bM4Q== +css-minimizer-webpack-plugin@^4.0.0: + version "4.2.2" + resolved "https://registry.yarnpkg.com/css-minimizer-webpack-plugin/-/css-minimizer-webpack-plugin-4.2.2.tgz#79f6199eb5adf1ff7ba57f105e3752d15211eb35" + integrity sha512-s3Of/4jKfw1Hj9CxEO1E5oXhQAxlayuHO2y/ML+C6I9sQ7FdzfEV6QgMLN3vI+qFsjJGIAFLKtQK7t8BOXAIyA== dependencies: - cssnano "^5.0.6" - jest-worker "^27.0.2" - postcss "^8.3.5" + cssnano "^5.1.8" + jest-worker "^29.1.2" + postcss "^8.4.17" schema-utils "^4.0.0" serialize-javascript "^6.0.0" source-map "^0.6.1" css-select@^4.1.3: - version "4.2.1" - resolved "https://registry.yarnpkg.com/css-select/-/css-select-4.2.1.tgz#9e665d6ae4c7f9d65dbe69d0316e3221fb274cdd" - integrity sha512-/aUslKhzkTNCQUB2qTX84lVmfia9NyjP3WpDGtj/WxhwBzWBYUV3DgUpurHTme8UTPcPlAD1DJ+b0nN/t50zDQ== + version "4.3.0" + resolved "https://registry.yarnpkg.com/css-select/-/css-select-4.3.0.tgz#db7129b2846662fd8628cfc496abb2b59e41529b" + integrity sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ== dependencies: boolbase "^1.0.0" - css-what "^5.1.0" - domhandler "^4.3.0" + css-what "^6.0.1" + domhandler "^4.3.1" domutils "^2.8.0" nth-check "^2.0.1" -css-select@~1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/css-select/-/css-select-1.2.0.tgz#2b3a110539c5355f1cd8d314623e870b121ec858" - integrity sha1-KzoRBTnFNV8c2NMUYj6HCxIeyFg= +css-select@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/css-select/-/css-select-5.1.0.tgz#b8ebd6554c3637ccc76688804ad3f6a6fdaea8a6" + integrity sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg== dependencies: - boolbase "~1.0.0" - css-what "2.1" - domutils "1.5.1" - nth-check "~1.0.1" - -css-selector-parser@^1.0.0: - version "1.4.1" - resolved "https://registry.yarnpkg.com/css-selector-parser/-/css-selector-parser-1.4.1.tgz#03f9cb8a81c3e5ab2c51684557d5aaf6d2569759" - integrity sha512-HYPSb7y/Z7BNDCOrakL4raGO2zltZkbeXyAd6Tg9obzix6QhzxCotdBl6VT0Dv4vZfJGVz3WL/xaEI9Ly3ul0g== + boolbase "^1.0.0" + css-what "^6.1.0" + domhandler "^5.0.2" + domutils "^3.0.1" + nth-check "^2.0.1" css-tree@^1.1.2, css-tree@^1.1.3: version "1.1.3" @@ -3149,79 +3277,74 @@ css-tree@^1.1.2, css-tree@^1.1.3: mdn-data "2.0.14" source-map "^0.6.1" -css-what@2.1: - version "2.1.3" - resolved "https://registry.yarnpkg.com/css-what/-/css-what-2.1.3.tgz#a6d7604573365fe74686c3f311c56513d88285f2" - integrity sha512-a+EPoD+uZiNfh+5fxw2nO9QwFa6nJe2Or35fGY6Ipw1R3R4AGz1d1TEZrCegvw2YTmZ0jXirGYlzxxpYSHwpEg== - -css-what@^5.0.1, css-what@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/css-what/-/css-what-5.1.0.tgz#3f7b707aadf633baf62c2ceb8579b545bb40f7fe" - integrity sha512-arSMRWIIFY0hV8pIxZMEfmMI47Wj3R/aWpZDDxWYCPEiOMv6tfOrnpDtgxBYPEQD4V0Y/958+1TdC3iWTFcUPw== +css-what@^6.0.1, css-what@^6.1.0: + version "6.1.0" + resolved "https://registry.yarnpkg.com/css-what/-/css-what-6.1.0.tgz#fb5effcf76f1ddea2c81bdfaa4de44e79bac70f4" + integrity sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw== cssesc@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-3.0.0.tgz#37741919903b868565e1c09ea747445cd18983ee" integrity sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg== -cssnano-preset-advanced@^5.1.4: - version "5.1.10" - resolved "https://registry.yarnpkg.com/cssnano-preset-advanced/-/cssnano-preset-advanced-5.1.10.tgz#0540a8902350418314f4f0d9ccfc45028fb62e25" - integrity sha512-6Rc7jbnIBpEUyuTLDBLuvsZE64NY9NRNe4HjOVb0zT0ixiGatKAmUNtTIwLP2F/vE5VJsdlVcixX9y2kb7O+zQ== - dependencies: - autoprefixer "^10.3.7" - cssnano-preset-default "^5.1.10" - postcss-discard-unused "^5.0.1" - postcss-merge-idents "^5.0.2" - postcss-reduce-idents "^5.0.1" - postcss-zindex "^5.0.1" - -cssnano-preset-default@^5.1.10: - version "5.1.10" - resolved "https://registry.yarnpkg.com/cssnano-preset-default/-/cssnano-preset-default-5.1.10.tgz#9350765fdf3c49bf78fac7673354fa58fa95daa4" - integrity sha512-BcpSzUVygHMOnp9uG5rfPzTOCb0GAHQkqtUQx8j1oMNF9A1Q8hziOOhiM4bdICpmrBIU85BE64RD5XGYsVQZNA== - dependencies: - css-declaration-sorter "^6.0.3" - cssnano-utils "^3.0.0" - postcss-calc "^8.2.0" - postcss-colormin "^5.2.3" - postcss-convert-values "^5.0.2" - postcss-discard-comments "^5.0.1" - postcss-discard-duplicates "^5.0.1" - postcss-discard-empty "^5.0.1" - postcss-discard-overridden "^5.0.2" - postcss-merge-longhand "^5.0.4" - postcss-merge-rules "^5.0.4" - postcss-minify-font-values "^5.0.2" - postcss-minify-gradients "^5.0.4" - postcss-minify-params "^5.0.3" - postcss-minify-selectors "^5.1.1" - postcss-normalize-charset "^5.0.1" - postcss-normalize-display-values "^5.0.2" - postcss-normalize-positions "^5.0.2" - postcss-normalize-repeat-style "^5.0.2" - postcss-normalize-string "^5.0.2" - postcss-normalize-timing-functions "^5.0.2" - postcss-normalize-unicode "^5.0.2" - postcss-normalize-url "^5.0.4" - postcss-normalize-whitespace "^5.0.2" - postcss-ordered-values "^5.0.3" - postcss-reduce-initial "^5.0.2" - postcss-reduce-transforms "^5.0.2" - postcss-svgo "^5.0.3" - postcss-unique-selectors "^5.0.2" - -cssnano-utils@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/cssnano-utils/-/cssnano-utils-3.0.0.tgz#c0b9fcd6e4f05c5155b07e9ab11bf94b97163057" - integrity sha512-Pzs7/BZ6OgT+tXXuF12DKR8SmSbzUeVYCtMBbS8lI0uAm3mrYmkyqCXXPsQESI6kmLfEVBppbdVY/el3hg3nAA== +cssnano-preset-advanced@^5.3.8: + version "5.3.9" + resolved "https://registry.yarnpkg.com/cssnano-preset-advanced/-/cssnano-preset-advanced-5.3.9.tgz#99e1cdf81a467a5e6c366cfc6d874a166c4d9a67" + integrity sha512-njnh4pp1xCsibJcEHnWZb4EEzni0ePMqPuPNyuWT4Z+YeXmsgqNuTPIljXFEXhxGsWs9183JkXgHxc1TcsahIg== + dependencies: + autoprefixer "^10.4.12" + cssnano-preset-default "^5.2.13" + postcss-discard-unused "^5.1.0" + postcss-merge-idents "^5.1.1" + postcss-reduce-idents "^5.2.0" + postcss-zindex "^5.1.0" + +cssnano-preset-default@^5.2.13: + version "5.2.13" + resolved "https://registry.yarnpkg.com/cssnano-preset-default/-/cssnano-preset-default-5.2.13.tgz#e7353b0c57975d1bdd97ac96e68e5c1b8c68e990" + integrity sha512-PX7sQ4Pb+UtOWuz8A1d+Rbi+WimBIxJTRyBdgGp1J75VU0r/HFQeLnMYgHiCAp6AR4rqrc7Y4R+1Rjk3KJz6DQ== + dependencies: + css-declaration-sorter "^6.3.1" + cssnano-utils "^3.1.0" + postcss-calc "^8.2.3" + postcss-colormin "^5.3.0" + postcss-convert-values "^5.1.3" + postcss-discard-comments "^5.1.2" + postcss-discard-duplicates "^5.1.0" + postcss-discard-empty "^5.1.1" + postcss-discard-overridden "^5.1.0" + postcss-merge-longhand "^5.1.7" + postcss-merge-rules "^5.1.3" + postcss-minify-font-values "^5.1.0" + postcss-minify-gradients "^5.1.1" + postcss-minify-params "^5.1.4" + postcss-minify-selectors "^5.2.1" + postcss-normalize-charset "^5.1.0" + postcss-normalize-display-values "^5.1.0" + postcss-normalize-positions "^5.1.1" + postcss-normalize-repeat-style "^5.1.1" + postcss-normalize-string "^5.1.0" + postcss-normalize-timing-functions "^5.1.0" + postcss-normalize-unicode "^5.1.1" + postcss-normalize-url "^5.1.0" + postcss-normalize-whitespace "^5.1.1" + postcss-ordered-values "^5.1.3" + postcss-reduce-initial "^5.1.1" + postcss-reduce-transforms "^5.1.0" + postcss-svgo "^5.1.0" + postcss-unique-selectors "^5.1.1" + +cssnano-utils@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/cssnano-utils/-/cssnano-utils-3.1.0.tgz#95684d08c91511edfc70d2636338ca37ef3a6861" + integrity sha512-JQNR19/YZhz4psLX/rQ9M83e3z2Wf/HdJbryzte4a3NSuafyp9w/I4U+hx5C2S9g41qlstH7DEWnZaaj83OuEA== -cssnano@^5.0.6, cssnano@^5.0.8: - version "5.0.15" - resolved "https://registry.yarnpkg.com/cssnano/-/cssnano-5.0.15.tgz#8779eaf60e3665e6a12687c814d375cc9f78db76" - integrity sha512-ppZsS7oPpi2sfiyV5+i+NbB/3GtQ+ab2Vs1azrZaXWujUSN4o+WdTxlCZIMcT9yLW3VO/5yX3vpyDaQ1nIn8CQ== +cssnano@^5.1.12, cssnano@^5.1.8: + version "5.1.14" + resolved "https://registry.yarnpkg.com/cssnano/-/cssnano-5.1.14.tgz#07b0af6da73641276fe5a6d45757702ebae2eb05" + integrity sha512-Oou7ihiTocbKqi0J1bB+TRJIQX5RMR3JghA8hcWSw9mjBLQ5Y3RWqEDoYG3sRNlAbCIXpqMoZGbq5KDR3vdzgw== dependencies: - cssnano-preset-default "^5.1.10" + cssnano-preset-default "^5.2.13" lilconfig "^2.0.3" yaml "^1.10.2" @@ -3250,18 +3373,18 @@ cssstyle@^2.3.0: cssom "~0.3.6" csstype@^3.0.2: - version "3.0.10" - resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.0.10.tgz#2ad3a7bed70f35b965707c092e5f30b327c290e5" - integrity sha512-2u44ZG2OcNUO9HDp/Jl8C07x6pU/eTR3ncV91SiK3dhG9TWvRVsCoJw14Ckx5DgWkzGA3waZWO3d7pgqpUI/XA== + version "3.1.1" + resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.1.1.tgz#841b532c45c758ee546a11d5bd7b7b473c8c30b9" + integrity sha512-DJR/VvkAvSZW9bTouZue2sSxDwdTN92uHjqeKVm+0dAqdfNykRzQ95tay8aXMBAAPpUiq4Qcug2L7neoRh2Egw== data-urls@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/data-urls/-/data-urls-3.0.1.tgz#597fc2ae30f8bc4dbcf731fcd1b1954353afc6f8" - integrity sha512-Ds554NeT5Gennfoo9KN50Vh6tpgtvYEwraYjejXnyTpu1C7oXKxdFk75REooENHE8ndTVOJuv+BEs4/J/xcozw== + version "3.0.2" + resolved "https://registry.yarnpkg.com/data-urls/-/data-urls-3.0.2.tgz#9cf24a477ae22bcef5cd5f6f0bfbc1d2d3be9143" + integrity sha512-Jy/tj3ldjZJo63sVAvg6LHt2mHvl4V6AgRAmNDtLdm7faqtsx+aJG42rsyCo9JCoRVKwPFzKlIPx3DIibwSIaQ== dependencies: - abab "^2.0.3" + abab "^2.0.6" whatwg-mimetype "^3.0.0" - whatwg-url "^10.0.0" + whatwg-url "^11.0.0" debug@2.6.9, debug@^2.6.0: version "2.6.9" @@ -3271,43 +3394,24 @@ debug@2.6.9, debug@^2.6.0: ms "2.0.0" debug@4, debug@^4.1.0, debug@^4.1.1: - version "4.3.3" - resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.3.tgz#04266e0b70a98d4462e6e288e38259213332b664" - integrity sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q== + version "4.3.4" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" + integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== dependencies: ms "2.1.2" -debug@^3.1.1: - version "3.2.7" - resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.7.tgz#72580b7e9145fb39b6676f9c5e5fb100b934179a" - integrity sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ== - dependencies: - ms "^2.1.1" - decimal.js@^10.3.1: - version "10.3.1" - resolved "https://registry.yarnpkg.com/decimal.js/-/decimal.js-10.3.1.tgz#d8c3a444a9c6774ba60ca6ad7261c3a94fd5e783" - integrity sha512-V0pfhfr8suzyPGOx3nmq4aHqabehUZn6Ch9kyFpV79TGDTWFmHqUqXdabR7QHqxzrYolF4+tVmJhUG4OURg5dQ== + version "10.4.2" + resolved "https://registry.yarnpkg.com/decimal.js/-/decimal.js-10.4.2.tgz#0341651d1d997d86065a2ce3a441fbd0d8e8b98e" + integrity sha512-ic1yEvwT6GuvaYwBLLY6/aFFgjZdySKTE8en/fkU3QICTmRtgtSlFn0u0BXN06InZwtfCelR7j8LRiDI/02iGA== decompress-response@^3.3.0: version "3.3.0" resolved "https://registry.yarnpkg.com/decompress-response/-/decompress-response-3.3.0.tgz#80a4dd323748384bfa248083622aedec982adff3" - integrity sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M= + integrity sha512-BzRPQuY1ip+qDonAOz42gRm/pg9F768C+npV/4JOsxRC2sq+Rlk+Q4ZCAsOhnIaMrgarILY+RMUIvMmmX1qAEA== dependencies: mimic-response "^1.0.0" -deep-equal@^1.0.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/deep-equal/-/deep-equal-1.1.1.tgz#b5c98c942ceffaf7cb051e24e1434a25a2e6076a" - integrity sha512-yd9c5AdiqVcR+JjcwUQb9DkhJc8ngNr0MahEBGvDiJw8puWab2yZlh+nkasOnZP+EGTAP6rRp2JzJhJZzvNF8g== - dependencies: - is-arguments "^1.0.4" - is-date-object "^1.0.1" - is-regex "^1.0.4" - object-is "^1.0.1" - object-keys "^1.1.1" - regexp.prototype.flags "^1.2.0" - deep-extend@^0.6.0: version "0.6.0" resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac" @@ -3340,17 +3444,18 @@ define-lazy-prop@^2.0.0: resolved "https://registry.yarnpkg.com/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz#3f7ae421129bcaaac9bc74905c98a0009ec9ee7f" integrity sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og== -define-properties@^1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.3.tgz#cf88da6cbee26fe6db7094f61d870cbd84cee9f1" - integrity sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ== +define-properties@^1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.4.tgz#0b14d7bd7fbeb2f3572c3a7eda80ea5d57fb05b1" + integrity sha512-uckOqKcfaVvtBdsVkdPv3XjveQJsNQqmhXgRi8uhvWWuPYZCNlzT8qAyblUgNoXdHdjMTzAqeGjAoli8f+bzPA== dependencies: - object-keys "^1.0.12" + has-property-descriptors "^1.0.0" + object-keys "^1.1.1" -del@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/del/-/del-6.0.0.tgz#0b40d0332cea743f1614f818be4feb717714c952" - integrity sha512-1shh9DQ23L16oXSZKB2JxpL7iMy2E0S9d517ptA1P8iw0alkPtQcrKH7ru31rYtKwF499HkTu+DRzq3TCKDFRQ== +del@^6.1.1: + version "6.1.1" + resolved "https://registry.yarnpkg.com/del/-/del-6.1.1.tgz#3b70314f1ec0aa325c6b14eb36b95786671edb7a" + integrity sha512-ua8BhapfP0JUJKC/zV9yHHDW/rDoDxP4Zhn3AkA6/xT6gY7jYXJiaeyBZznYVujhZZET+UgcbZiQ7sN3WqcImg== dependencies: globby "^11.0.1" graceful-fs "^4.2.4" @@ -3364,17 +3469,22 @@ del@^6.0.0: delayed-stream@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" - integrity sha1-3zrhmayt+31ECqrgsp4icrJOxhk= + integrity sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ== + +depd@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/depd/-/depd-2.0.0.tgz#b696163cc757560d09cf22cc8fad1571b79e76df" + integrity sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw== depd@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9" - integrity sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak= + integrity sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ== -destroy@~1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.0.4.tgz#978857442c44749e4206613e37946205826abd80" - integrity sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA= +destroy@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.2.0.tgz#4803735509ad8be552934c67df614f94e66fa015" + integrity sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg== detab@2.0.4: version "2.0.4" @@ -3397,12 +3507,12 @@ detect-port-alt@^1.1.6: debug "^2.6.0" detect-port@^1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/detect-port/-/detect-port-1.3.0.tgz#d9c40e9accadd4df5cac6a782aefd014d573d1f1" - integrity sha512-E+B1gzkl2gqxt1IhUzwjrxBKRqx1UzC3WLONHinn8S3T6lwV/agVCyitiFOsGJ/eYuEUBvD71MZHy3Pv1G9doQ== + version "1.5.1" + resolved "https://registry.yarnpkg.com/detect-port/-/detect-port-1.5.1.tgz#451ca9b6eaf20451acb0799b8ab40dff7718727b" + integrity sha512-aBzdj76lueB6uUst5iAs7+0H/oOjqI5D16XUWxlWMIMROhcM0rfsNVk93zTngq1dDNpoXRr++Sus7ETAExppAQ== dependencies: address "^1.0.1" - debug "^2.6.0" + debug "4" dir-glob@^3.0.1: version "3.0.1" @@ -3411,50 +3521,17 @@ dir-glob@^3.0.1: dependencies: path-type "^4.0.0" -direction@^1.0.0: - version "1.0.4" - resolved "https://registry.yarnpkg.com/direction/-/direction-1.0.4.tgz#2b86fb686967e987088caf8b89059370d4837442" - integrity sha512-GYqKi1aH7PJXxdhTeZBFrg8vUBeKXi+cNprXsC1kpJcbcVnV9wBsrOu1cQEdG0WeQwlfHiy3XvnKfIrJ2R0NzQ== - dns-equal@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/dns-equal/-/dns-equal-1.0.0.tgz#b39e7f1da6eb0a75ba9c17324b34753c47e0654d" - integrity sha1-s55/HabrCnW6nBcySzR1PEfgZU0= - -dns-packet@^1.3.1: - version "1.3.4" - resolved "https://registry.yarnpkg.com/dns-packet/-/dns-packet-1.3.4.tgz#e3455065824a2507ba886c55a89963bb107dec6f" - integrity sha512-BQ6F4vycLXBvdrJZ6S3gZewt6rcrks9KBgM9vrhW+knGRqc8uEdT7fuCwloc7nny5xNoMJ17HGH0R/6fpo8ECA== - dependencies: - ip "^1.1.0" - safe-buffer "^5.0.1" - -dns-txt@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/dns-txt/-/dns-txt-2.0.2.tgz#b91d806f5d27188e4ab3e7d107d881a1cc4642b6" - integrity sha1-uR2Ab10nGI5Ks+fRB9iBocxGQrY= - dependencies: - buffer-indexof "^1.0.0" + integrity sha512-z+paD6YUQsk+AbGCEM4PrOXSss5gd66QfcVBFTKR/HpFL9jCqikS94HYwKww6fQyO7IxrIIyUu+g0Ka9tUS2Cg== -docusaurus-lunr-search@^2.1.15: - version "2.1.15" - resolved "https://registry.yarnpkg.com/docusaurus-lunr-search/-/docusaurus-lunr-search-2.1.15.tgz#e0b141ebf6226e3fb2cd7ec0a07fccee809cfc94" - integrity sha512-W37af7ziwNFstM0VNjruJi3HChPWI5BWGAAxFYpRRbMZQAZqdQtz4aZHX5E/ORrfqHWsKTGMCRWode1rb3ncQw== +dns-packet@^5.2.2: + version "5.4.0" + resolved "https://registry.yarnpkg.com/dns-packet/-/dns-packet-5.4.0.tgz#1f88477cf9f27e78a213fb6d118ae38e759a879b" + integrity sha512-EgqGeaBB8hLiHLZtp/IbaDQTL8pZ0+IvwzSHA6d7VyMDM+B9hgddEMa9xjK5oYnw0ci0JQ6g2XCD7/f6cafU6g== dependencies: - autocomplete.js "^0.37.0" - classnames "^2.2.6" - gauge "^3.0.0" - hast-util-select "^4.0.0" - hast-util-to-text "^2.0.0" - hogan.js "^3.0.2" - lunr "^2.3.8" - lunr-languages "^1.4.0" - minimatch "^3.0.4" - object-assign "^4.1.1" - rehype-parse "^7.0.1" - to-vfile "^6.1.0" - unified "^9.0.0" - unist-util-is "^4.0.2" + "@leichtgewicht/ip-codec" "^2.0.1" dom-converter@^0.2.0: version "0.2.0" @@ -3463,40 +3540,28 @@ dom-converter@^0.2.0: dependencies: utila "~0.4" -dom-serializer@0: - version "0.2.2" - resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-0.2.2.tgz#1afb81f533717175d478655debc5e332d9f9bb51" - integrity sha512-2/xPb3ORsQ42nHYiSunXkDjPLBaEj/xTwUO4B7XCZQTRk7EBtTOPaygh10YAAh2OI1Qrp6NWfpAhzswj0ydt9g== - dependencies: - domelementtype "^2.0.1" - entities "^2.0.0" - -dom-serializer@^1.0.1, dom-serializer@^1.3.2: - version "1.3.2" - resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-1.3.2.tgz#6206437d32ceefaec7161803230c7a20bc1b4d91" - integrity sha512-5c54Bk5Dw4qAxNOI1pFEizPSjVsx5+bpJKmL2kPn8JhBUq2q09tTCa3mjijun2NfK78NMouDYNMBkOrPZiS+ig== +dom-serializer@^1.0.1: + version "1.4.1" + resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-1.4.1.tgz#de5d41b1aea290215dc45a6dae8adcf1d32e2d30" + integrity sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag== dependencies: domelementtype "^2.0.1" domhandler "^4.2.0" entities "^2.0.0" -dom-serializer@~0.1.0: - version "0.1.1" - resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-0.1.1.tgz#1ec4059e284babed36eec2941d4a970a189ce7c0" - integrity sha512-l0IU0pPzLWSHBcieZbpOKgkIn3ts3vAh7ZuFyXNwJxJXk/c4Gwj9xaTJwIDVQCXawWD0qb3IzMGH5rglQaO0XA== +dom-serializer@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-2.0.0.tgz#e41b802e1eedf9f6cae183ce5e622d789d7d8e53" + integrity sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg== dependencies: - domelementtype "^1.3.0" - entities "^1.1.1" - -domelementtype@1, domelementtype@^1.3.0, domelementtype@^1.3.1: - version "1.3.1" - resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-1.3.1.tgz#d048c44b37b0d10a7f2a3d5fee3f4333d790481f" - integrity sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w== + domelementtype "^2.3.0" + domhandler "^5.0.2" + entities "^4.2.0" -domelementtype@^2.0.1, domelementtype@^2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-2.2.0.tgz#9a0b6c2782ed6a1c7323d42267183df9bd8b1d57" - integrity sha512-DtBMo82pv1dFtUmHyr48beiuq792Sxohr+8Hm9zoxklYPfa6n0Z3Byjj2IV7bmr2IyqClnqEQhfgHJJ5QF0R5A== +domelementtype@^2.0.1, domelementtype@^2.2.0, domelementtype@^2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-2.3.0.tgz#5c45e8e869952626331d7aab326d01daf65d589d" + integrity sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw== domexception@^4.0.0: version "4.0.0" @@ -3505,37 +3570,21 @@ domexception@^4.0.0: dependencies: webidl-conversions "^7.0.0" -domhandler@^2.3.0: - version "2.4.2" - resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-2.4.2.tgz#8805097e933d65e85546f726d60f5eb88b44f803" - integrity sha512-JiK04h0Ht5u/80fdLMCEmV4zkNh2BcoMFBmZ/91WtYZ8qVXSKjiw7fXMgFPnHcSZgOo3XdinHvmnDUeMf5R4wA== - dependencies: - domelementtype "1" - -domhandler@^4.0.0, domhandler@^4.2.0, domhandler@^4.3.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-4.3.0.tgz#16c658c626cf966967e306f966b431f77d4a5626" - integrity sha512-fC0aXNQXqKSFTr2wDNZDhsEYjCiYsDWl3D01kwt25hm1YIPyDGHvvi3rw+PLqHAl/m71MaiF7d5zvBr0p5UB2g== +domhandler@^4.0.0, domhandler@^4.2.0, domhandler@^4.3.1: + version "4.3.1" + resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-4.3.1.tgz#8d792033416f59d68bc03a5aa7b018c1ca89279c" + integrity sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ== dependencies: domelementtype "^2.2.0" -domutils@1.5.1: - version "1.5.1" - resolved "https://registry.yarnpkg.com/domutils/-/domutils-1.5.1.tgz#dcd8488a26f563d61079e48c9f7b7e32373682cf" - integrity sha1-3NhIiib1Y9YQeeSMn3t+Mjc2gs8= - dependencies: - dom-serializer "0" - domelementtype "1" - -domutils@^1.5.1: - version "1.7.0" - resolved "https://registry.yarnpkg.com/domutils/-/domutils-1.7.0.tgz#56ea341e834e06e6748af7a1cb25da67ea9f8c2a" - integrity sha512-Lgd2XcJ/NjEw+7tFvfKxOzCYKZsdct5lczQ2ZaQY8Djz7pfAD3Gbp8ySJWtreII/vDlMVmxwa6pHmdxIYgttDg== +domhandler@^5.0.1, domhandler@^5.0.2, domhandler@^5.0.3: + version "5.0.3" + resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-5.0.3.tgz#cc385f7f751f1d1fc650c21374804254538c7d31" + integrity sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w== dependencies: - dom-serializer "0" - domelementtype "1" + domelementtype "^2.3.0" -domutils@^2.5.2, domutils@^2.7.0, domutils@^2.8.0: +domutils@^2.5.2, domutils@^2.8.0: version "2.8.0" resolved "https://registry.yarnpkg.com/domutils/-/domutils-2.8.0.tgz#4437def5db6e2d1f5d6ee859bd95ca7d02048135" integrity sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A== @@ -3544,6 +3593,15 @@ domutils@^2.5.2, domutils@^2.7.0, domutils@^2.8.0: domelementtype "^2.2.0" domhandler "^4.2.0" +domutils@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/domutils/-/domutils-3.0.1.tgz#696b3875238338cb186b6c0612bd4901c89a4f1c" + integrity sha512-z08c1l761iKhDFtfXO04C7kTdPBLi41zwOZl00WS8b5eiaebNpY00HKbztwBq+e3vyqWNwWF3mP9YLUeqIrF+Q== + dependencies: + dom-serializer "^2.0.0" + domelementtype "^2.3.0" + domhandler "^5.0.1" + dot-case@^3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/dot-case/-/dot-case-3.0.4.tgz#9b2b670d00a431667a8a75ba29cd1b98809ce751" @@ -3560,30 +3618,40 @@ dot-prop@^5.2.0: is-obj "^2.0.0" duplexer3@^0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/duplexer3/-/duplexer3-0.1.4.tgz#ee01dd1cac0ed3cbc7fdbea37dc0a8f1ce002ce2" - integrity sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI= + version "0.1.5" + resolved "https://registry.yarnpkg.com/duplexer3/-/duplexer3-0.1.5.tgz#0b5e4d7bad5de8901ea4440624c8e1d20099217e" + integrity sha512-1A8za6ws41LQgv9HrE/66jyC5yuSjQ3L/KOpFtoBilsAK2iA2wuS5rTt1OCzIvtS2V7nVmedsUU+DGRcjBmOYA== duplexer@^0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/duplexer/-/duplexer-0.1.2.tgz#3abe43aef3835f8ae077d136ddce0f276b0400e6" integrity sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg== +eastasianwidth@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/eastasianwidth/-/eastasianwidth-0.2.0.tgz#696ce2ec0aa0e6ea93a397ffcf24aa7840c827cb" + integrity sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA== + ee-first@1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" - integrity sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0= + integrity sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow== -electron-to-chromium@^1.4.17: - version "1.4.44" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.44.tgz#8a41923afdd6ef5ddabe001626036ba5d1d64ae6" - integrity sha512-tHGWiUUmY7GABK8+DNcr474cnZDTzD8x1736SlDosVH8+/vRJeqfaIBAEHFtMjddz/0T4rKKYsxEc8BwQRdBpw== +electron-to-chromium@^1.4.251: + version "1.4.284" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.284.tgz#61046d1e4cab3a25238f6bf7413795270f125592" + integrity sha512-M8WEXFuKXMYMVr45fo8mq0wUrrJHheiKZf6BArTKk9ZBYCKJEOU5H8cdWgDT+qCVZf7Na4lVUaZsA+h6uA9+PA== emoji-regex@^8.0.0: version "8.0.0" resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== +emoji-regex@^9.2.2: + version "9.2.2" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-9.2.2.tgz#840c8803b0d8047f4ff0cf963176b32d4ef3ed72" + integrity sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg== + emojis-list@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/emojis-list/-/emojis-list-3.0.0.tgz#5570662046ad29e2e916e71aae260abdff4f6a78" @@ -3597,7 +3665,7 @@ emoticon@^3.2.0: encodeurl@~1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" - integrity sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k= + integrity sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w== end-of-stream@^1.1.0: version "1.4.4" @@ -3606,28 +3674,23 @@ end-of-stream@^1.1.0: dependencies: once "^1.4.0" -enhanced-resolve@^5.8.3: - version "5.8.3" - resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.8.3.tgz#6d552d465cce0423f5b3d718511ea53826a7b2f0" - integrity sha512-EGAbGvH7j7Xt2nc0E7D99La1OiEs8LnyimkRgwExpUMScN6O+3x9tIWs7PLQZVNx4YD+00skHXPXi1yQHpAmZA== +enhanced-resolve@^5.10.0: + version "5.10.0" + resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.10.0.tgz#0dc579c3bb2a1032e357ac45b8f3a6f3ad4fb1e6" + integrity sha512-T0yTFjdpldGY8PmuXXR0PyQ1ufZpEGiHVrp7zHKB7jdR4qlmZHhONVM5AQOAWXuF/w3dnHbEQVrNptJgt7F+cQ== dependencies: graceful-fs "^4.2.4" tapable "^2.2.0" -entities@^1.1.1, entities@~1.1.1: - version "1.1.2" - resolved "https://registry.yarnpkg.com/entities/-/entities-1.1.2.tgz#bdfa735299664dfafd34529ed4f8522a275fea56" - integrity sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w== - entities@^2.0.0: version "2.2.0" resolved "https://registry.yarnpkg.com/entities/-/entities-2.2.0.tgz#098dc90ebb83d8dffa089d55256b351d34c4da55" integrity sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A== -entities@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/entities/-/entities-3.0.1.tgz#2b887ca62585e96db3903482d336c1006c3001d4" - integrity sha512-WiyBqoomrwMdFG1e0kqvASYfnlb0lp8M5o5Fw2OFq1hNZxxcNk8Ik0Xm7LxzBhuidnZB/UtBqVCgUz3kBOP51Q== +entities@^4.2.0, entities@^4.3.0, entities@^4.4.0: + version "4.4.0" + resolved "https://registry.yarnpkg.com/entities/-/entities-4.4.0.tgz#97bdaba170339446495e653cfd2db78962900174" + integrity sha512-oYp7156SP8LkeGD0GF85ad1X9Ai79WtRsZ2gxJqtBuzH+98YUV6jkHEKlZkMbcrjJjIVJNIDP/3WL9wQkoPbWA== error-ex@^1.3.1: version "1.3.2" @@ -3654,12 +3717,12 @@ escape-goat@^2.0.0: escape-html@^1.0.3, escape-html@~1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" - integrity sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg= + integrity sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow== escape-string-regexp@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" - integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= + integrity sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg== escape-string-regexp@^4.0.0: version "4.0.0" @@ -3726,13 +3789,14 @@ eta@^1.12.3: etag@~1.8.1: version "1.8.1" resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887" - integrity sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc= + integrity sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg== -eval@^0.1.4: - version "0.1.6" - resolved "https://registry.yarnpkg.com/eval/-/eval-0.1.6.tgz#9620d7d8c85515e97e6b47c5814f46ae381cb3cc" - integrity sha512-o0XUw+5OGkXw4pJZzQoXUk+H87DHuC+7ZE//oSrRGtatTmr12oTnLfg6QOq9DyTt0c/p4TwzgmkKrBzWTSizyQ== +eval@^0.1.8: + version "0.1.8" + resolved "https://registry.yarnpkg.com/eval/-/eval-0.1.8.tgz#2b903473b8cc1d1989b83a1e7923f883eb357f85" + integrity sha512-EzV94NYKoO09GLXGjXj9JIlXijVck4ONSr5wiCWDvhsvj5jxSrzTmRU/9C1DyB6uToszLs8aifA6NQ7lEQdvFw== dependencies: + "@types/node" "*" require-like ">= 0.1.1" eventemitter3@^4.0.0: @@ -3760,38 +3824,39 @@ execa@^5.0.0: signal-exit "^3.0.3" strip-final-newline "^2.0.0" -express@^4.17.1: - version "4.17.2" - resolved "https://registry.yarnpkg.com/express/-/express-4.17.2.tgz#c18369f265297319beed4e5558753cc8c1364cb3" - integrity sha512-oxlxJxcQlYwqPWKVJJtvQiwHgosH/LrLSPA+H4UxpyvSS6jC5aH+5MoHFM+KABgTOt0APue4w66Ha8jCUo9QGg== +express@^4.17.3: + version "4.18.2" + resolved "https://registry.yarnpkg.com/express/-/express-4.18.2.tgz#3fabe08296e930c796c19e3c516979386ba9fd59" + integrity sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ== dependencies: - accepts "~1.3.7" + accepts "~1.3.8" array-flatten "1.1.1" - body-parser "1.19.1" + body-parser "1.20.1" content-disposition "0.5.4" content-type "~1.0.4" - cookie "0.4.1" + cookie "0.5.0" cookie-signature "1.0.6" debug "2.6.9" - depd "~1.1.2" + depd "2.0.0" encodeurl "~1.0.2" escape-html "~1.0.3" etag "~1.8.1" - finalhandler "~1.1.2" + finalhandler "1.2.0" fresh "0.5.2" + http-errors "2.0.0" merge-descriptors "1.0.1" methods "~1.1.2" - on-finished "~2.3.0" + on-finished "2.4.1" parseurl "~1.3.3" path-to-regexp "0.1.7" proxy-addr "~2.0.7" - qs "6.9.6" + qs "6.11.0" range-parser "~1.2.1" safe-buffer "5.2.1" - send "0.17.2" - serve-static "1.14.2" + send "0.18.0" + serve-static "1.15.0" setprototypeof "1.2.0" - statuses "~1.5.0" + statuses "2.0.1" type-is "~1.6.18" utils-merge "1.0.1" vary "~1.1.2" @@ -3799,7 +3864,7 @@ express@^4.17.1: extend-shallow@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-2.0.1.tgz#51af7d614ad9a9f610ea1bafbb989d6b1c56890f" - integrity sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8= + integrity sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug== dependencies: is-extendable "^0.1.0" @@ -3813,10 +3878,10 @@ fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== -fast-glob@^3.2.7, fast-glob@^3.2.9: - version "3.2.10" - resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.10.tgz#2734f83baa7f43b7fd41e13bc34438f4ffe284ee" - integrity sha512-s9nFhFnvR63wls6/kM88kQqDhMu0AfdjqouE2l5GVQPbqLgyFjjU5ry/r2yKsJxpb9Py1EYNqieFrmMaX4v++A== +fast-glob@^3.2.11, fast-glob@^3.2.9: + version "3.2.12" + resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.12.tgz#7f39ec99c2e6ab030337142da9e0c18f37afae80" + integrity sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w== dependencies: "@nodelib/fs.stat" "^2.0.2" "@nodelib/fs.walk" "^1.2.3" @@ -3832,12 +3897,12 @@ fast-json-stable-stringify@^2.0.0: fast-levenshtein@~2.0.6: version "2.0.6" resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" - integrity sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc= + integrity sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw== fast-url-parser@1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/fast-url-parser/-/fast-url-parser-1.1.3.tgz#f4af3ea9f34d8a271cf58ad2b3759f431f0b318d" - integrity sha1-9K8+qfNNiicc9YrSs3WfQx8LMY0= + integrity sha512-5jOCVXADYNuRkKFzNJ0dCCewsZiYo0dz8QNYljkOpFC6r2U4OBmKtvm/Tsuh4w1YYdDqDb31a8TVhBJ2OJKdqQ== dependencies: punycode "^1.3.2" @@ -3868,11 +3933,11 @@ fbjs-css-vars@^1.0.0: integrity sha512-b2XGFAFdWZWg0phtAWLHCk836A1Xann+I+Dgd3Gk64MHKZO44FfoD1KxyvbSh0qZsIoXQGGlVztIY+oitJPpRQ== fbjs@^3.0.0, fbjs@^3.0.1: - version "3.0.2" - resolved "https://registry.yarnpkg.com/fbjs/-/fbjs-3.0.2.tgz#dfae08a85c66a58372993ce2caf30863f569ff94" - integrity sha512-qv+boqYndjElAJHNN3NoM8XuwQZ1j2m3kEvTgdle8IDjr6oUbkEpvABWtj/rQl3vq4ew7dnElBxL4YJAwTVqQQ== + version "3.0.4" + resolved "https://registry.yarnpkg.com/fbjs/-/fbjs-3.0.4.tgz#e1871c6bd3083bac71ff2da868ad5067d37716c6" + integrity sha512-ucV0tDODnGV3JCnnkmoszb5lf4bNpzjv80K41wd4k798Etq+UYD0y0TIfalLjZoKgjive6/adkRnszwapiDgBQ== dependencies: - cross-fetch "^3.0.4" + cross-fetch "^3.1.5" fbjs-css-vars "^1.0.0" loose-envify "^1.0.0" object-assign "^4.1.0" @@ -3907,17 +3972,17 @@ fill-range@^7.0.1: dependencies: to-regex-range "^5.0.1" -finalhandler@~1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.1.2.tgz#b7e7d000ffd11938d0fdb053506f6ebabe9f587d" - integrity sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA== +finalhandler@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.2.0.tgz#7d23fe5731b207b4640e4fcd00aec1f9207a7b32" + integrity sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg== dependencies: debug "2.6.9" encodeurl "~1.0.2" escape-html "~1.0.3" - on-finished "~2.3.0" + on-finished "2.4.1" parseurl "~1.3.3" - statuses "~1.5.0" + statuses "2.0.1" unpipe "~1.0.0" find-cache-dir@^3.3.1: @@ -3960,15 +4025,15 @@ flux@^4.0.1: fbemitter "^3.0.0" fbjs "^3.0.1" -follow-redirects@^1.0.0, follow-redirects@^1.14.0: - version "1.14.7" - resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.14.7.tgz#2004c02eb9436eee9a21446a6477debf17e81685" - integrity sha512-+hbxoLbFMbRKDwohX8GkTataGqO6Jb7jGwpAlwgy2bIz25XtRm7KEzJM76R1WiNT5SwZkX4Y75SwBolkpmE7iQ== +follow-redirects@^1.0.0, follow-redirects@^1.14.7: + version "1.15.2" + resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.2.tgz#b460864144ba63f2681096f274c4e57026da2c13" + integrity sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA== fork-ts-checker-webpack-plugin@^6.5.0: - version "6.5.0" - resolved "https://registry.yarnpkg.com/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-6.5.0.tgz#0282b335fa495a97e167f69018f566ea7d2a2b5e" - integrity sha512-cS178Y+xxtIjEUorcHddKS7yCMlrDPV31mt47blKKRfMd70Kxu5xruAFE2o9sDY6wVC5deuob/u/alD04YYHnw== + version "6.5.2" + resolved "https://registry.yarnpkg.com/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-6.5.2.tgz#4f67183f2f9eb8ba7df7177ce3cf3e75cdafb340" + integrity sha512-m5cUmF30xkZ7h4tWUgTAcEaKmUW7tfyUyTqNNOz7OxWJ0v1VWKTcOvH8FWHUwSjlW/356Ijc9vi3XfcPstpQKA== dependencies: "@babel/code-frame" "^7.8.3" "@types/json-schema" "^7.0.5" @@ -3998,20 +4063,20 @@ forwarded@0.2.0: resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.2.0.tgz#2269936428aad4c15c7ebe9779a84bf0b2a81811" integrity sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow== -fraction.js@^4.1.2: - version "4.1.2" - resolved "https://registry.yarnpkg.com/fraction.js/-/fraction.js-4.1.2.tgz#13e420a92422b6cf244dff8690ed89401029fbe8" - integrity sha512-o2RiJQ6DZaR/5+Si0qJUIy637QMRudSi9kU/FFzx9EZazrIdnBgpU+3sEWCxAVhH2RtxW2Oz+T4p2o8uOPVcgA== +fraction.js@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/fraction.js/-/fraction.js-4.2.0.tgz#448e5109a313a3527f5a3ab2119ec4cf0e0e2950" + integrity sha512-MhLuK+2gUcnZe8ZHlaaINnQLl0xRIGRfcGk2yl8xoQAfHrSsL3rYu6FCmBdkdbhc9EPlwyGHewaRsvwRMJtAlA== fresh@0.5.2: version "0.5.2" resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7" - integrity sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac= + integrity sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q== -fs-extra@^10.0.0: - version "10.0.0" - resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-10.0.0.tgz#9ff61b655dde53fb34a82df84bb214ce802e17c1" - integrity sha512-C5owb14u9eJwizKGdchcDUQeFtlSHHthBk8pbX9Vc1PFZrLombudjDnNns88aYslCyF6IY5SUw3Roz6xShcEIQ== +fs-extra@^10.1.0: + version "10.1.0" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-10.1.0.tgz#02873cfbc4084dde127eaa5f9905eef2325d1abf" + integrity sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ== dependencies: graceful-fs "^4.2.0" jsonfile "^6.0.1" @@ -4027,7 +4092,7 @@ fs-extra@^9.0.0: jsonfile "^6.0.1" universalify "^2.0.0" -fs-monkey@1.0.3: +fs-monkey@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/fs-monkey/-/fs-monkey-1.0.3.tgz#ae3ac92d53bb328efe0e9a1d9541f6ad8d48e2d3" integrity sha512-cybjIfiiE+pTWicSCLFHSrXZ6EilF30oh91FDP9S2B051prEa7QWfrVTQm10/dDpswBDXZugPa1Ogu8Yh+HV0Q== @@ -4035,7 +4100,7 @@ fs-monkey@1.0.3: fs.realpath@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" - integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8= + integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw== fsevents@~2.3.2: version "2.3.2" @@ -4047,34 +4112,19 @@ function-bind@^1.1.1: resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== -gauge@^3.0.0: - version "3.0.2" - resolved "https://registry.yarnpkg.com/gauge/-/gauge-3.0.2.tgz#03bf4441c044383908bcfa0656ad91803259b395" - integrity sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q== - dependencies: - aproba "^1.0.3 || ^2.0.0" - color-support "^1.1.2" - console-control-strings "^1.0.0" - has-unicode "^2.0.1" - object-assign "^4.1.1" - signal-exit "^3.0.0" - string-width "^4.2.3" - strip-ansi "^6.0.1" - wide-align "^1.1.2" - gensync@^1.0.0-beta.1, gensync@^1.0.0-beta.2: version "1.0.0-beta.2" resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.2.tgz#32a6ee76c3d7f52d46b2b1ae5d93fea8580a25e0" integrity sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg== -get-intrinsic@^1.0.2: - version "1.1.1" - resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.1.1.tgz#15f59f376f855c446963948f0d24cd3637b4abc6" - integrity sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q== +get-intrinsic@^1.0.2, get-intrinsic@^1.1.1: + version "1.1.3" + resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.1.3.tgz#063c84329ad93e83893c7f4f243ef63ffa351385" + integrity sha512-QJVz1Tj7MS099PevUG5jvnt9tSkXN8K14dxQlikJuPt4uD9hHAHjLyLBiLR5zELelBdD9QNRAXZzsJx0WaDL9A== dependencies: function-bind "^1.1.1" has "^1.0.3" - has-symbols "^1.0.1" + has-symbols "^1.0.3" get-own-enumerable-property-symbols@^3.0.0: version "3.0.2" @@ -4101,14 +4151,14 @@ get-stream@^6.0.0: integrity sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg== github-slugger@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/github-slugger/-/github-slugger-1.4.0.tgz#206eb96cdb22ee56fdc53a28d5a302338463444e" - integrity sha512-w0dzqw/nt51xMVmlaV1+JRzN+oCa1KfcgGEWhxUG16wbdA+Xnt/yoFO8Z8x/V82ZcZ0wy6ln9QDup5avbhiDhQ== + version "1.5.0" + resolved "https://registry.yarnpkg.com/github-slugger/-/github-slugger-1.5.0.tgz#17891bbc73232051474d68bd867a34625c955f7d" + integrity sha512-wIh+gKBI9Nshz2o46B0B3f5k/W+WI9ZAv6y5Dn5WJ5SK1t0TnDimB4WE5rmTD05ZAIn8HALCZVmCsvj0w0v0lw== gleap@^7.0.29: - version "7.0.29" - resolved "https://registry.yarnpkg.com/gleap/-/gleap-7.0.29.tgz#d8da12d06aead1b9ef75cb4c7f9778395c188c9c" - integrity sha512-2vRs+ZiRFDtyri1q/VznAE+fTAD1TOWjfY75J/2tDeS8fDg8qiFVQuNS0Lkgll1AOiGPojbG7AZ5ZusCTExhRA== + version "7.0.31" + resolved "https://registry.yarnpkg.com/gleap/-/gleap-7.0.31.tgz#c650f96ddf24f7eecaa6128e8003478d347316ba" + integrity sha512-pTEVt/cK280Jb5cm82LkOKgR9wgy91T1SaANvkyGNMq9+QE3BDSsaKC99nfd+BkDz8erflkLbuc/YYam09yXUw== glob-parent@^5.1.2, glob-parent@~5.1.2: version "5.1.2" @@ -4130,21 +4180,21 @@ glob-to-regexp@^0.4.1: integrity sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw== glob@^7.0.0, glob@^7.1.3, glob@^7.1.6: - version "7.2.0" - resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.0.tgz#d15535af7732e02e948f4c41628bd910293f6023" - integrity sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q== + version "7.2.3" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b" + integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q== dependencies: fs.realpath "^1.0.0" inflight "^1.0.4" inherits "2" - minimatch "^3.0.4" + minimatch "^3.1.1" once "^1.3.0" path-is-absolute "^1.0.0" global-dirs@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/global-dirs/-/global-dirs-3.0.0.tgz#70a76fe84ea315ab37b1f5576cbde7d48ef72686" - integrity sha512-v8ho2DS5RiCjftj1nD9NmnfaOzTdud7RRnVd9kFNOjqZbISlx5DQ+OrTkywgd0dIt7oFCvKetZSHoHcP3sDdiA== + version "3.0.1" + resolved "https://registry.yarnpkg.com/global-dirs/-/global-dirs-3.0.1.tgz#0c488971f066baceda21447aecb1a8b911d22485" + integrity sha512-NBcGGFbBA9s1VzD41QXDG+3++t9Mn5t1FpLdhESY6oKY4gYTFpX4wO3sqGUa0Srjtbfj3szX0RnemmrVRUdULA== dependencies: ini "2.0.0" @@ -4169,7 +4219,7 @@ globals@^11.1.0: resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e" integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== -globby@^11.0.1, globby@^11.0.2, globby@^11.0.4: +globby@^11.0.1, globby@^11.0.4, globby@^11.1.0: version "11.1.0" resolved "https://registry.yarnpkg.com/globby/-/globby-11.1.0.tgz#bd4be98bb042f83d796f7e3811991fbe82a0d34b" integrity sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g== @@ -4181,15 +4231,14 @@ globby@^11.0.1, globby@^11.0.2, globby@^11.0.4: merge2 "^1.4.1" slash "^3.0.0" -globby@^12.0.2: - version "12.2.0" - resolved "https://registry.yarnpkg.com/globby/-/globby-12.2.0.tgz#2ab8046b4fba4ff6eede835b29f678f90e3d3c22" - integrity sha512-wiSuFQLZ+urS9x2gGPl1H5drc5twabmm4m2gTR27XDFyjUHJUNsS8o/2aKyIF6IoBaR630atdher0XJ5g6OMmA== +globby@^13.1.1: + version "13.1.2" + resolved "https://registry.yarnpkg.com/globby/-/globby-13.1.2.tgz#29047105582427ab6eca4f905200667b056da515" + integrity sha512-LKSDZXToac40u8Q1PQtZihbNdTYSNMuWe+K5l+oa6KgDzSvVrHXlJy40hUP522RjAIoNLJYBJi7ow+rbFpIhHQ== dependencies: - array-union "^3.0.1" dir-glob "^3.0.1" - fast-glob "^3.2.7" - ignore "^5.1.9" + fast-glob "^3.2.11" + ignore "^5.2.0" merge2 "^1.4.1" slash "^4.0.0" @@ -4211,9 +4260,9 @@ got@^9.6.0: url-parse-lax "^3.0.0" graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.4, graceful-fs@^4.2.6, graceful-fs@^4.2.9: - version "4.2.9" - resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.9.tgz#041b05df45755e587a24942279b9d113146e1c96" - integrity sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ== + version "4.2.10" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.10.tgz#147d3a006da4ca3ce14728c7aefc287c367d7a6c" + integrity sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA== gray-matter@^4.0.3: version "4.0.3" @@ -4240,29 +4289,24 @@ handle-thing@^2.0.0: has-flag@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" - integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0= + integrity sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw== has-flag@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== -has-symbols@^1.0.1, has-symbols@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.2.tgz#165d3070c00309752a1236a479331e3ac56f1423" - integrity sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw== - -has-tostringtag@^1.0.0: +has-property-descriptors@^1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/has-tostringtag/-/has-tostringtag-1.0.0.tgz#7e133818a7d394734f941e73c3d3f9291e658b25" - integrity sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ== + resolved "https://registry.yarnpkg.com/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz#610708600606d36961ed04c196193b6a607fa861" + integrity sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ== dependencies: - has-symbols "^1.0.2" + get-intrinsic "^1.1.1" -has-unicode@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9" - integrity sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk= +has-symbols@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.3.tgz#bb7b2c4349251dce87b125f7bdf874aa7c8b39f8" + integrity sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A== has-yarn@^2.1.0: version "2.1.0" @@ -4290,24 +4334,13 @@ hast-to-hyperscript@^9.0.0: web-namespaces "^1.0.0" hast-util-from-dom@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/hast-util-from-dom/-/hast-util-from-dom-4.0.1.tgz#07840f288a24a38148428699454859d3e4064607" - integrity sha512-cR54EKU5PnR6WL4nGn+wuv/IrNiFEVaPMMODys5dm7tPktyYY0L+Jp3X6UTjxb1ewN1u5GmMb+O7hbDxdJChIg== + version "4.1.0" + resolved "https://registry.yarnpkg.com/hast-util-from-dom/-/hast-util-from-dom-4.1.0.tgz#8a09b3bb9c624371e3d5fae114678f663f928d06" + integrity sha512-0EMIYQVIhRfiC1LVdTsvM4yTY0rM/v63wwoYmOYV02mIOASYeQrfQekG4Jhge2kOAMaNFbvppUma47rbeWWE5Q== dependencies: hastscript "^7.0.0" web-namespaces "^2.0.0" -hast-util-from-parse5@^5.0.0: - version "5.0.3" - resolved "https://registry.yarnpkg.com/hast-util-from-parse5/-/hast-util-from-parse5-5.0.3.tgz#3089dc0ee2ccf6ec8bc416919b51a54a589e097c" - integrity sha512-gOc8UB99F6eWVWFtM9jUikjN7QkWxB3nY0df5Z0Zq1/Nkwl5V4hAAsl0tmwlgWl/1shlTF8DnNYLO8X6wRV9pA== - dependencies: - ccount "^1.0.3" - hastscript "^5.0.0" - property-information "^5.0.0" - web-namespaces "^1.1.2" - xtend "^4.0.1" - hast-util-from-parse5@^6.0.0: version "6.0.1" resolved "https://registry.yarnpkg.com/hast-util-from-parse5/-/hast-util-from-parse5-6.0.1.tgz#554e34abdeea25ac76f5bd950a1f0180e0b3bc2a" @@ -4320,11 +4353,6 @@ hast-util-from-parse5@^6.0.0: vfile-location "^3.2.0" web-namespaces "^1.0.0" -hast-util-has-property@^1.0.0: - version "1.0.4" - resolved "https://registry.yarnpkg.com/hast-util-has-property/-/hast-util-has-property-1.0.4.tgz#9f137565fad6082524b382c1e7d7d33ca5059f36" - integrity sha512-ghHup2voGfgFoHMGnaLHOjbYFACKrRh9KFttdCzMCbFoBMJXiNi2+XTrPP8+q6cDJM/RSqlCfVWrjp1H201rZg== - hast-util-is-element@1.1.0, hast-util-is-element@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/hast-util-is-element/-/hast-util-is-element-1.1.0.tgz#3b3ed5159a2707c6137b48637fbfe068e175a425" @@ -4366,26 +4394,6 @@ hast-util-raw@6.0.1: xtend "^4.0.0" zwitch "^1.0.0" -hast-util-select@^4.0.0: - version "4.0.2" - resolved "https://registry.yarnpkg.com/hast-util-select/-/hast-util-select-4.0.2.tgz#ae3ef2860e02cda2ad3a2e72b47c1f5e8f44e9e7" - integrity sha512-8EEG2//bN5rrzboPWD2HdS3ugLijNioS1pqOTIolXNf67xxShYw4SQEmVXd3imiBG+U2bC2nVTySr/iRAA7Cjg== - dependencies: - bcp-47-match "^1.0.0" - comma-separated-tokens "^1.0.0" - css-selector-parser "^1.0.0" - direction "^1.0.0" - hast-util-has-property "^1.0.0" - hast-util-is-element "^1.0.0" - hast-util-to-string "^1.0.0" - hast-util-whitespace "^1.0.0" - not "^0.1.0" - nth-check "^2.0.0" - property-information "^5.0.0" - space-separated-tokens "^1.0.0" - unist-util-visit "^2.0.0" - zwitch "^1.0.0" - hast-util-to-parse5@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/hast-util-to-parse5/-/hast-util-to-parse5-6.0.0.tgz#1ec44650b631d72952066cea9b1445df699f8479" @@ -4397,11 +4405,6 @@ hast-util-to-parse5@^6.0.0: xtend "^4.0.0" zwitch "^1.0.0" -hast-util-to-string@^1.0.0: - version "1.0.4" - resolved "https://registry.yarnpkg.com/hast-util-to-string/-/hast-util-to-string-1.0.4.tgz#9b24c114866bdb9478927d7e9c36a485ac728378" - integrity sha512-eK0MxRX47AV2eZ+Lyr18DCpQgodvaS3fAQO2+b9Two9F5HEoRPhiUMNzoXArMJfZi2yieFzUBMRl3HNJ3Jus3w== - hast-util-to-text@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/hast-util-to-text/-/hast-util-to-text-2.0.1.tgz#04f2e065642a0edb08341976084aa217624a0f8b" @@ -4420,21 +4423,6 @@ hast-util-to-text@^3.1.0: hast-util-is-element "^2.0.0" unist-util-find-after "^4.0.0" -hast-util-whitespace@^1.0.0: - version "1.0.4" - resolved "https://registry.yarnpkg.com/hast-util-whitespace/-/hast-util-whitespace-1.0.4.tgz#e4fe77c4a9ae1cb2e6c25e02df0043d0164f6e41" - integrity sha512-I5GTdSfhYfAPNztx2xJRQpG8cuDSNt599/7YUn7Gx/WxNMsG+a835k97TDkFgk123cwjfwINaZknkKkphx/f2A== - -hastscript@^5.0.0: - version "5.1.2" - resolved "https://registry.yarnpkg.com/hastscript/-/hastscript-5.1.2.tgz#bde2c2e56d04c62dd24e8c5df288d050a355fb8a" - integrity sha512-WlztFuK+Lrvi3EggsqOkQ52rKbxkXL3RwB6t5lwoa8QLMemoWfBuL43eDrwOamJyR7uKQKdmKYaBH1NZBiIRrQ== - dependencies: - comma-separated-tokens "^1.0.0" - hast-util-parse-selector "^2.0.0" - property-information "^5.0.0" - space-separated-tokens "^1.0.0" - hastscript@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/hastscript/-/hastscript-6.0.0.tgz#e8768d7eac56c3fdeac8a92830d58e811e5bf640" @@ -4447,9 +4435,9 @@ hastscript@^6.0.0: space-separated-tokens "^1.0.0" hastscript@^7.0.0: - version "7.0.2" - resolved "https://registry.yarnpkg.com/hastscript/-/hastscript-7.0.2.tgz#d811fc040817d91923448a28156463b2e40d590a" - integrity sha512-uA8ooUY4ipaBvKcMuPehTAB/YfFLSSzCwFSwT6ltJbocFUKH/GDHLN+tflq7lSRf9H86uOuxOFkh1KgIy3Gg2g== + version "7.1.0" + resolved "https://registry.yarnpkg.com/hastscript/-/hastscript-7.1.0.tgz#e402ed48f46161cf2f093badbff30583a5c3c315" + integrity sha512-uBjaTTLN0MkCZxY/R2fWUOcu7FRtUVzKRO5P/RAfgsu3yFiMB1JWCO4AjeVkgHxAira1f2UecHK5WfS9QurlWA== dependencies: "@types/hast" "^2.0.0" comma-separated-tokens "^2.0.0" @@ -4474,14 +4462,6 @@ history@^4.9.0: tiny-warning "^1.0.0" value-equal "^1.0.1" -hogan.js@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/hogan.js/-/hogan.js-3.0.2.tgz#4cd9e1abd4294146e7679e41d7898732b02c7bfd" - integrity sha1-TNnhq9QpQUbnZ55B14mHMrAse/0= - dependencies: - mkdirp "0.3.0" - nopt "1.0.10" - hoist-non-react-statics@^3.1.0: version "3.3.2" resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz#ece0acaf71d62c2969c2ec59feff42a4b1a85b45" @@ -4492,7 +4472,7 @@ hoist-non-react-statics@^3.1.0: hpack.js@^2.1.6: version "2.1.6" resolved "https://registry.yarnpkg.com/hpack.js/-/hpack.js-2.1.6.tgz#87774c0949e513f42e84575b3c45681fade2a0b2" - integrity sha1-h3dMCUnlE/QuhFdbPEVoH63ioLI= + integrity sha512-zJxVehUdMGIKsRaNt7apO2Gqp0BdqW5yaiGHXXmbpvxgBYVZnAql+BJb4RO5ad2MgpbZKn5G6nMnegrH1FcNYQ== dependencies: inherits "^2.0.1" obuf "^1.0.0" @@ -4507,11 +4487,11 @@ html-encoding-sniffer@^3.0.0: whatwg-encoding "^2.0.0" html-entities@^2.3.2: - version "2.3.2" - resolved "https://registry.yarnpkg.com/html-entities/-/html-entities-2.3.2.tgz#760b404685cb1d794e4f4b744332e3b00dcfe488" - integrity sha512-c3Ab/url5ksaT0WyleslpBEthOzWhrjQbg75y7XUsfSzi3Dgzt0l8w5e7DylRn15MTlMMD58dTfzddNS2kcAjQ== + version "2.3.3" + resolved "https://registry.yarnpkg.com/html-entities/-/html-entities-2.3.3.tgz#117d7626bece327fc8baace8868fa6f5ef856e46" + integrity sha512-DV5Ln36z34NNTDgnz0EWGBLZENelNAtkiFA4kyNOG2tDI6Mz1uSWiq1wAKdyjnJwyDiDO7Fa2SO1CTxPXL8VxA== -html-minifier-terser@^6.0.2: +html-minifier-terser@^6.0.2, html-minifier-terser@^6.1.0: version "6.1.0" resolved "https://registry.yarnpkg.com/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz#bfc818934cc07918f6b3669f5774ecdfd48f32ab" integrity sha512-YXxSlJBZTP7RS3tWnQw74ooKa6L9b9i9QYXY21eUEvhZ3u9XLfv6OnFsQq6RxkhHygsaUMvYsZRV5rU/OVNZxw== @@ -4524,17 +4504,17 @@ html-minifier-terser@^6.0.2: relateurl "^0.2.7" terser "^5.10.0" -html-tags@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/html-tags/-/html-tags-3.1.0.tgz#7b5e6f7e665e9fb41f30007ed9e0d41e97fb2140" - integrity sha512-1qYz89hW3lFDEazhjW0yVAV87lw8lVkrJocr72XmBkMKsoSVJCQx3W8BXsC7hO2qAt8BoVjYjtAcZ9perqGnNg== +html-tags@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/html-tags/-/html-tags-3.2.0.tgz#dbb3518d20b726524e4dd43de397eb0a95726961" + integrity sha512-vy7ClnArOZwCnqZgvv+ddgHgJiAFXe3Ge9ML5/mBctVJoUoYPCdxVucOywjDARn6CVoh3dRSFdPHy2sX80L0Wg== html-void-elements@^1.0.0: version "1.0.5" resolved "https://registry.yarnpkg.com/html-void-elements/-/html-void-elements-1.0.5.tgz#ce9159494e86d95e45795b166c2021c2cfca4483" integrity sha512-uE/TxKuyNIcx44cIWnjr/rfIATDH7ZaOMmstu0CwhFG1Dunhlp4OC6/NMbhiwoq5BpW0ubi303qnEk/PZj614w== -html-webpack-plugin@^5.4.0: +html-webpack-plugin@^5.5.0: version "5.5.0" resolved "https://registry.yarnpkg.com/html-webpack-plugin/-/html-webpack-plugin-5.5.0.tgz#c3911936f57681c1f9f4d8b68c158cd9dfe52f50" integrity sha512-sy88PC2cRTVxvETRgUHFrL4No3UxvcH8G1NepGhqaTT+GXN2kTamqasot0inS5hXeg1cMbFDt27zzo9p35lZVw== @@ -4545,18 +4525,6 @@ html-webpack-plugin@^5.4.0: pretty-error "^4.0.0" tapable "^2.0.0" -htmlparser2@^3.9.1: - version "3.10.1" - resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-3.10.1.tgz#bd679dc3f59897b6a34bb10749c855bb53a9392f" - integrity sha512-IgieNijUMbkDovyoKObU1DUhm1iwNYE/fuifEoEHfd1oZKZDaONBSkal7Y01shxsM49R4XaMdGez3WnF9UfiCQ== - dependencies: - domelementtype "^1.3.1" - domhandler "^2.3.0" - domutils "^1.5.1" - entities "^1.1.1" - inherits "^2.0.1" - readable-stream "^3.1.1" - htmlparser2@^6.1.0: version "6.1.0" resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-6.1.0.tgz#c4d762b6c3371a05dbe65e94ae43a9f845fb8fb7" @@ -4567,6 +4535,16 @@ htmlparser2@^6.1.0: domutils "^2.5.2" entities "^2.0.0" +htmlparser2@^8.0.1: + version "8.0.1" + resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-8.0.1.tgz#abaa985474fcefe269bc761a779b544d7196d010" + integrity sha512-4lVbmc1diZC7GUJQtRQ5yBAeUCL1exyMwmForWkRLnwyzWBFxN633SALPMGYaWZvKe9j1pRZJpauvmxENSp/EA== + dependencies: + domelementtype "^2.3.0" + domhandler "^5.0.2" + domutils "^3.0.1" + entities "^4.3.0" + http-cache-semantics@^4.0.0: version "4.1.0" resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz#49e91c5cbf36c9b94bcfcd71c23d5249ec74e390" @@ -4575,23 +4553,23 @@ http-cache-semantics@^4.0.0: http-deceiver@^1.2.7: version "1.2.7" resolved "https://registry.yarnpkg.com/http-deceiver/-/http-deceiver-1.2.7.tgz#fa7168944ab9a519d337cb0bec7284dc3e723d87" - integrity sha1-+nFolEq5pRnTN8sL7HKE3D5yPYc= + integrity sha512-LmpOGxTfbpgtGVxJrj5k7asXHCgNZp5nLfp+hWc8QQRqtb7fUy6kRY3BO1h9ddF6yIPYUARgxGOwB42DnxIaNw== -http-errors@1.8.1: - version "1.8.1" - resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.8.1.tgz#7c3f28577cbc8a207388455dbd62295ed07bd68c" - integrity sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g== +http-errors@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-2.0.0.tgz#b7774a1486ef73cf7667ac9ae0858c012c57b9d3" + integrity sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ== dependencies: - depd "~1.1.2" + depd "2.0.0" inherits "2.0.4" setprototypeof "1.2.0" - statuses ">= 1.5.0 < 2" + statuses "2.0.1" toidentifier "1.0.1" http-errors@~1.6.2: version "1.6.3" resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.6.3.tgz#8b55680bb4be283a0b5bf4ea2e38580be1d9320d" - integrity sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0= + integrity sha512-lks+lVC8dgGyh97jxvxeYTWQFvh4uw4yC12gVl63Cg30sjPX4wuGcdkICVXDAESr6OJGjqGA8Iz5mkeN6zlD7A== dependencies: depd "~1.1.2" inherits "2.0.3" @@ -4599,9 +4577,9 @@ http-errors@~1.6.2: statuses ">= 1.4.0 < 2" http-parser-js@>=0.5.1: - version "0.5.5" - resolved "https://registry.yarnpkg.com/http-parser-js/-/http-parser-js-0.5.5.tgz#d7c30d5d3c90d865b4a2e870181f9d6f22ac7ac5" - integrity sha512-x+JVEkO2PoM8qqpbPbOL3cqHPwerep7OwzK7Ay+sMQjKzaKCqWvjoXm5tqMP9tXWWTnTzAjIhXg+J99XYuPhPA== + version "0.5.8" + resolved "https://registry.yarnpkg.com/http-parser-js/-/http-parser-js-0.5.8.tgz#af23090d9ac4e24573de6f6aecc9d84a48bf20e3" + integrity sha512-SGeBX54F94Wgu5RH3X5jsDtf4eHyRogWX1XGT3b4HuW3tQPM4AaBzoUji/4AAJNXCEOWZ5O0DgZmJw1947gD5Q== http-proxy-agent@^5.0.0: version "5.0.0" @@ -4612,12 +4590,12 @@ http-proxy-agent@^5.0.0: agent-base "6" debug "4" -http-proxy-middleware@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/http-proxy-middleware/-/http-proxy-middleware-2.0.1.tgz#7ef3417a479fb7666a571e09966c66a39bd2c15f" - integrity sha512-cfaXRVoZxSed/BmkA7SwBVNI9Kj7HFltaE5rqYOub5kWzWZ+gofV2koVN1j2rMW7pEfSSlCHGJ31xmuyFyfLOg== +http-proxy-middleware@^2.0.3: + version "2.0.6" + resolved "https://registry.yarnpkg.com/http-proxy-middleware/-/http-proxy-middleware-2.0.6.tgz#e1a4dd6979572c7ab5a4e4b55095d1f32a74963f" + integrity sha512-ya/UeJ6HVBYxrgYotAZo1KvPWlgB48kUJLDePFeneHsVujFaW5WNj2NgWCAE//B1Dl02BIfYlpNgBy8Kf8Rjmw== dependencies: - "@types/http-proxy" "^1.17.5" + "@types/http-proxy" "^1.17.8" http-proxy "^1.18.1" is-glob "^4.0.1" is-plain-obj "^3.0.0" @@ -4633,9 +4611,9 @@ http-proxy@^1.18.1: requires-port "^1.0.0" https-proxy-agent@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz#e2a90542abb68a762e0a0850f6c9edadfd8506b2" - integrity sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA== + version "5.0.1" + resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz#c59ef224a04fe8b754f3db0063a25ea30d0005d6" + integrity sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA== dependencies: agent-base "6" debug "4" @@ -4664,29 +4642,24 @@ icss-utils@^5.0.0, icss-utils@^5.1.0: resolved "https://registry.yarnpkg.com/icss-utils/-/icss-utils-5.1.0.tgz#c6be6858abd013d768e98366ae47e25d5887b1ae" integrity sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA== -ignore@^5.1.9, ignore@^5.2.0: +ignore@^5.2.0: version "5.2.0" resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.2.0.tgz#6d3bac8fa7fe0d45d9f9be7bac2fc279577e345a" integrity sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ== image-size@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/image-size/-/image-size-1.0.1.tgz#86d6cfc2b1d19eab5d2b368d4b9194d9e48541c5" - integrity sha512-VAwkvNSNGClRw9mDHhc5Efax8PLlsOGcUTh0T/LIriC8vPA3U5PdqXWqkz406MoYHMKW8Uf9gWr05T/rYB44kQ== + version "1.0.2" + resolved "https://registry.yarnpkg.com/image-size/-/image-size-1.0.2.tgz#d778b6d0ab75b2737c1556dd631652eb963bc486" + integrity sha512-xfOoWjceHntRb3qFCrh5ZFORYH8XCdYpASltMhZ/Q0KZiOwjdE/Yl2QCiWdwD+lygV5bMCvauzgu5PxBX/Yerg== dependencies: queue "6.0.2" -immediate@^3.2.3: - version "3.3.0" - resolved "https://registry.yarnpkg.com/immediate/-/immediate-3.3.0.tgz#1aef225517836bcdf7f2a2de2600c79ff0269266" - integrity sha512-HR7EVodfFUdQCTIeySw+WDRFJlPcLOJbXfwwZ7Oom6tjsvZ3bOkCDJHehQC3nxJrv7+f9XecwazynjU8e4Vw3Q== - immer@^9.0.7: - version "9.0.12" - resolved "https://registry.yarnpkg.com/immer/-/immer-9.0.12.tgz#2d33ddf3ee1d247deab9d707ca472c8c942a0f20" - integrity sha512-lk7UNmSbAukB5B6dh9fnh5D0bJTOFKxVg2cyJWTYrWRfhLrLMBquONcUs3aFq507hNoIZEDDh8lb8UtOizSMhA== + version "9.0.16" + resolved "https://registry.yarnpkg.com/immer/-/immer-9.0.16.tgz#8e7caab80118c2b54b37ad43e05758cdefad0198" + integrity sha512-qenGE7CstVm1NrHQbMh8YaSzTZTFNP3zPqr3YU0S0UY441j4bJTg4A2Hh5KAhwgaiU6ZZ1Ar6y/2f4TblnMReQ== -import-fresh@^3.1.0, import-fresh@^3.2.1, import-fresh@^3.2.2, import-fresh@^3.3.0: +import-fresh@^3.1.0, import-fresh@^3.2.1, import-fresh@^3.3.0: version "3.3.0" resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.0.tgz#37162c25fcb9ebaa2e6e53d5b4d88ce17d9e0c2b" integrity sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw== @@ -4697,27 +4670,27 @@ import-fresh@^3.1.0, import-fresh@^3.2.1, import-fresh@^3.2.2, import-fresh@^3.3 import-lazy@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/import-lazy/-/import-lazy-2.1.0.tgz#05698e3d45c88e8d7e9d92cb0584e77f096f3e43" - integrity sha1-BWmOPUXIjo1+nZLLBYTnfwlvPkM= + integrity sha512-m7ZEHgtw69qOGw+jwxXkHlrlIPdTGkyh66zXZ1ajZbxkDBNjSY/LGbmjc7h0s2ELsUDTAhFr55TrPSSqJGPG0A== imurmurhash@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" - integrity sha1-khi5srkoojixPcT7a21XbyMUU+o= + integrity sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA== indent-string@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-4.0.0.tgz#624f8f4497d619b2d9768531d58f4122854d7251" integrity sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg== -infima@0.2.0-alpha.37: - version "0.2.0-alpha.37" - resolved "https://registry.yarnpkg.com/infima/-/infima-0.2.0-alpha.37.tgz#b87ff42d528d6d050098a560f0294fbdd12adb78" - integrity sha512-4GX7Baw+/lwS4PPW/UJNY89tWSvYG1DL6baKVdpK6mC593iRgMssxNtORMTFArLPJ/A/lzsGhRmx+z6MaMxj0Q== +infima@0.2.0-alpha.42: + version "0.2.0-alpha.42" + resolved "https://registry.yarnpkg.com/infima/-/infima-0.2.0-alpha.42.tgz#f6e86a655ad40877c6b4d11b2ede681eb5470aa5" + integrity sha512-ift8OXNbQQwtbIt6z16KnSWP7uJ/SysSMFI4F87MNRTicypfl4Pv3E2OGVv6N3nSZFJvA8imYulCBS64iyHYww== inflight@^1.0.4: version "1.0.6" resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" - integrity sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk= + integrity sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA== dependencies: once "^1.3.0" wrappy "1" @@ -4730,7 +4703,7 @@ inherits@2, inherits@2.0.4, inherits@^2.0.0, inherits@^2.0.1, inherits@^2.0.3, i inherits@2.0.3: version "2.0.3" resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" - integrity sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4= + integrity sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw== ini@2.0.0: version "2.0.0" @@ -4752,10 +4725,12 @@ interpret@^1.0.0: resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.4.0.tgz#665ab8bc4da27a774a40584e812e3e0fa45b1a1e" integrity sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA== -ip@^1.1.0: - version "1.1.5" - resolved "https://registry.yarnpkg.com/ip/-/ip-1.1.5.tgz#bdded70114290828c0a039e72ef25f5aaec4354a" - integrity sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo= +invariant@^2.2.4: + version "2.2.4" + resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.4.tgz#610f3c92c9359ce1db616e538008d23ff35158e6" + integrity sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA== + dependencies: + loose-envify "^1.0.0" ipaddr.js@1.9.1: version "1.9.1" @@ -4780,18 +4755,10 @@ is-alphanumerical@^1.0.0: is-alphabetical "^1.0.0" is-decimal "^1.0.0" -is-arguments@^1.0.4: - version "1.1.1" - resolved "https://registry.yarnpkg.com/is-arguments/-/is-arguments-1.1.1.tgz#15b3f88fda01f2a97fec84ca761a560f123efa9b" - integrity sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA== - dependencies: - call-bind "^1.0.2" - has-tostringtag "^1.0.0" - is-arrayish@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" - integrity sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0= + integrity sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg== is-binary-path@~2.1.0: version "2.1.0" @@ -4812,20 +4779,13 @@ is-ci@^2.0.0: dependencies: ci-info "^2.0.0" -is-core-module@^2.8.0: - version "2.8.1" - resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.8.1.tgz#f59fdfca701d5879d0a6b100a40aa1560ce27211" - integrity sha512-SdNCUs284hr40hFTFP6l0IfZ/RSrMXF3qgoRHd3/79unUTvrFO/JoXwkGm+5J/Oe3E/b5GsnG330uUNgRpu1PA== +is-core-module@^2.9.0: + version "2.11.0" + resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.11.0.tgz#ad4cb3e3863e814523c96f3f58d26cc570ff0144" + integrity sha512-RRjxlvLDkD1YJwDbroBHMb+cukurkDWNyHx7D3oNB5x9rb5ogcksMC5wHCadcXoo67gVr/+3GFySh3134zi6rw== dependencies: has "^1.0.3" -is-date-object@^1.0.1: - version "1.0.5" - resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.5.tgz#0841d5536e724c25597bf6ea62e1bd38298df31f" - integrity sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ== - dependencies: - has-tostringtag "^1.0.0" - is-decimal@^1.0.0: version "1.0.4" resolved "https://registry.yarnpkg.com/is-decimal/-/is-decimal-1.0.4.tgz#65a3a5958a1c5b63a706e1b333d7cd9f630d3fa5" @@ -4839,12 +4799,12 @@ is-docker@^2.0.0, is-docker@^2.1.1: is-extendable@^0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-0.1.1.tgz#62b110e289a471418e3ec36a617d472e301dfc89" - integrity sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik= + integrity sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw== is-extglob@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" - integrity sha1-qIwCU1eR8C7TfHahueqXc8gz+MI= + integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ== is-fullwidth-code-point@^3.0.0: version "3.0.0" @@ -4884,7 +4844,7 @@ is-number@^7.0.0: is-obj@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-1.0.1.tgz#3e4729ac1f5fde025cd7d83a896dab9f4f67db0f" - integrity sha1-PkcprB9f3gJc19g6iW2rn09n2w8= + integrity sha512-l4RyHgRqGN4Y3+9JHVrNqO+tN0rV5My76uW5/nuO4K1b6vw5G8d/cmFjP9tRfEsdhZNt0IFdZuK/c2Vr4Nb+Qg== is-obj@^2.0.0: version "2.0.0" @@ -4912,9 +4872,9 @@ is-plain-obj@^3.0.0: integrity sha512-gwsOE28k+23GP1B6vFl1oVh/WOzmawBrKwo5Ev6wMKzPkaXaCDIQKzLnvsA42DRlbVTWorkgTKIviAKCWkfUwA== is-plain-obj@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-4.0.0.tgz#06c0999fd7574edf5a906ba5644ad0feb3a84d22" - integrity sha512-NXRbBtUdBioI73y/HmOhogw/U5msYPC9DAtGkJXeFcFWSFZw0mCUsPxk/snTuJHzNKA8kLBK4rH97RMB1BfCXw== + version "4.1.0" + resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-4.1.0.tgz#d65025edec3657ce032fd7db63c97883eaed71f0" + integrity sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg== is-plain-object@^2.0.4: version "2.0.4" @@ -4928,18 +4888,10 @@ is-potential-custom-element-name@^1.0.1: resolved "https://registry.yarnpkg.com/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz#171ed6f19e3ac554394edf78caa05784a45bebb5" integrity sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ== -is-regex@^1.0.4: - version "1.1.4" - resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.4.tgz#eef5663cd59fa4c0ae339505323df6854bb15958" - integrity sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg== - dependencies: - call-bind "^1.0.2" - has-tostringtag "^1.0.0" - is-regexp@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-regexp/-/is-regexp-1.0.0.tgz#fd2d883545c46bac5a633e7b9a09e87fa2cb5069" - integrity sha1-/S2INUXEa6xaYz57mgnof6LLUGk= + integrity sha512-7zjFAPO4/gwyQAAgRRmqeEeyIICSdmCqa3tsVHMdBzaXXRiqopZL4Cyghg/XulGWrtABTpbnYYzzIRffLkP4oA== is-root@^2.1.0: version "2.1.0" @@ -4954,7 +4906,7 @@ is-stream@^2.0.0: is-typedarray@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" - integrity sha1-5HnICFjfDBsR3dppQPlgEfzaSpo= + integrity sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA== is-whitespace-character@^1.0.0: version "1.0.4" @@ -4981,36 +4933,58 @@ is-yarn-global@^0.3.0: isarray@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf" - integrity sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8= + integrity sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ== isarray@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" - integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE= + integrity sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ== isexe@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" - integrity sha1-6PvzdNxVb/iUehDcsFctYz8s+hA= + integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw== isobject@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df" - integrity sha1-TkMekrEalzFjaqH5yNHMvP2reN8= + integrity sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg== + +jest-util@^29.3.1: + version "29.3.1" + resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-29.3.1.tgz#1dda51e378bbcb7e3bc9d8ab651445591ed373e1" + integrity sha512-7YOVZaiX7RJLv76ZfHt4nbNEzzTRiMW/IiOG7ZOKmTXmoGBxUDefgMAxQubu6WPVqP5zSzAdZG0FfLcC7HOIFQ== + dependencies: + "@jest/types" "^29.3.1" + "@types/node" "*" + chalk "^4.0.0" + ci-info "^3.2.0" + graceful-fs "^4.2.9" + picomatch "^2.2.3" + +jest-worker@^27.4.5: + version "27.5.1" + resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-27.5.1.tgz#8d146f0900e8973b106b6f73cc1e9a8cb86f8db0" + integrity sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg== + dependencies: + "@types/node" "*" + merge-stream "^2.0.0" + supports-color "^8.0.0" -jest-worker@^27.0.2, jest-worker@^27.4.1: - version "27.4.6" - resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-27.4.6.tgz#5d2d93db419566cb680752ca0792780e71b3273e" - integrity sha512-gHWJF/6Xi5CTG5QCvROr6GcmpIqNYpDJyc8A1h/DyXqH1tD6SnRCM0d3U5msV31D2LB/U+E0M+W4oyvKV44oNw== +jest-worker@^29.1.2: + version "29.3.1" + resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-29.3.1.tgz#e9462161017a9bb176380d721cab022661da3d6b" + integrity sha512-lY4AnnmsEWeiXirAIA0c9SDPbuCBq8IYuDVL8PMm0MZ2PEs2yPvRA/J64QBXuZp7CYKrDM/rmNrc9/i3KJQncw== dependencies: "@types/node" "*" + jest-util "^29.3.1" merge-stream "^2.0.0" supports-color "^8.0.0" -joi@^17.4.0, joi@^17.4.2: - version "17.5.0" - resolved "https://registry.yarnpkg.com/joi/-/joi-17.5.0.tgz#7e66d0004b5045d971cf416a55fb61d33ac6e011" - integrity sha512-R7hR50COp7StzLnDi4ywOXHrBrgNXuUUfJWIR5lPY5Bm/pOD3jZaTwpluUXVLRWcoWZxkrHBBJ5hLxgnlehbdw== +joi@^17.6.0: + version "17.7.0" + resolved "https://registry.yarnpkg.com/joi/-/joi-17.7.0.tgz#591a33b1fe1aca2bc27f290bcad9b9c1c570a6b3" + integrity sha512-1/ugc8djfn93rTE3WRKdCzGGt/EtiYKxITMO4Wiv6q5JL1gl9ePt4kBsl1S499nbosspfctIQTpYIhSmHA3WAg== dependencies: "@hapi/hoek" "^9.0.0" "@hapi/topo" "^5.0.0" @@ -5031,7 +5005,7 @@ js-yaml@^3.13.1: argparse "^1.0.7" esprima "^4.0.0" -js-yaml@^4.0.0: +js-yaml@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602" integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA== @@ -5079,19 +5053,14 @@ jsesc@^2.5.1: jsesc@~0.5.0: version "0.5.0" resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-0.5.0.tgz#e7dee66e35d6fc16f710fe91d5cf69f70f08911d" - integrity sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0= + integrity sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA== json-buffer@3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.0.tgz#5b1f397afc75d677bde8bcfc0e47e1f9a3d9a898" - integrity sha1-Wx85evx11ne96Lz8Dkfh+aPZqJg= + integrity sha512-CuUqjv0FUZIdXkHPI8MezCnFCdaTAacej1TZYulLoAg1h/PhwkdXFN4V/gzY4g+fMBCOV2xF+rp7t2XD2ns/NQ== -json-parse-better-errors@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz#bb867cfb3450e69107c131d1c514bab3dc8bcaa9" - integrity sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw== - -json-parse-even-better-errors@^2.3.0: +json-parse-even-better-errors@^2.3.0, json-parse-even-better-errors@^2.3.1: version "2.3.1" resolved "https://registry.yarnpkg.com/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz#7c47805a94319928e05777405dc12e1f7a4ee02d" integrity sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w== @@ -5106,19 +5075,10 @@ json-schema-traverse@^1.0.0: resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz#ae7bcb3656ab77a73ba5c49bf654f38e6b6860e2" integrity sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug== -json5@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/json5/-/json5-1.0.1.tgz#779fb0018604fa854eacbf6252180d83543e3dbe" - integrity sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow== - dependencies: - minimist "^1.2.0" - -json5@^2.1.2: - version "2.2.0" - resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.0.tgz#2dfefe720c6ba525d9ebd909950f0515316c89a3" - integrity sha512-f+8cldu7X/y7RAJurMEJmdoKXGB/X550w2Nr3tTbezL6RwEE/iMcm+tZnXeoZtKuOq6ft8+CqzEkrIgx1fPoQA== - dependencies: - minimist "^1.2.5" +json5@^2.1.2, json5@^2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.1.tgz#655d50ed1e6f95ad1a3caababd2b0efda10b395c" + integrity sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA== jsonfile@^6.0.1: version "6.1.0" @@ -5173,15 +5133,15 @@ leven@^3.1.0: levn@~0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/levn/-/levn-0.3.0.tgz#3b09924edf9f083c0490fdd4c0bc4421e04764ee" - integrity sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4= + integrity sha512-0OO4y2iOHix2W6ujICbKIaEQXvFQHue65vUG3pb5EUomzPI90z9hsA1VsO/dbIIpC53J8gxM9Q4Oho0jrCM/yA== dependencies: prelude-ls "~1.1.2" type-check "~0.3.2" lilconfig@^2.0.3: - version "2.0.4" - resolved "https://registry.yarnpkg.com/lilconfig/-/lilconfig-2.0.4.tgz#f4507d043d7058b380b6a8f5cb7bcd4b34cee082" - integrity sha512-bfTIN7lEsiooCocSISTWXkiWJkRqtL9wYtYy+8EK3Y41qh3mpwPU0ycTOgjdY9ErwXCc8QyrQp82bdL0Xkm9yA== + version "2.0.6" + resolved "https://registry.yarnpkg.com/lilconfig/-/lilconfig-2.0.6.tgz#32a384558bd58af3d4c6e077dd1ad1d397bc69d4" + integrity sha512-9JROoBW7pobfsx+Sq2JsASvCo6Pfo6WWoUW79HuB1BCoBXD4PLWJPqDF6fNj67pqBYTbAHkE57M1kS/+L1neOg== lines-and-columns@^1.1.6: version "1.2.4" @@ -5189,32 +5149,23 @@ lines-and-columns@^1.1.6: integrity sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg== loader-runner@^4.2.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/loader-runner/-/loader-runner-4.2.0.tgz#d7022380d66d14c5fb1d496b89864ebcfd478384" - integrity sha512-92+huvxMvYlMzMt0iIOukcwYBFpkYJdpl2xsZ7LrlayO7E8SOv+JJUEK17B/dJIHAOLMfh2dZZ/Y18WgmGtYNw== - -loader-utils@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-1.4.0.tgz#c579b5e34cb34b1a74edc6c1fb36bfa371d5a613" - integrity sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA== - dependencies: - big.js "^5.2.2" - emojis-list "^3.0.0" - json5 "^1.0.1" + version "4.3.0" + resolved "https://registry.yarnpkg.com/loader-runner/-/loader-runner-4.3.0.tgz#c1b4a163b99f614830353b16755e7149ac2314e1" + integrity sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg== loader-utils@^2.0.0: - version "2.0.2" - resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-2.0.2.tgz#d6e3b4fb81870721ae4e0868ab11dd638368c129" - integrity sha512-TM57VeHptv569d/GKh6TAYdzKblwDNiumOdkFnejjD0XwTH87K90w3O7AiJRqdQoXygvi1VQTJTLGhJl7WqA7A== + version "2.0.4" + resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-2.0.4.tgz#8b5cb38b5c34a9a018ee1fc0e6a066d1dfcc528c" + integrity sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw== dependencies: big.js "^5.2.2" emojis-list "^3.0.0" json5 "^2.1.2" loader-utils@^3.2.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-3.2.0.tgz#bcecc51a7898bee7473d4bc6b845b23af8304d4f" - integrity sha512-HVl9ZqccQihZ7JM85dco1MvO9G+ONvxoGa9rkhzFsneGLKSUg1gJf9bWzhRhcvm2qChhWpebQhP44qxjKIUCaQ== + version "3.2.1" + resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-3.2.1.tgz#4fb104b599daafd82ef3e1a41fb9265f87e1f576" + integrity sha512-ZvFw1KWS3GVyYBYb7qkmRM/WwL2TQQBxgCK62rlvm4WpVQ23Nb4tYjApUlfjrEGvOs7KHEsmyUn75OHZrJMWPw== locate-path@^3.0.0: version "3.0.0" @@ -5238,92 +5189,32 @@ locate-path@^6.0.0: dependencies: p-locate "^5.0.0" -lodash.assignin@^4.0.9: - version "4.2.0" - resolved "https://registry.yarnpkg.com/lodash.assignin/-/lodash.assignin-4.2.0.tgz#ba8df5fb841eb0a3e8044232b0e263a8dc6a28a2" - integrity sha1-uo31+4QesKPoBEIysOJjqNxqKKI= - -lodash.bind@^4.1.4: - version "4.2.1" - resolved "https://registry.yarnpkg.com/lodash.bind/-/lodash.bind-4.2.1.tgz#7ae3017e939622ac31b7d7d7dcb1b34db1690d35" - integrity sha1-euMBfpOWIqwxt9fX3LGzTbFpDTU= - lodash.curry@^4.0.1: version "4.1.1" resolved "https://registry.yarnpkg.com/lodash.curry/-/lodash.curry-4.1.1.tgz#248e36072ede906501d75966200a86dab8b23170" - integrity sha1-JI42By7ekGUB11lmIAqG2riyMXA= + integrity sha512-/u14pXGviLaweY5JI0IUzgzF2J6Ne8INyzAZjImcryjgkZ+ebruBxy2/JaOOkTqScddcYtakjhSaeemV8lR0tA== lodash.debounce@^4.0.8: version "4.0.8" resolved "https://registry.yarnpkg.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz#82d79bff30a67c4005ffd5e2515300ad9ca4d7af" - integrity sha1-gteb/zCmfEAF/9XiUVMArZyk168= - -lodash.defaults@^4.0.1: - version "4.2.0" - resolved "https://registry.yarnpkg.com/lodash.defaults/-/lodash.defaults-4.2.0.tgz#d09178716ffea4dde9e5fb7b37f6f0802274580c" - integrity sha1-0JF4cW/+pN3p5ft7N/bwgCJ0WAw= - -lodash.filter@^4.4.0: - version "4.6.0" - resolved "https://registry.yarnpkg.com/lodash.filter/-/lodash.filter-4.6.0.tgz#668b1d4981603ae1cc5a6fa760143e480b4c4ace" - integrity sha1-ZosdSYFgOuHMWm+nYBQ+SAtMSs4= - -lodash.flatten@^4.2.0: - version "4.4.0" - resolved "https://registry.yarnpkg.com/lodash.flatten/-/lodash.flatten-4.4.0.tgz#f31c22225a9632d2bbf8e4addbef240aa765a61f" - integrity sha1-8xwiIlqWMtK7+OSt2+8kCqdlph8= + integrity sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow== lodash.flow@^3.3.0: version "3.5.0" resolved "https://registry.yarnpkg.com/lodash.flow/-/lodash.flow-3.5.0.tgz#87bf40292b8cf83e4e8ce1a3ae4209e20071675a" - integrity sha1-h79AKSuM+D5OjOGjrkIJ4gBxZ1o= - -lodash.foreach@^4.3.0: - version "4.5.0" - resolved "https://registry.yarnpkg.com/lodash.foreach/-/lodash.foreach-4.5.0.tgz#1a6a35eace401280c7f06dddec35165ab27e3e53" - integrity sha1-Gmo16s5AEoDH8G3d7DUWWrJ+PlM= - -lodash.map@^4.4.0: - version "4.6.0" - resolved "https://registry.yarnpkg.com/lodash.map/-/lodash.map-4.6.0.tgz#771ec7839e3473d9c4cde28b19394c3562f4f6d3" - integrity sha1-dx7Hg540c9nEzeKLGTlMNWL09tM= + integrity sha512-ff3BX/tSioo+XojX4MOsOMhJw0nZoUEF011LX8g8d3gvjVbxd89cCio4BCXronjxcTUIJUoqKEUA+n4CqvvRPw== lodash.memoize@^4.1.2: version "4.1.2" resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-4.1.2.tgz#bcc6c49a42a2840ed997f323eada5ecd182e0bfe" - integrity sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4= - -lodash.merge@^4.4.0: - version "4.6.2" - resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a" - integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ== - -lodash.pick@^4.2.1: - version "4.4.0" - resolved "https://registry.yarnpkg.com/lodash.pick/-/lodash.pick-4.4.0.tgz#52f05610fff9ded422611441ed1fc123a03001b3" - integrity sha1-UvBWEP/53tQiYRRB7R/BI6AwAbM= - -lodash.reduce@^4.4.0: - version "4.6.0" - resolved "https://registry.yarnpkg.com/lodash.reduce/-/lodash.reduce-4.6.0.tgz#f1ab6b839299ad48f784abbf476596f03b914d3b" - integrity sha1-8atrg5KZrUj3hKu/R2WW8DuRTTs= - -lodash.reject@^4.4.0: - version "4.6.0" - resolved "https://registry.yarnpkg.com/lodash.reject/-/lodash.reject-4.6.0.tgz#80d6492dc1470864bbf583533b651f42a9f52415" - integrity sha1-gNZJLcFHCGS79YNTO2UfQqn1JBU= - -lodash.some@^4.4.0: - version "4.6.0" - resolved "https://registry.yarnpkg.com/lodash.some/-/lodash.some-4.6.0.tgz#1bb9f314ef6b8baded13b549169b2a945eb68e4d" - integrity sha1-G7nzFO9ri63tE7VJFpsqlF62jk0= + integrity sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag== lodash.uniq@4.5.0, lodash.uniq@^4.5.0: version "4.5.0" resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773" - integrity sha1-0CJTc662Uq3BvILklFM5qEJ1R3M= + integrity sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ== -lodash@^4.17.14, lodash@^4.17.19, lodash@^4.17.20, lodash@^4.17.21: +lodash@^4.17.19, lodash@^4.17.20, lodash@^4.17.21: version "4.17.21" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== @@ -5359,23 +5250,6 @@ lru-cache@^6.0.0: dependencies: yallist "^4.0.0" -lunr-languages@^1.4.0: - version "1.9.0" - resolved "https://registry.yarnpkg.com/lunr-languages/-/lunr-languages-1.9.0.tgz#7105230807788a112a69910561b7bbd055a0e588" - integrity sha512-Be5vFuc8NAheOIjviCRms3ZqFFBlzns3u9DXpPSZvALetgnydAN0poV71pVLFn0keYy/s4VblMMkqewTLe+KPg== - -lunr@^2.3.8: - version "2.3.9" - resolved "https://registry.yarnpkg.com/lunr/-/lunr-2.3.9.tgz#18b123142832337dd6e964df1a5a7707b25d35e1" - integrity sha512-zTU3DaZaF3Rt9rhN3uBMGQD3dD2/vFQqnvZCDv4dl5iOzq2IZQqTxu90r4E5J+nP70J3ilqVCrbho2eWaeW8Ow== - -magic-string@^0.25.3: - version "0.25.7" - resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.25.7.tgz#3f497d6fd34c669c6798dcb821f2ef31f5445051" - integrity sha512-4CrMT5DOHTDk4HYDlzmwu4FVCcIYI8gauveasrdCu2IKIFOJ3f0v/8MDGJCDL9oD2ppz/Av1b0Nj345H9M+XIA== - dependencies: - sourcemap-codec "^1.4.4" - make-dir@^3.0.0, make-dir@^3.0.2, make-dir@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-3.1.0.tgz#415e967046b3a7f1d185277d84aa58203726a13f" @@ -5389,14 +5263,14 @@ markdown-escapes@^1.0.0: integrity sha512-8z4efJYk43E0upd0NbVXwgSTQs6cT3T06etieCMEg7dRbzCbxUCK/GHlX8mhHRDcp+OLlHkPKsvqQTCvsRl2cg== mathjax-full@^3.0.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/mathjax-full/-/mathjax-full-3.2.0.tgz#e53269842a943d4df10502937518991268996c5c" - integrity sha512-D2EBNvUG+mJyhn+M1C858k0f2Fc4KxXvbEX2WCMXroV10212JwfYqaBJ336ECBSz5X9L5LRoamxb7AJtg3KaJA== + version "3.2.2" + resolved "https://registry.yarnpkg.com/mathjax-full/-/mathjax-full-3.2.2.tgz#43f02e55219db393030985d2b6537ceae82f1fa7" + integrity sha512-+LfG9Fik+OuI8SLwsiR02IVdjcnRCy5MufYLi0C3TdMT56L/pjB0alMVGgoWJF8pN9Rc7FESycZB9BMNWIid5w== dependencies: esm "^3.2.25" mhchemparser "^4.1.0" mj-context-menu "^0.6.1" - speech-rule-engine "^3.3.3" + speech-rule-engine "^4.0.6" mdast-squeeze-paragraphs@^4.0.0: version "4.0.0" @@ -5439,24 +5313,24 @@ mdn-data@2.0.14: mdurl@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/mdurl/-/mdurl-1.0.1.tgz#fe85b2ec75a59037f2adfec100fd6c601761152e" - integrity sha1-/oWy7HWlkDfyrf7BAP1sYBdhFS4= + integrity sha512-/sKlQJCBYVY9Ers9hqzKou4H6V5UWc/M59TH2dvkt+84itfnq7uFOMLpOiOS4ujvHP4etln18fmIxA5R5fll0g== media-typer@0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" - integrity sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g= + integrity sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ== -memfs@^3.1.2, memfs@^3.2.2: - version "3.4.1" - resolved "https://registry.yarnpkg.com/memfs/-/memfs-3.4.1.tgz#b78092f466a0dce054d63d39275b24c71d3f1305" - integrity sha512-1c9VPVvW5P7I85c35zAdEr1TD5+F11IToIHIlrVIcflfnzPkJa0ZoYEoEdYDP8KgPFoSZ/opDrUsAoZWym3mtw== +memfs@^3.1.2, memfs@^3.4.3: + version "3.4.12" + resolved "https://registry.yarnpkg.com/memfs/-/memfs-3.4.12.tgz#d00f8ad8dab132dc277c659dc85bfd14b07d03bd" + integrity sha512-BcjuQn6vfqP+k100e0E9m61Hyqa//Brp+I3f0OBmN0ATHlFA8vx3Lt8z57R3u2bPqe3WGDBC+nF72fTH7isyEw== dependencies: - fs-monkey "1.0.3" + fs-monkey "^1.0.3" merge-descriptors@1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61" - integrity sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E= + integrity sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w== merge-stream@^2.0.0: version "2.0.0" @@ -5471,25 +5345,25 @@ merge2@^1.3.0, merge2@^1.4.1: methods@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee" - integrity sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4= + integrity sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w== mhchemparser@^4.1.0: version "4.1.1" resolved "https://registry.yarnpkg.com/mhchemparser/-/mhchemparser-4.1.1.tgz#a2142fdab37a02ec8d1b48a445059287790becd5" integrity sha512-R75CUN6O6e1t8bgailrF1qPq+HhVeFTM3XQ0uzI+mXTybmphy3b6h4NbLOYhemViQ3lUs+6CKRkC3Ws1TlYREA== -micromatch@^4.0.2, micromatch@^4.0.4: - version "4.0.4" - resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.4.tgz#896d519dfe9db25fce94ceb7a500919bf881ebf9" - integrity sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg== +micromatch@^4.0.2, micromatch@^4.0.4, micromatch@^4.0.5: + version "4.0.5" + resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.5.tgz#bc8999a7cbbf77cdc89f132f6e467051b49090c6" + integrity sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA== dependencies: - braces "^3.0.1" - picomatch "^2.2.3" + braces "^3.0.2" + picomatch "^2.3.1" -mime-db@1.51.0, "mime-db@>= 1.43.0 < 2": - version "1.51.0" - resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.51.0.tgz#d9ff62451859b18342d960850dc3cfb77e63fb0c" - integrity sha512-5y8A56jg7XVQx2mbv1lu49NR4dokRnhZYTtL+KGfaa27uq4pSTXkwQkFJl4pkRMyNFz/EtYDSkiiEHx3F7UN6g== +mime-db@1.52.0, "mime-db@>= 1.43.0 < 2": + version "1.52.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70" + integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== mime-db@~1.33.0: version "1.33.0" @@ -5503,12 +5377,12 @@ mime-types@2.1.18: dependencies: mime-db "~1.33.0" -mime-types@^2.1.12, mime-types@^2.1.27, mime-types@^2.1.31, mime-types@~2.1.17, mime-types@~2.1.24: - version "2.1.34" - resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.34.tgz#5a712f9ec1503511a945803640fafe09d3793c24" - integrity sha512-6cP692WwGIs9XXdOO4++N+7qjqv0rqxxVvJ3VHPh/Sc9mVZcQP+ZGhkKiTvWMQRr2tbHkJP/Yn7Y0npb3ZBs4A== +mime-types@^2.1.12, mime-types@^2.1.27, mime-types@^2.1.31, mime-types@~2.1.17, mime-types@~2.1.24, mime-types@~2.1.34: + version "2.1.35" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a" + integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw== dependencies: - mime-db "1.51.0" + mime-db "1.52.0" mime@1.6.0: version "1.6.0" @@ -5525,99 +5399,72 @@ mimic-response@^1.0.0, mimic-response@^1.0.1: resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-1.0.1.tgz#4923538878eef42063cb8a3e3b0798781487ab1b" integrity sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ== -mini-create-react-context@^0.4.0: - version "0.4.1" - resolved "https://registry.yarnpkg.com/mini-create-react-context/-/mini-create-react-context-0.4.1.tgz#072171561bfdc922da08a60c2197a497cc2d1d5e" - integrity sha512-YWCYEmd5CQeHGSAKrYvXgmzzkrvssZcuuQDDeqkT+PziKGMgE+0MCCtcKbROzocGBG1meBLl2FotlRwf4gAzbQ== - dependencies: - "@babel/runtime" "^7.12.1" - tiny-warning "^1.0.3" - -mini-css-extract-plugin@^1.6.0: - version "1.6.2" - resolved "https://registry.yarnpkg.com/mini-css-extract-plugin/-/mini-css-extract-plugin-1.6.2.tgz#83172b4fd812f8fc4a09d6f6d16f924f53990ca8" - integrity sha512-WhDvO3SjGm40oV5y26GjMJYjd2UMqrLAGKy5YS2/3QKJy2F7jgynuHTir/tgUUOiNQu5saXHdc8reo7YuhhT4Q== +mini-css-extract-plugin@^2.6.1: + version "2.7.0" + resolved "https://registry.yarnpkg.com/mini-css-extract-plugin/-/mini-css-extract-plugin-2.7.0.tgz#d7d9ba0c5b596d155e36e2b174082fc7f010dd64" + integrity sha512-auqtVo8KhTScMsba7MbijqZTfibbXiBNlPAQbsVt7enQfcDYLdgG57eGxMqwVU3mfeWANY4F1wUg+rMF+ycZgw== dependencies: - loader-utils "^2.0.0" - schema-utils "^3.0.0" - webpack-sources "^1.1.0" + schema-utils "^4.0.0" minimalistic-assert@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz#2e194de044626d4a10e7f7fbc00ce73e83e4d5c7" integrity sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A== -minimatch@3.0.4, minimatch@^3.0.4: - version "3.0.4" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" - integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA== +minimatch@3.1.2, minimatch@^3.0.4, minimatch@^3.0.5, minimatch@^3.1.1: + version "3.1.2" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" + integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== dependencies: brace-expansion "^1.1.7" minimist@^1.2.0, minimist@^1.2.5: - version "1.2.5" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602" - integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw== + version "1.2.7" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.7.tgz#daa1c4d91f507390437c6a8bc01078e7000c4d18" + integrity sha512-bzfL1YUZsP41gmu/qjrEk0Q6i2ix/cVeAhbCbqH9u3zYutS1cLg00qhrD0M2MVdCcx4Sc0UpP2eBWo9rotpq6g== mj-context-menu@^0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/mj-context-menu/-/mj-context-menu-0.6.1.tgz#a043c5282bf7e1cf3821de07b13525ca6f85aa69" integrity sha512-7NO5s6n10TIV96d4g2uDpG7ZDpIhMh0QNfGdJw/W47JswFcosz457wqz/b5sAKvl12sxINGFCn80NZHKwxQEXA== -mkdirp@0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.3.0.tgz#1bbf5ab1ba827af23575143490426455f481fe1e" - integrity sha1-G79asbqCevI1dRQ0kEJkVfSB/h4= - -mkdirp@^0.5.5: - version "0.5.5" - resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.5.tgz#d91cefd62d1436ca0f41620e251288d420099def" - integrity sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ== - dependencies: - minimist "^1.2.5" - mrmime@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/mrmime/-/mrmime-1.0.0.tgz#14d387f0585a5233d291baba339b063752a2398b" - integrity sha512-a70zx7zFfVO7XpnQ2IX1Myh9yY4UYvfld/dikWRnsXxbyvMcfz+u6UfgNAtH+k2QqtJuzVpv6eLTx1G2+WKZbQ== + version "1.0.1" + resolved "https://registry.yarnpkg.com/mrmime/-/mrmime-1.0.1.tgz#5f90c825fad4bdd41dc914eff5d1a8cfdaf24f27" + integrity sha512-hzzEagAgDyoU1Q6yg5uI+AorQgdvMCur3FcKf7NhMKWsaYg+RnbTyHRa/9IlLF9rf455MOCtcqqrQQ83pPP7Uw== ms@2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" - integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g= + integrity sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A== ms@2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== -ms@2.1.3, ms@^2.1.1: +ms@2.1.3: version "2.1.3" resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== -multicast-dns-service-types@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/multicast-dns-service-types/-/multicast-dns-service-types-1.1.0.tgz#899f11d9686e5e05cb91b35d5f0e63b773cfc901" - integrity sha1-iZ8R2WhuXgXLkbNdXw5jt3PPyQE= - -multicast-dns@^6.0.1: - version "6.2.3" - resolved "https://registry.yarnpkg.com/multicast-dns/-/multicast-dns-6.2.3.tgz#a0ec7bd9055c4282f790c3c82f4e28db3b31b229" - integrity sha512-ji6J5enbMyGRHIAkAOu3WdV8nggqviKCEKtXcOqfphZZtQrmHKycfynJ2V7eVPUA4NhJ6V7Wf4TmGbTwKE9B6g== +multicast-dns@^7.2.5: + version "7.2.5" + resolved "https://registry.yarnpkg.com/multicast-dns/-/multicast-dns-7.2.5.tgz#77eb46057f4d7adbd16d9290fa7299f6fa64cced" + integrity sha512-2eznPJP8z2BFLX50tf0LuODrpINqP1RVIm/CObbTcBRITQgmC/TjcREF1NeTBzIcR5XO/ukWo+YHOjBbFwIupg== dependencies: - dns-packet "^1.3.1" + dns-packet "^5.2.2" thunky "^1.0.2" -nanoid@^3.1.30: - version "3.1.32" - resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.1.32.tgz#8f96069e6239cc0a9ae8c0d3b41a3b4933a88c0a" - integrity sha512-F8mf7R3iT9bvThBoW4tGXhXFHCctyCiUUPrWF8WaTqa3h96d9QybkSeba43XVOOE3oiLfkVDe4bT8MeGmkrTxw== +nanoid@^3.3.4: + version "3.3.4" + resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.4.tgz#730b67e3cd09e2deacf03c027c81c9d9dbc5e8ab" + integrity sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw== -negotiator@0.6.2: - version "0.6.2" - resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.2.tgz#feacf7ccf525a77ae9634436a64883ffeca346fb" - integrity sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw== +negotiator@0.6.3: + version "0.6.3" + resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.3.tgz#58e323a72fedc0d6f9cd4d31fe49f51479590ccd" + integrity sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg== neo-async@^2.6.2: version "2.6.2" @@ -5639,27 +5486,22 @@ node-emoji@^1.10.0: dependencies: lodash "^4.17.21" -node-fetch@2.6.1: - version "2.6.1" - resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.1.tgz#045bd323631f76ed2e2b55573394416b639a0052" - integrity sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw== - -node-forge@^1.2.0: - version "1.2.1" - resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-1.2.1.tgz#82794919071ef2eb5c509293325cec8afd0fd53c" - integrity sha512-Fcvtbb+zBcZXbTTVwqGA5W+MKBj56UjVRevvchv5XrcyXbmNdesfZL37nlcWOfpgHhgmxApw3tQbTr4CqNmX4w== +node-fetch@2.6.7: + version "2.6.7" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.7.tgz#24de9fba827e3b4ae44dc8b20256a379160052ad" + integrity sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ== + dependencies: + whatwg-url "^5.0.0" -node-releases@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.1.tgz#3d1d395f204f1f2f29a54358b9fb678765ad2fc5" - integrity sha512-CqyzN6z7Q6aMeF/ktcMVTzhAHCEpf8SOarwpzpf8pNBY2k5/oM34UHldUwp8VKI7uxct2HxSRdJjBaZeESzcxA== +node-forge@^1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-1.3.1.tgz#be8da2af243b2417d5f646a770663a92b7e9ded3" + integrity sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA== -nopt@1.0.10: - version "1.0.10" - resolved "https://registry.yarnpkg.com/nopt/-/nopt-1.0.10.tgz#6ddd21bd2a31417b92727dd585f8a6f37608ebee" - integrity sha1-bd0hvSoxQXuScn3Vhfim83YI6+4= - dependencies: - abbrev "1" +node-releases@^2.0.6: + version "2.0.6" + resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.6.tgz#8a7088c63a55e493845683ebf3c828d8c51c5503" + integrity sha512-PiVXnNuFm5+iYkLBNeq5211hvO38y63T0i2KKh2KnUs3RpzJ+JtODFjkD8yjLwnDkTYF1eKXheUwdssR+NRZdg== normalize-path@^3.0.0, normalize-path@~3.0.0: version "3.0.0" @@ -5669,7 +5511,7 @@ normalize-path@^3.0.0, normalize-path@~3.0.0: normalize-range@^0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/normalize-range/-/normalize-range-0.1.2.tgz#2d10c06bdfd312ea9777695a4d28439456b75942" - integrity sha1-LRDAa9/TEuqXd2laTShDlFa3WUI= + integrity sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA== normalize-url@^4.1.0: version "4.5.1" @@ -5681,11 +5523,6 @@ normalize-url@^6.0.1: resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-6.1.0.tgz#40d0885b535deffe3f3147bec877d05fe4c5668a" integrity sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A== -not@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/not/-/not-0.1.0.tgz#c9691c1746c55dcfbe54cbd8bd4ff041bc2b519d" - integrity sha1-yWkcF0bFXc++VMvYvU/wQbwrUZ0= - npm-run-path@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-4.0.1.tgz#b7ecd1e5ed53da8e37a55e1c2269e0b97ed748ea" @@ -5696,53 +5533,43 @@ npm-run-path@^4.0.1: nprogress@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/nprogress/-/nprogress-0.2.0.tgz#cb8f34c53213d895723fcbab907e9422adbcafb1" - integrity sha1-y480xTIT2JVyP8urkH6UIq28r7E= + integrity sha512-I19aIingLgR1fmhftnbWWO3dXc0hSxqHQHQb3H8m+K3TnEn/iSeTZZOyvKXWqQESMwuUVnatlCnZdLBZZt2VSA== -nth-check@^2.0.0, nth-check@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/nth-check/-/nth-check-2.0.1.tgz#2efe162f5c3da06a28959fbd3db75dbeea9f0fc2" - integrity sha512-it1vE95zF6dTT9lBsYbxvqh0Soy4SPowchj0UBGj/V6cTPnXXtQOPUbhZ6CmGzAD/rW22LQK6E96pcdJXk4A4w== +nth-check@^2.0.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/nth-check/-/nth-check-2.1.1.tgz#c9eab428effce36cd6b92c924bdb000ef1f1ed1d" + integrity sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w== dependencies: boolbase "^1.0.0" -nth-check@~1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/nth-check/-/nth-check-1.0.2.tgz#b2bd295c37e3dd58a3bf0700376663ba4d9cf05c" - integrity sha512-WeBOdju8SnzPN5vTUJYxYUxLeXpCaVP5i5e0LF8fg7WORF2Wd7wFX/pk0tYZk7s8T+J7VLy0Da6J1+wCT0AtHg== - dependencies: - boolbase "~1.0.0" - nwsapi@^2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/nwsapi/-/nwsapi-2.2.0.tgz#204879a9e3d068ff2a55139c2c772780681a38b7" - integrity sha512-h2AatdwYH+JHiZpv7pt/gSX1XoRGb7L/qSIeuqA6GwYoF9w1vP1cw42TO0aI2pNyshRK5893hNSl+1//vHK7hQ== + version "2.2.2" + resolved "https://registry.yarnpkg.com/nwsapi/-/nwsapi-2.2.2.tgz#e5418863e7905df67d51ec95938d67bf801f0bb0" + integrity sha512-90yv+6538zuvUMnN+zCr8LuV6bPFdq50304114vJYJ8RDyK8D5O9Phpbd6SZWgI7PwzmmfN1upeOJlvybDSgCw== object-assign@^4.1.0, object-assign@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" - integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM= + integrity sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg== -object-is@^1.0.1: - version "1.1.5" - resolved "https://registry.yarnpkg.com/object-is/-/object-is-1.1.5.tgz#b9deeaa5fc7f1846a0faecdceec138e5778f53ac" - integrity sha512-3cyDsyHgtmi7I7DfSSI2LDp6SK2lwvtbg0p0R1e0RvTqF5ceGx+K2dfSjm1bKDMVCFEDAQvy+o8c6a7VujOddw== - dependencies: - call-bind "^1.0.2" - define-properties "^1.1.3" +object-inspect@^1.9.0: + version "1.12.2" + resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.12.2.tgz#c0641f26394532f28ab8d796ab954e43c009a8ea" + integrity sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ== -object-keys@^1.0.12, object-keys@^1.1.1: +object-keys@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA== object.assign@^4.1.0: - version "4.1.2" - resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.2.tgz#0ed54a342eceb37b38ff76eb831a0e788cb63940" - integrity sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ== + version "4.1.4" + resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.4.tgz#9673c7c7c351ab8c4d0b516f4343ebf4dfb7799f" + integrity sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ== dependencies: - call-bind "^1.0.0" - define-properties "^1.1.3" - has-symbols "^1.0.1" + call-bind "^1.0.2" + define-properties "^1.1.4" + has-symbols "^1.0.3" object-keys "^1.1.1" obuf@^1.0.0, obuf@^1.1.2: @@ -5750,10 +5577,10 @@ obuf@^1.0.0, obuf@^1.1.2: resolved "https://registry.yarnpkg.com/obuf/-/obuf-1.1.2.tgz#09bea3343d41859ebd446292d11c9d4db619084e" integrity sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg== -on-finished@~2.3.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.3.0.tgz#20f1336481b083cd75337992a16971aa2d906947" - integrity sha1-IPEzZIGwg811M3mSoWlxqi2QaUc= +on-finished@2.4.1: + version "2.4.1" + resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.4.1.tgz#58c8c44116e54845ad57f14ab10b03533184ac3f" + integrity sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg== dependencies: ee-first "1.1.1" @@ -5765,7 +5592,7 @@ on-headers@~1.0.2: once@^1.3.0, once@^1.3.1, once@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" - integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E= + integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w== dependencies: wrappy "1" @@ -5850,11 +5677,11 @@ p-map@^4.0.0: aggregate-error "^3.0.0" p-retry@^4.5.0: - version "4.6.1" - resolved "https://registry.yarnpkg.com/p-retry/-/p-retry-4.6.1.tgz#8fcddd5cdf7a67a0911a9cf2ef0e5df7f602316c" - integrity sha512-e2xXGNhZOZ0lfgR9kL34iGlU8N/KO0xZnQxVEwdeOvpqNDQfdnxIYizvWtK8RglUa3bGqI8g0R/BdfzLMxRkiA== + version "4.6.2" + resolved "https://registry.yarnpkg.com/p-retry/-/p-retry-4.6.2.tgz#9baae7184057edd4e17231cee04264106e092a16" + integrity sha512-312Id396EbJdvRONlngUx0NydfrIQ5lsYu0znKVUzVvArzEIt08V1qhtyESbGVd1FGX7UKtiFp5uwKZdM8wIuQ== dependencies: - "@types/retry" "^0.12.0" + "@types/retry" "0.12.0" retry "^0.13.1" p-try@^2.0.0: @@ -5914,22 +5741,25 @@ parse-numeric-range@^1.3.0: resolved "https://registry.yarnpkg.com/parse-numeric-range/-/parse-numeric-range-1.3.0.tgz#7c63b61190d61e4d53a1197f0c83c47bb670ffa3" integrity sha512-twN+njEipszzlMJd4ONUYgSfZPDxgHhT9Ahed5uTigpQn90FggW4SA/AIPq/6a149fTbE9qBEcSwE3FAEp6wQQ== -parse5-htmlparser2-tree-adapter@^6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-6.0.1.tgz#2cdf9ad823321140370d4dbf5d3e92c7c8ddc6e6" - integrity sha512-qPuWvbLgvDGilKc5BoicRovlT4MtYT6JfJyBOMDsKoiT+GiuP5qyrPCnR9HcPECIJJmZh5jRndyNThnhhb/vlA== +parse5-htmlparser2-tree-adapter@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-7.0.0.tgz#23c2cc233bcf09bb7beba8b8a69d46b08c62c2f1" + integrity sha512-B77tOZrqqfUfnVcOrUvfdLbz4pu4RopLD/4vmu3HUPswwTA8OH0EMW9BlWR2B0RCoiZRAHEUu7IxeP1Pd1UU+g== dependencies: - parse5 "^6.0.1" + domhandler "^5.0.2" + parse5 "^7.0.0" -parse5@6.0.1, parse5@^6.0.0, parse5@^6.0.1: +parse5@6.0.1, parse5@^6.0.0: version "6.0.1" resolved "https://registry.yarnpkg.com/parse5/-/parse5-6.0.1.tgz#e1a1c085c569b3dc08321184f19a39cc27f7c30b" integrity sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw== -parse5@^5.0.0: - version "5.1.1" - resolved "https://registry.yarnpkg.com/parse5/-/parse5-5.1.1.tgz#f68e4e5ba1852ac2cadc00f4555fff6c2abb6178" - integrity sha512-ugq4DFI0Ptb+WWjAdOK16+u/nHfiIrcE+sh8kZMaM0WllQKLI9rOUq6c2b7cwPkXdzfQESqvoqK6ug7U/Yyzug== +parse5@^7.0.0: + version "7.1.2" + resolved "https://registry.yarnpkg.com/parse5/-/parse5-7.1.2.tgz#0736bebbfd77793823240a23b7fc5e010b7f8e32" + integrity sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw== + dependencies: + entities "^4.4.0" parseurl@~1.3.2, parseurl@~1.3.3: version "1.3.3" @@ -5947,7 +5777,7 @@ pascal-case@^3.1.2: path-exists@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515" - integrity sha1-zg6+ql94yxiSXqfYENe1mwEP1RU= + integrity sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ== path-exists@^4.0.0: version "4.0.0" @@ -5957,12 +5787,12 @@ path-exists@^4.0.0: path-is-absolute@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" - integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18= + integrity sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg== path-is-inside@1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/path-is-inside/-/path-is-inside-1.0.2.tgz#365417dede44430d1c11af61027facf074bdfc53" - integrity sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM= + integrity sha512-DUWJr3+ULp4zXmol/SZkFf3JGsS9/SIv+Y3Rt93/UjPpDpklB5f1er4O3POIbUuUJ3FXgqte2Q7SrU6zAqwk8w== path-key@^3.0.0, path-key@^3.1.0: version "3.1.1" @@ -5977,7 +5807,7 @@ path-parse@^1.0.7: path-to-regexp@0.1.7: version "0.1.7" resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c" - integrity sha1-32BBeABfUi8V60SQ5yR6G/qmf4w= + integrity sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ== path-to-regexp@2.2.1: version "2.2.1" @@ -6001,7 +5831,7 @@ picocolors@^1.0.0: resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c" integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ== -picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.2.3: +picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.2.3, picomatch@^2.3.1: version "2.3.1" resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== @@ -6020,134 +5850,124 @@ pkg-up@^3.1.0: dependencies: find-up "^3.0.0" -portfinder@^1.0.28: - version "1.0.28" - resolved "https://registry.yarnpkg.com/portfinder/-/portfinder-1.0.28.tgz#67c4622852bd5374dd1dd900f779f53462fac778" - integrity sha512-Se+2isanIcEqf2XMHjyUKskczxbPH7dQnlMjXX6+dybayyHvAf/TCgyMRlzf/B6QDhAEFOGes0pzRo3by4AbMA== - dependencies: - async "^2.6.2" - debug "^3.1.1" - mkdirp "^0.5.5" - -postcss-calc@^8.2.0: - version "8.2.2" - resolved "https://registry.yarnpkg.com/postcss-calc/-/postcss-calc-8.2.2.tgz#9706e7399e8ec8b61a47830dcf1f21391af23373" - integrity sha512-B5R0UeB4zLJvxNt1FVCaDZULdzsKLPc6FhjFJ+xwFiq7VG4i9cuaJLxVjNtExNK8ocm3n2o4unXXLiVX1SCqxA== +postcss-calc@^8.2.3: + version "8.2.4" + resolved "https://registry.yarnpkg.com/postcss-calc/-/postcss-calc-8.2.4.tgz#77b9c29bfcbe8a07ff6693dc87050828889739a5" + integrity sha512-SmWMSJmB8MRnnULldx0lQIyhSNvuDl9HfrZkaqqE/WHAhToYsAvDq+yAsA/kIyINDszOp3Rh0GFoNuH5Ypsm3Q== dependencies: - postcss-selector-parser "^6.0.2" - postcss-value-parser "^4.0.2" + postcss-selector-parser "^6.0.9" + postcss-value-parser "^4.2.0" -postcss-colormin@^5.2.3: - version "5.2.3" - resolved "https://registry.yarnpkg.com/postcss-colormin/-/postcss-colormin-5.2.3.tgz#da7fb80e81ad80d2867ea9e38672a892add5df15" - integrity sha512-dra4xoAjub2wha6RUXAgadHEn2lGxbj8drhFcIGLOMn914Eu7DkPUurugDXgstwttCYkJtZ/+PkWRWdp3UHRIA== +postcss-colormin@^5.3.0: + version "5.3.0" + resolved "https://registry.yarnpkg.com/postcss-colormin/-/postcss-colormin-5.3.0.tgz#3cee9e5ca62b2c27e84fce63affc0cfb5901956a" + integrity sha512-WdDO4gOFG2Z8n4P8TWBpshnL3JpmNmJwdnfP2gbk2qBA8PWwOYcmjmI/t3CmMeL72a7Hkd+x/Mg9O2/0rD54Pg== dependencies: browserslist "^4.16.6" caniuse-api "^3.0.0" colord "^2.9.1" postcss-value-parser "^4.2.0" -postcss-convert-values@^5.0.2: - version "5.0.2" - resolved "https://registry.yarnpkg.com/postcss-convert-values/-/postcss-convert-values-5.0.2.tgz#879b849dc3677c7d6bc94b6a2c1a3f0808798059" - integrity sha512-KQ04E2yadmfa1LqXm7UIDwW1ftxU/QWZmz6NKnHnUvJ3LEYbbcX6i329f/ig+WnEByHegulocXrECaZGLpL8Zg== +postcss-convert-values@^5.1.3: + version "5.1.3" + resolved "https://registry.yarnpkg.com/postcss-convert-values/-/postcss-convert-values-5.1.3.tgz#04998bb9ba6b65aa31035d669a6af342c5f9d393" + integrity sha512-82pC1xkJZtcJEfiLw6UXnXVXScgtBrjlO5CBmuDQc+dlb88ZYheFsjTn40+zBVi3DkfF7iezO0nJUPLcJK3pvA== dependencies: - postcss-value-parser "^4.1.0" + browserslist "^4.21.4" + postcss-value-parser "^4.2.0" -postcss-discard-comments@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/postcss-discard-comments/-/postcss-discard-comments-5.0.1.tgz#9eae4b747cf760d31f2447c27f0619d5718901fe" - integrity sha512-lgZBPTDvWrbAYY1v5GYEv8fEO/WhKOu/hmZqmCYfrpD6eyDWWzAOsl2rF29lpvziKO02Gc5GJQtlpkTmakwOWg== +postcss-discard-comments@^5.1.2: + version "5.1.2" + resolved "https://registry.yarnpkg.com/postcss-discard-comments/-/postcss-discard-comments-5.1.2.tgz#8df5e81d2925af2780075840c1526f0660e53696" + integrity sha512-+L8208OVbHVF2UQf1iDmRcbdjJkuBF6IS29yBDSiWUIzpYaAhtNl6JYnYm12FnkeCwQqF5LeklOu6rAqgfBZqQ== -postcss-discard-duplicates@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/postcss-discard-duplicates/-/postcss-discard-duplicates-5.0.1.tgz#68f7cc6458fe6bab2e46c9f55ae52869f680e66d" - integrity sha512-svx747PWHKOGpAXXQkCc4k/DsWo+6bc5LsVrAsw+OU+Ibi7klFZCyX54gjYzX4TH+f2uzXjRviLARxkMurA2bA== +postcss-discard-duplicates@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/postcss-discard-duplicates/-/postcss-discard-duplicates-5.1.0.tgz#9eb4fe8456706a4eebd6d3b7b777d07bad03e848" + integrity sha512-zmX3IoSI2aoenxHV6C7plngHWWhUOV3sP1T8y2ifzxzbtnuhk1EdPwm0S1bIUNaJ2eNbWeGLEwzw8huPD67aQw== -postcss-discard-empty@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/postcss-discard-empty/-/postcss-discard-empty-5.0.1.tgz#ee136c39e27d5d2ed4da0ee5ed02bc8a9f8bf6d8" - integrity sha512-vfU8CxAQ6YpMxV2SvMcMIyF2LX1ZzWpy0lqHDsOdaKKLQVQGVP1pzhrI9JlsO65s66uQTfkQBKBD/A5gp9STFw== +postcss-discard-empty@^5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/postcss-discard-empty/-/postcss-discard-empty-5.1.1.tgz#e57762343ff7f503fe53fca553d18d7f0c369c6c" + integrity sha512-zPz4WljiSuLWsI0ir4Mcnr4qQQ5e1Ukc3i7UfE2XcrwKK2LIPIqE5jxMRxO6GbI3cv//ztXDsXwEWT3BHOGh3A== -postcss-discard-overridden@^5.0.2: - version "5.0.2" - resolved "https://registry.yarnpkg.com/postcss-discard-overridden/-/postcss-discard-overridden-5.0.2.tgz#e6f51d83e66feffcf05ed94c4ad20b814d0aab5f" - integrity sha512-+56BLP6NSSUuWUXjRgAQuho1p5xs/hU5Sw7+xt9S3JSg+7R6+WMGnJW7Hre/6tTuZ2xiXMB42ObkiZJ2hy/Pew== +postcss-discard-overridden@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/postcss-discard-overridden/-/postcss-discard-overridden-5.1.0.tgz#7e8c5b53325747e9d90131bb88635282fb4a276e" + integrity sha512-21nOL7RqWR1kasIVdKs8HNqQJhFxLsyRfAnUDm4Fe4t4mCWL9OJiHvlHPjcd8zc5Myu89b/7wZDnOSjFgeWRtw== -postcss-discard-unused@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/postcss-discard-unused/-/postcss-discard-unused-5.0.1.tgz#63e35a74a154912f93d4e75a1e6ff3cc146f934b" - integrity sha512-tD6xR/xyZTwfhKYRw0ylfCY8wbfhrjpKAMnDKRTLMy2fNW5hl0hoV6ap5vo2JdCkuHkP3CHw72beO4Y8pzFdww== +postcss-discard-unused@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/postcss-discard-unused/-/postcss-discard-unused-5.1.0.tgz#8974e9b143d887677304e558c1166d3762501142" + integrity sha512-KwLWymI9hbwXmJa0dkrzpRbSJEh0vVUd7r8t0yOGPcfKzyJJxFM8kLyC5Ev9avji6nY95pOp1W6HqIrfT+0VGw== dependencies: postcss-selector-parser "^6.0.5" -postcss-loader@^6.1.1: - version "6.2.1" - resolved "https://registry.yarnpkg.com/postcss-loader/-/postcss-loader-6.2.1.tgz#0895f7346b1702103d30fdc66e4d494a93c008ef" - integrity sha512-WbbYpmAaKcux/P66bZ40bpWsBucjx/TTgVVzRZ9yUO8yQfVBlameJ0ZGVaPfH64hNSBh63a+ICP5nqOpBA0w+Q== +postcss-loader@^7.0.0: + version "7.0.1" + resolved "https://registry.yarnpkg.com/postcss-loader/-/postcss-loader-7.0.1.tgz#4c883cc0a1b2bfe2074377b7a74c1cd805684395" + integrity sha512-VRviFEyYlLjctSM93gAZtcJJ/iSkPZ79zWbN/1fSH+NisBByEiVLqpdVDrPLVSi8DX0oJo12kL/GppTBdKVXiQ== dependencies: cosmiconfig "^7.0.0" klona "^2.0.5" - semver "^7.3.5" + semver "^7.3.7" -postcss-merge-idents@^5.0.2: - version "5.0.2" - resolved "https://registry.yarnpkg.com/postcss-merge-idents/-/postcss-merge-idents-5.0.2.tgz#d67d9505857a9546c3f7a305386e4147497322d6" - integrity sha512-V8IlmvQez+/mB06touksO3lUKtzL3ZKfBxfXFK2q136TOyOLXBuoI8kQwZsIOFWUfA8gk/XpFtmMsqURqYPk6Q== +postcss-merge-idents@^5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/postcss-merge-idents/-/postcss-merge-idents-5.1.1.tgz#7753817c2e0b75d0853b56f78a89771e15ca04a1" + integrity sha512-pCijL1TREiCoog5nQp7wUe+TUonA2tC2sQ54UGeMmryK3UFGIYKqDyjnqd6RcuI4znFn9hWSLNN8xKE/vWcUQw== dependencies: - cssnano-utils "^3.0.0" + cssnano-utils "^3.1.0" postcss-value-parser "^4.2.0" -postcss-merge-longhand@^5.0.4: - version "5.0.4" - resolved "https://registry.yarnpkg.com/postcss-merge-longhand/-/postcss-merge-longhand-5.0.4.tgz#41f4f3270282ea1a145ece078b7679f0cef21c32" - integrity sha512-2lZrOVD+d81aoYkZDpWu6+3dTAAGkCKbV5DoRhnIR7KOULVrI/R7bcMjhrH9KTRy6iiHKqmtG+n/MMj1WmqHFw== +postcss-merge-longhand@^5.1.7: + version "5.1.7" + resolved "https://registry.yarnpkg.com/postcss-merge-longhand/-/postcss-merge-longhand-5.1.7.tgz#24a1bdf402d9ef0e70f568f39bdc0344d568fb16" + integrity sha512-YCI9gZB+PLNskrK0BB3/2OzPnGhPkBEwmwhfYk1ilBHYVAZB7/tkTHFBAnCrvBBOmeYyMYw3DMjT55SyxMBzjQ== dependencies: - postcss-value-parser "^4.1.0" - stylehacks "^5.0.1" + postcss-value-parser "^4.2.0" + stylehacks "^5.1.1" -postcss-merge-rules@^5.0.4: - version "5.0.4" - resolved "https://registry.yarnpkg.com/postcss-merge-rules/-/postcss-merge-rules-5.0.4.tgz#a50640fd832380f322bd2861a9b33fbde4219f9b" - integrity sha512-yOj7bW3NxlQxaERBB0lEY1sH5y+RzevjbdH4DBJurjKERNpknRByFNdNe+V72i5pIZL12woM9uGdS5xbSB+kDQ== +postcss-merge-rules@^5.1.3: + version "5.1.3" + resolved "https://registry.yarnpkg.com/postcss-merge-rules/-/postcss-merge-rules-5.1.3.tgz#8f97679e67cc8d08677a6519afca41edf2220894" + integrity sha512-LbLd7uFC00vpOuMvyZop8+vvhnfRGpp2S+IMQKeuOZZapPRY4SMq5ErjQeHbHsjCUgJkRNrlU+LmxsKIqPKQlA== dependencies: - browserslist "^4.16.6" + browserslist "^4.21.4" caniuse-api "^3.0.0" - cssnano-utils "^3.0.0" + cssnano-utils "^3.1.0" postcss-selector-parser "^6.0.5" -postcss-minify-font-values@^5.0.2: - version "5.0.2" - resolved "https://registry.yarnpkg.com/postcss-minify-font-values/-/postcss-minify-font-values-5.0.2.tgz#4603e956d85cd0719156e2b3eb68e3cd2f917092" - integrity sha512-R6MJZryq28Cw0AmnyhXrM7naqJZZLoa1paBltIzh2wM7yb4D45TLur+eubTQ4jCmZU9SGeZdWsc5KcSoqTMeTg== +postcss-minify-font-values@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/postcss-minify-font-values/-/postcss-minify-font-values-5.1.0.tgz#f1df0014a726083d260d3bd85d7385fb89d1f01b" + integrity sha512-el3mYTgx13ZAPPirSVsHqFzl+BBBDrXvbySvPGFnQcTI4iNslrPaFq4muTkLZmKlGk4gyFAYUBMH30+HurREyA== dependencies: postcss-value-parser "^4.2.0" -postcss-minify-gradients@^5.0.4: - version "5.0.4" - resolved "https://registry.yarnpkg.com/postcss-minify-gradients/-/postcss-minify-gradients-5.0.4.tgz#f13146950513f5a201015306914e3c76d10b591d" - integrity sha512-RVwZA7NC4R4J76u8X0Q0j+J7ItKUWAeBUJ8oEEZWmtv3Xoh19uNJaJwzNpsydQjk6PkuhRrK+YwwMf+c+68EYg== +postcss-minify-gradients@^5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/postcss-minify-gradients/-/postcss-minify-gradients-5.1.1.tgz#f1fe1b4f498134a5068240c2f25d46fcd236ba2c" + integrity sha512-VGvXMTpCEo4qHTNSa9A0a3D+dxGFZCYwR6Jokk+/3oB6flu2/PnPXAh2x7x52EkY5xlIHLm+Le8tJxe/7TNhzw== dependencies: colord "^2.9.1" - cssnano-utils "^3.0.0" + cssnano-utils "^3.1.0" postcss-value-parser "^4.2.0" -postcss-minify-params@^5.0.3: - version "5.0.3" - resolved "https://registry.yarnpkg.com/postcss-minify-params/-/postcss-minify-params-5.0.3.tgz#9f933d37098ef1dcf007e159a47bb2c1cf06989d" - integrity sha512-NY92FUikE+wralaiVexFd5gwb7oJTIDhgTNeIw89i1Ymsgt4RWiPXfz3bg7hDy4NL6gepcThJwOYNtZO/eNi7Q== +postcss-minify-params@^5.1.4: + version "5.1.4" + resolved "https://registry.yarnpkg.com/postcss-minify-params/-/postcss-minify-params-5.1.4.tgz#c06a6c787128b3208b38c9364cfc40c8aa5d7352" + integrity sha512-+mePA3MgdmVmv6g+30rn57USjOGSAyuxUmkfiWpzalZ8aiBkdPYjXWtHuwJGm1v5Ojy0Z0LaSYhHaLJQB0P8Jw== dependencies: - alphanum-sort "^1.0.2" - browserslist "^4.16.6" - cssnano-utils "^3.0.0" + browserslist "^4.21.4" + cssnano-utils "^3.1.0" postcss-value-parser "^4.2.0" -postcss-minify-selectors@^5.1.1: - version "5.1.1" - resolved "https://registry.yarnpkg.com/postcss-minify-selectors/-/postcss-minify-selectors-5.1.1.tgz#20ae03b411f7fb397451e3d7d85b989f944b871c" - integrity sha512-TOzqOPXt91O2luJInaVPiivh90a2SIK5Nf1Ea7yEIM/5w+XA5BGrZGUSW8aEx9pJ/oNj7ZJBhjvigSiBV+bC1Q== +postcss-minify-selectors@^5.2.1: + version "5.2.1" + resolved "https://registry.yarnpkg.com/postcss-minify-selectors/-/postcss-minify-selectors-5.2.1.tgz#d4e7e6b46147b8117ea9325a915a801d5fe656c6" + integrity sha512-nPJu7OjZJTsVUmPdm2TcaiohIwxP+v8ha9NehQ2ye9szv4orirRU3SDdtUmKH+10nzn0bAyOXZ0UEr7OpvLehg== dependencies: - alphanum-sort "^1.0.2" postcss-selector-parser "^6.0.5" postcss-modules-extract-imports@^3.0.0: @@ -6178,158 +5998,157 @@ postcss-modules-values@^4.0.0: dependencies: icss-utils "^5.0.0" -postcss-normalize-charset@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/postcss-normalize-charset/-/postcss-normalize-charset-5.0.1.tgz#121559d1bebc55ac8d24af37f67bd4da9efd91d0" - integrity sha512-6J40l6LNYnBdPSk+BHZ8SF+HAkS4q2twe5jnocgd+xWpz/mx/5Sa32m3W1AA8uE8XaXN+eg8trIlfu8V9x61eg== +postcss-normalize-charset@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/postcss-normalize-charset/-/postcss-normalize-charset-5.1.0.tgz#9302de0b29094b52c259e9b2cf8dc0879879f0ed" + integrity sha512-mSgUJ+pd/ldRGVx26p2wz9dNZ7ji6Pn8VWBajMXFf8jk7vUoSrZ2lt/wZR7DtlZYKesmZI680qjr2CeFF2fbUg== -postcss-normalize-display-values@^5.0.2: - version "5.0.2" - resolved "https://registry.yarnpkg.com/postcss-normalize-display-values/-/postcss-normalize-display-values-5.0.2.tgz#8b5273c6c7d0a445e6ef226b8a5bb3204a55fb99" - integrity sha512-RxXoJPUR0shSjkMMzgEZDjGPrgXUVYyWA/YwQRicb48H15OClPuaDR7tYokLAlGZ2tCSENEN5WxjgxSD5m4cUw== +postcss-normalize-display-values@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/postcss-normalize-display-values/-/postcss-normalize-display-values-5.1.0.tgz#72abbae58081960e9edd7200fcf21ab8325c3da8" + integrity sha512-WP4KIM4o2dazQXWmFaqMmcvsKmhdINFblgSeRgn8BJ6vxaMyaJkwAzpPpuvSIoG/rmX3M+IrRZEz2H0glrQNEA== dependencies: postcss-value-parser "^4.2.0" -postcss-normalize-positions@^5.0.2: - version "5.0.2" - resolved "https://registry.yarnpkg.com/postcss-normalize-positions/-/postcss-normalize-positions-5.0.2.tgz#799fa494b352a5da183be8f050024af6d92fa29c" - integrity sha512-tqghWFVDp2btqFg1gYob1etPNxXLNh3uVeWgZE2AQGh6b2F8AK2Gj36v5Vhyh+APwIzNjmt6jwZ9pTBP+/OM8g== +postcss-normalize-positions@^5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/postcss-normalize-positions/-/postcss-normalize-positions-5.1.1.tgz#ef97279d894087b59325b45c47f1e863daefbb92" + integrity sha512-6UpCb0G4eofTCQLFVuI3EVNZzBNPiIKcA1AKVka+31fTVySphr3VUgAIULBhxZkKgwLImhzMR2Bw1ORK+37INg== dependencies: postcss-value-parser "^4.2.0" -postcss-normalize-repeat-style@^5.0.2: - version "5.0.2" - resolved "https://registry.yarnpkg.com/postcss-normalize-repeat-style/-/postcss-normalize-repeat-style-5.0.2.tgz#fd9bddba3e6fd5f5d95c18dfb42a09ecd563adea" - integrity sha512-/rIZn8X9bBzC7KvY4iKUhXUGW3MmbXwfPF23jC9wT9xTi7kAvgj8sEgwxjixBmoL6MVa4WOgxNz2hAR6wTK8tw== +postcss-normalize-repeat-style@^5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/postcss-normalize-repeat-style/-/postcss-normalize-repeat-style-5.1.1.tgz#e9eb96805204f4766df66fd09ed2e13545420fb2" + integrity sha512-mFpLspGWkQtBcWIRFLmewo8aC3ImN2i/J3v8YCFUwDnPu3Xz4rLohDO26lGjwNsQxB3YF0KKRwspGzE2JEuS0g== dependencies: postcss-value-parser "^4.2.0" -postcss-normalize-string@^5.0.2: - version "5.0.2" - resolved "https://registry.yarnpkg.com/postcss-normalize-string/-/postcss-normalize-string-5.0.2.tgz#1b2bbf91526f61266f28abf7f773e4136b2c4bd2" - integrity sha512-zaI1yzwL+a/FkIzUWMQoH25YwCYxi917J4pYm1nRXtdgiCdnlTkx5eRzqWEC64HtRa06WCJ9TIutpb6GmW4gFw== +postcss-normalize-string@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/postcss-normalize-string/-/postcss-normalize-string-5.1.0.tgz#411961169e07308c82c1f8c55f3e8a337757e228" + integrity sha512-oYiIJOf4T9T1N4i+abeIc7Vgm/xPCGih4bZz5Nm0/ARVJ7K6xrDlLwvwqOydvyL3RHNf8qZk6vo3aatiw/go3w== dependencies: postcss-value-parser "^4.2.0" -postcss-normalize-timing-functions@^5.0.2: - version "5.0.2" - resolved "https://registry.yarnpkg.com/postcss-normalize-timing-functions/-/postcss-normalize-timing-functions-5.0.2.tgz#db4f4f49721f47667afd1fdc5edb032f8d9cdb2e" - integrity sha512-Ao0PP6MoYsRU1LxeVUW740ioknvdIUmfr6uAA3xWlQJ9s69/Tupy8qwhuKG3xWfl+KvLMAP9p2WXF9cwuk/7Bg== +postcss-normalize-timing-functions@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/postcss-normalize-timing-functions/-/postcss-normalize-timing-functions-5.1.0.tgz#d5614410f8f0b2388e9f240aa6011ba6f52dafbb" + integrity sha512-DOEkzJ4SAXv5xkHl0Wa9cZLF3WCBhF3o1SKVxKQAa+0pYKlueTpCgvkFAHfk+Y64ezX9+nITGrDZeVGgITJXjg== dependencies: postcss-value-parser "^4.2.0" -postcss-normalize-unicode@^5.0.2: - version "5.0.2" - resolved "https://registry.yarnpkg.com/postcss-normalize-unicode/-/postcss-normalize-unicode-5.0.2.tgz#c4db89a0116066716b9e9fcb6444ce63178f5ced" - integrity sha512-3y/V+vjZ19HNcTizeqwrbZSUsE69ZMRHfiiyLAJb7C7hJtYmM4Gsbajy7gKagu97E8q5rlS9k8FhojA8cpGhWw== +postcss-normalize-unicode@^5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/postcss-normalize-unicode/-/postcss-normalize-unicode-5.1.1.tgz#f67297fca3fea7f17e0d2caa40769afc487aa030" + integrity sha512-qnCL5jzkNUmKVhZoENp1mJiGNPcsJCs1aaRmURmeJGES23Z/ajaln+EPTD+rBeNkSryI+2WTdW+lwcVdOikrpA== dependencies: - browserslist "^4.16.6" + browserslist "^4.21.4" postcss-value-parser "^4.2.0" -postcss-normalize-url@^5.0.4: - version "5.0.4" - resolved "https://registry.yarnpkg.com/postcss-normalize-url/-/postcss-normalize-url-5.0.4.tgz#3b0322c425e31dd275174d0d5db0e466f50810fb" - integrity sha512-cNj3RzK2pgQQyNp7dzq0dqpUpQ/wYtdDZM3DepPmFjCmYIfceuD9VIAcOdvrNetjIU65g1B4uwdP/Krf6AFdXg== +postcss-normalize-url@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/postcss-normalize-url/-/postcss-normalize-url-5.1.0.tgz#ed9d88ca82e21abef99f743457d3729a042adcdc" + integrity sha512-5upGeDO+PVthOxSmds43ZeMeZfKH+/DKgGRD7TElkkyS46JXAUhMzIKiCa7BabPeIy3AQcTkXwVVN7DbqsiCew== dependencies: normalize-url "^6.0.1" postcss-value-parser "^4.2.0" -postcss-normalize-whitespace@^5.0.2: - version "5.0.2" - resolved "https://registry.yarnpkg.com/postcss-normalize-whitespace/-/postcss-normalize-whitespace-5.0.2.tgz#92c5eaffe5255b5c43fca0baf19227e607c534db" - integrity sha512-CXBx+9fVlzSgbk0IXA/dcZn9lXixnQRndnsPC5ht3HxlQ1bVh77KQDL1GffJx1LTzzfae8ftMulsjYmO2yegxA== +postcss-normalize-whitespace@^5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/postcss-normalize-whitespace/-/postcss-normalize-whitespace-5.1.1.tgz#08a1a0d1ffa17a7cc6efe1e6c9da969cc4493cfa" + integrity sha512-83ZJ4t3NUDETIHTa3uEg6asWjSBYL5EdkVB0sDncx9ERzOKBVJIUeDO9RyA9Zwtig8El1d79HBp0JEi8wvGQnA== dependencies: postcss-value-parser "^4.2.0" -postcss-ordered-values@^5.0.3: - version "5.0.3" - resolved "https://registry.yarnpkg.com/postcss-ordered-values/-/postcss-ordered-values-5.0.3.tgz#d80a8565f2e21efe8a06abacd60629a783bbcf54" - integrity sha512-T9pDS+P9bWeFvqivXd5ACzQmrCmHjv3ZP+djn8E1UZY7iK79pFSm7i3WbKw2VSmFmdbMm8sQ12OPcNpzBo3Z2w== +postcss-ordered-values@^5.1.3: + version "5.1.3" + resolved "https://registry.yarnpkg.com/postcss-ordered-values/-/postcss-ordered-values-5.1.3.tgz#b6fd2bd10f937b23d86bc829c69e7732ce76ea38" + integrity sha512-9UO79VUhPwEkzbb3RNpqqghc6lcYej1aveQteWY+4POIwlqkYE21HKWaLDF6lWNuqCobEAyTovVhtI32Rbv2RQ== dependencies: - cssnano-utils "^3.0.0" + cssnano-utils "^3.1.0" postcss-value-parser "^4.2.0" -postcss-reduce-idents@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/postcss-reduce-idents/-/postcss-reduce-idents-5.0.1.tgz#99b49ce8ee6f9c179447671cc9693e198e877bb7" - integrity sha512-6Rw8iIVFbqtaZExgWK1rpVgP7DPFRPh0DDFZxJ/ADNqPiH10sPCoq5tgo6kLiTyfh9sxjKYjXdc8udLEcPOezg== +postcss-reduce-idents@^5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/postcss-reduce-idents/-/postcss-reduce-idents-5.2.0.tgz#c89c11336c432ac4b28792f24778859a67dfba95" + integrity sha512-BTrLjICoSB6gxbc58D5mdBK8OhXRDqud/zodYfdSi52qvDHdMwk+9kB9xsM8yJThH/sZU5A6QVSmMmaN001gIg== dependencies: - postcss-value-parser "^4.1.0" + postcss-value-parser "^4.2.0" -postcss-reduce-initial@^5.0.2: - version "5.0.2" - resolved "https://registry.yarnpkg.com/postcss-reduce-initial/-/postcss-reduce-initial-5.0.2.tgz#fa424ce8aa88a89bc0b6d0f94871b24abe94c048" - integrity sha512-v/kbAAQ+S1V5v9TJvbGkV98V2ERPdU6XvMcKMjqAlYiJ2NtsHGlKYLPjWWcXlaTKNxooId7BGxeraK8qXvzKtw== +postcss-reduce-initial@^5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/postcss-reduce-initial/-/postcss-reduce-initial-5.1.1.tgz#c18b7dfb88aee24b1f8e4936541c29adbd35224e" + integrity sha512-//jeDqWcHPuXGZLoolFrUXBDyuEGbr9S2rMo19bkTIjBQ4PqkaO+oI8wua5BOUxpfi97i3PCoInsiFIEBfkm9w== dependencies: - browserslist "^4.16.6" + browserslist "^4.21.4" caniuse-api "^3.0.0" -postcss-reduce-transforms@^5.0.2: - version "5.0.2" - resolved "https://registry.yarnpkg.com/postcss-reduce-transforms/-/postcss-reduce-transforms-5.0.2.tgz#9242758629f9ad4d90312eadbc921259d15bee4d" - integrity sha512-25HeDeFsgiPSUx69jJXZn8I06tMxLQJJNF5h7i9gsUg8iP4KOOJ8EX8fj3seeoLt3SLU2YDD6UPnDYVGUO7DEA== +postcss-reduce-transforms@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/postcss-reduce-transforms/-/postcss-reduce-transforms-5.1.0.tgz#333b70e7758b802f3dd0ddfe98bb1ccfef96b6e9" + integrity sha512-2fbdbmgir5AvpW9RLtdONx1QoYG2/EtqpNQbFASDlixBbAYuTcJ0dECwlqNqH7VbaUnEnh8SrxOe2sRIn24XyQ== dependencies: postcss-value-parser "^4.2.0" -postcss-selector-parser@^6.0.2, postcss-selector-parser@^6.0.4, postcss-selector-parser@^6.0.5: - version "6.0.8" - resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-6.0.8.tgz#f023ed7a9ea736cd7ef70342996e8e78645a7914" - integrity sha512-D5PG53d209Z1Uhcc0qAZ5U3t5HagH3cxu+WLZ22jt3gLUpXM4eXXfiO14jiDWST3NNooX/E8wISfOhZ9eIjGTQ== +postcss-selector-parser@^6.0.2, postcss-selector-parser@^6.0.4, postcss-selector-parser@^6.0.5, postcss-selector-parser@^6.0.9: + version "6.0.11" + resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-6.0.11.tgz#2e41dc39b7ad74046e1615185185cd0b17d0c8dc" + integrity sha512-zbARubNdogI9j7WY4nQJBiNqQf3sLS3wCP4WfOidu+p28LofJqDH1tcXypGrcmMHhDk2t9wGhCsYe/+szLTy1g== dependencies: cssesc "^3.0.0" util-deprecate "^1.0.2" -postcss-sort-media-queries@^4.1.0: - version "4.2.1" - resolved "https://registry.yarnpkg.com/postcss-sort-media-queries/-/postcss-sort-media-queries-4.2.1.tgz#a99bae69ef1098ee3b64a5fa94d258ec240d0355" - integrity sha512-9VYekQalFZ3sdgcTjXMa0dDjsfBVHXlraYJEMiOJ/2iMmI2JGCMavP16z3kWOaRu8NSaJCTgVpB/IVpH5yT9YQ== +postcss-sort-media-queries@^4.2.1: + version "4.3.0" + resolved "https://registry.yarnpkg.com/postcss-sort-media-queries/-/postcss-sort-media-queries-4.3.0.tgz#f48a77d6ce379e86676fc3f140cf1b10a06f6051" + integrity sha512-jAl8gJM2DvuIJiI9sL1CuiHtKM4s5aEIomkU8G3LFvbP+p8i7Sz8VV63uieTgoewGqKbi+hxBTiOKJlB35upCg== dependencies: - sort-css-media-queries "2.0.4" + sort-css-media-queries "2.1.0" -postcss-svgo@^5.0.3: - version "5.0.3" - resolved "https://registry.yarnpkg.com/postcss-svgo/-/postcss-svgo-5.0.3.tgz#d945185756e5dfaae07f9edb0d3cae7ff79f9b30" - integrity sha512-41XZUA1wNDAZrQ3XgWREL/M2zSw8LJPvb5ZWivljBsUQAGoEKMYm6okHsTjJxKYI4M75RQEH4KYlEM52VwdXVA== +postcss-svgo@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/postcss-svgo/-/postcss-svgo-5.1.0.tgz#0a317400ced789f233a28826e77523f15857d80d" + integrity sha512-D75KsH1zm5ZrHyxPakAxJWtkyXew5qwS70v56exwvw542d9CRtTo78K0WeFxZB4G7JXKKMbEZtZayTGdIky/eA== dependencies: - postcss-value-parser "^4.1.0" + postcss-value-parser "^4.2.0" svgo "^2.7.0" -postcss-unique-selectors@^5.0.2: - version "5.0.2" - resolved "https://registry.yarnpkg.com/postcss-unique-selectors/-/postcss-unique-selectors-5.0.2.tgz#5d6893daf534ae52626708e0d62250890108c0c1" - integrity sha512-w3zBVlrtZm7loQWRPVC0yjUwwpty7OM6DnEHkxcSQXO1bMS3RJ+JUS5LFMSDZHJcvGsRwhZinCWVqn8Kej4EDA== +postcss-unique-selectors@^5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/postcss-unique-selectors/-/postcss-unique-selectors-5.1.1.tgz#a9f273d1eacd09e9aa6088f4b0507b18b1b541b6" + integrity sha512-5JiODlELrz8L2HwxfPnhOWZYWDxVHWL83ufOv84NrcgipI7TaeRsatAhK4Tr2/ZiYldpK/wBvw5BD3qfaK96GA== dependencies: - alphanum-sort "^1.0.2" postcss-selector-parser "^6.0.5" -postcss-value-parser@^4.0.2, postcss-value-parser@^4.1.0, postcss-value-parser@^4.2.0: +postcss-value-parser@^4.1.0, postcss-value-parser@^4.2.0: version "4.2.0" resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz#723c09920836ba6d3e5af019f92bc0971c02e514" integrity sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ== -postcss-zindex@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/postcss-zindex/-/postcss-zindex-5.0.1.tgz#c585724beb69d356af8c7e68847b28d6298ece03" - integrity sha512-nwgtJJys+XmmSGoYCcgkf/VczP8Mp/0OfSv3v0+fw0uABY4yxw+eFs0Xp9nAZHIKnS5j+e9ywQ+RD+ONyvl5pA== +postcss-zindex@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/postcss-zindex/-/postcss-zindex-5.1.0.tgz#4a5c7e5ff1050bd4c01d95b1847dfdcc58a496ff" + integrity sha512-fgFMf0OtVSBR1va1JNHYgMxYk73yhn/qb4uQDq1DLGYolz8gHCyr/sesEuGUaYs58E3ZJRcpoGuPVoB7Meiq9A== -postcss@^8.2.15, postcss@^8.3.11, postcss@^8.3.5, postcss@^8.3.7: - version "8.4.5" - resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.5.tgz#bae665764dfd4c6fcc24dc0fdf7e7aa00cc77f95" - integrity sha512-jBDboWM8qpaqwkMwItqTQTiFikhs/67OYVvblFFTM7MrZjt6yMKd6r2kgXizEbTTljacm4NldIlZnhbjr84QYg== +postcss@^8.3.11, postcss@^8.4.14, postcss@^8.4.17, postcss@^8.4.18: + version "8.4.19" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.19.tgz#61178e2add236b17351897c8bcc0b4c8ecab56fc" + integrity sha512-h+pbPsyhlYj6N2ozBmHhHrs9DzGmbaarbLvWipMRO7RLS+v4onj26MPFXA5OBYFxyqYhUJK456SwDcY9H2/zsA== dependencies: - nanoid "^3.1.30" + nanoid "^3.3.4" picocolors "^1.0.0" - source-map-js "^1.0.1" + source-map-js "^1.0.2" prelude-ls@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54" - integrity sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ= + integrity sha512-ESF23V4SKG6lVSGZgYNpbsiaAkdab6ZgOxe52p7+Kid3W3u3bxR4Vfd/o21dmN7jSt0IwgZ4v5MUd26FEtXE9w== prepend-http@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-2.0.0.tgz#e92434bfa5ea8c19f41cdfd401d741a3c819d897" - integrity sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc= + integrity sha512-ravE6m9Atw9Z/jjttRUZ+clIXogdghyZAuWJ3qEzjT+jI/dL1ifAqhZeC5VHzQp1MSt1+jxKkFNemj/iO7tVUA== pretty-error@^4.0.0: version "4.0.0" @@ -6344,15 +6163,15 @@ pretty-time@^1.1.0: resolved "https://registry.yarnpkg.com/pretty-time/-/pretty-time-1.1.0.tgz#ffb7429afabb8535c346a34e41873adf3d74dd0e" integrity sha512-28iF6xPQrP8Oa6uxE6a1biz+lWeTOAPKggvjB8HAs6nVMKZwf5bG++632Dx614hIWgUPkgivRfG+a8uAXGTIbA== -prism-react-renderer@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/prism-react-renderer/-/prism-react-renderer-1.2.1.tgz#392460acf63540960e5e3caa699d851264e99b89" - integrity sha512-w23ch4f75V1Tnz8DajsYKvY5lF7H1+WvzvLUcF0paFxkTHSp42RS0H5CttdN2Q8RR3DRGZ9v5xD/h3n8C8kGmg== +prism-react-renderer@^1.2.1, prism-react-renderer@^1.3.5: + version "1.3.5" + resolved "https://registry.yarnpkg.com/prism-react-renderer/-/prism-react-renderer-1.3.5.tgz#786bb69aa6f73c32ba1ee813fbe17a0115435085" + integrity sha512-IJ+MSwBWKG+SM3b2SUfdrhC+gu01QkV2KmRQgREThBfSQRoufqRfxfHUxpG1WcaFjP+kojcFyO9Qqtpgt3qLCg== -prismjs@^1.23.0: - version "1.26.0" - resolved "https://registry.yarnpkg.com/prismjs/-/prismjs-1.26.0.tgz#16881b594828bb6b45296083a8cbab46b0accd47" - integrity sha512-HUoH9C5Z3jKkl3UunCyiD5jwk0+Hz0fIgQ2nbwU2Oo/ceuTAQAg+pPVnfdt2TJWRVLcxKh9iuoYDUSc8clb5UQ== +prismjs@^1.28.0: + version "1.29.0" + resolved "https://registry.yarnpkg.com/prismjs/-/prismjs-1.29.0.tgz#f113555a8fa9b57c35e637bba27509dcf802dd12" + integrity sha512-Kx/1w86q/epKcmte75LNrEoT+lX8pBpavuAbvJWRXar7Hz8jrtF+e3vY751p0R8H9HdArwaCTNDDzHg/ScJK1Q== process-nextick-args@~2.0.0: version "2.0.1" @@ -6366,7 +6185,7 @@ promise@^7.1.1: dependencies: asap "~2.0.3" -prompts@^2.4.1, prompts@^2.4.2: +prompts@^2.4.2: version "2.4.2" resolved "https://registry.yarnpkg.com/prompts/-/prompts-2.4.2.tgz#7b57e73b3a48029ad10ebd44f74b01722a4cb069" integrity sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q== @@ -6391,9 +6210,9 @@ property-information@^5.0.0, property-information@^5.3.0: xtend "^4.0.0" property-information@^6.0.0: - version "6.1.1" - resolved "https://registry.yarnpkg.com/property-information/-/property-information-6.1.1.tgz#5ca85510a3019726cb9afed4197b7b8ac5926a22" - integrity sha512-hrzC564QIl0r0vy4l6MvRLhafmUowhO/O3KgVSoXIbbA2Sz4j8HGpJc6T2cubRVwMwpdiG/vKGfhT4IixmKN9w== + version "6.2.0" + resolved "https://registry.yarnpkg.com/property-information/-/property-information-6.2.0.tgz#b74f522c31c097b5149e3c3cb8d7f3defd986a1d" + integrity sha512-kma4U7AFCTwpqq5twzC1YVIDXSqg6qQK6JN0smOw8fgRy1OkMi0CYSzFmsy6dnqSenamAtj0CyXMUJ1Mf6oROg== proxy-addr@~2.0.7: version "2.0.7" @@ -6404,9 +6223,9 @@ proxy-addr@~2.0.7: ipaddr.js "1.9.1" psl@^1.1.33: - version "1.8.0" - resolved "https://registry.yarnpkg.com/psl/-/psl-1.8.0.tgz#9326f8bcfb013adcc005fdff056acce020e51c24" - integrity sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ== + version "1.9.0" + resolved "https://registry.yarnpkg.com/psl/-/psl-1.9.0.tgz#d0df2a137f00794565fcaf3b2c00cd09f8d5a5a7" + integrity sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag== pump@^3.0.0: version "3.0.0" @@ -6416,15 +6235,10 @@ pump@^3.0.0: end-of-stream "^1.1.0" once "^1.3.1" -punycode@1.3.2: - version "1.3.2" - resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.3.2.tgz#9653a036fb7c1ee42342f2325cceefea3926c48d" - integrity sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0= - punycode@^1.3.2: version "1.4.1" resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e" - integrity sha1-wNWmOycYgArY4esPpSachN1BhF4= + integrity sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ== punycode@^2.1.0, punycode@^2.1.1: version "2.1.1" @@ -6441,17 +6255,19 @@ pupa@^2.1.1: pure-color@^1.2.0: version "1.3.0" resolved "https://registry.yarnpkg.com/pure-color/-/pure-color-1.3.0.tgz#1fe064fb0ac851f0de61320a8bf796836422f33e" - integrity sha1-H+Bk+wrIUfDeYTIKi/eWg2Qi8z4= + integrity sha512-QFADYnsVoBMw1srW7OVKEYjG+MbIa49s54w1MA1EDY6r2r/sTcKKYqRX1f4GYvnXP7eN/Pe9HFcX+hwzmrXRHA== -qs@6.9.6: - version "6.9.6" - resolved "https://registry.yarnpkg.com/qs/-/qs-6.9.6.tgz#26ed3c8243a431b2924aca84cc90471f35d5a0ee" - integrity sha512-TIRk4aqYLNoJUbd+g2lEdz5kLWIuTMRagAXxl78Q0RiVjAOugHmeKNGdd3cwo/ktpf9aL9epCfFqWDEKysUlLQ== +qs@6.11.0: + version "6.11.0" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.11.0.tgz#fd0d963446f7a65e1367e01abd85429453f0c37a" + integrity sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q== + dependencies: + side-channel "^1.0.4" -querystring@0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/querystring/-/querystring-0.2.0.tgz#b209849203bb25df820da756e747005878521620" - integrity sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA= +querystringify@^2.1.1: + version "2.2.0" + resolved "https://registry.yarnpkg.com/querystringify/-/querystringify-2.2.0.tgz#3345941b4153cb9d082d8eee4cda2016a9aef7f6" + integrity sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ== queue-microtask@^1.2.2: version "1.2.3" @@ -6475,24 +6291,24 @@ randombytes@^2.1.0: range-parser@1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.0.tgz#f49be6b487894ddc40dcc94a322f611092e00d5e" - integrity sha1-9JvmtIeJTdxA3MlKMi9hEJLgDV4= + integrity sha512-kA5WQoNVo4t9lNx2kQNFCxKeBl5IbbSNBl1M/tLkw9WCn+hxNBAW5Qh8gdhs63CJnhjJ2zQWFoqPJP2sK1AV5A== range-parser@^1.2.1, range-parser@~1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031" integrity sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg== -raw-body@2.4.2: - version "2.4.2" - resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.4.2.tgz#baf3e9c21eebced59dd6533ac872b71f7b61cb32" - integrity sha512-RPMAFUJP19WIet/99ngh6Iv8fzAbqum4Li7AD6DtGaW2RpMB/11xDoalPiJMTbu6I3hkbMVkATvZrqb9EEqeeQ== +raw-body@2.5.1: + version "2.5.1" + resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.5.1.tgz#fe1b1628b181b700215e5fd42389f98b71392857" + integrity sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig== dependencies: - bytes "3.1.1" - http-errors "1.8.1" + bytes "3.1.2" + http-errors "2.0.0" iconv-lite "0.4.24" unpipe "1.0.0" -rc@^1.2.8: +rc@1.2.8, rc@^1.2.8: version "1.2.8" resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed" integrity sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw== @@ -6505,17 +6321,17 @@ rc@^1.2.8: react-base16-styling@^0.6.0: version "0.6.0" resolved "https://registry.yarnpkg.com/react-base16-styling/-/react-base16-styling-0.6.0.tgz#ef2156d66cf4139695c8a167886cb69ea660792c" - integrity sha1-7yFW1mz0E5aVyKFniGy2nqZgeSw= + integrity sha512-yvh/7CArceR/jNATXOKDlvTnPKPmGZz7zsenQ3jUwLzHkNUR0CvY3yGYJbWJ/nnxsL8Sgmt5cO3/SILVuPO6TQ== dependencies: base16 "^1.0.0" lodash.curry "^4.0.1" lodash.flow "^3.3.0" pure-color "^1.2.0" -react-dev-utils@^12.0.0: - version "12.0.0" - resolved "https://registry.yarnpkg.com/react-dev-utils/-/react-dev-utils-12.0.0.tgz#4eab12cdb95692a077616770b5988f0adf806526" - integrity sha512-xBQkitdxozPxt1YZ9O1097EJiVpwHr9FoAuEVURCKV0Av8NBERovJauzP7bo1ThvuhZ4shsQ1AJiu4vQpoT1AQ== +react-dev-utils@^12.0.1: + version "12.0.1" + resolved "https://registry.yarnpkg.com/react-dev-utils/-/react-dev-utils-12.0.1.tgz#ba92edb4a1f379bd46ccd6bcd4e7bc398df33e73" + integrity sha512-84Ivxmr17KjUupyqzFode6xKhjwuEJDROWKJy/BthkL7Wn6NJ8h4WE6k/exAv6ImS+0oZLRRW5j/aINMHyeGeQ== dependencies: "@babel/code-frame" "^7.16.0" address "^1.1.2" @@ -6536,7 +6352,7 @@ react-dev-utils@^12.0.0: open "^8.4.0" pkg-up "^3.1.0" prompts "^2.4.2" - react-error-overlay "^6.0.10" + react-error-overlay "^6.0.11" recursive-readdir "^2.2.2" shell-quote "^1.7.3" strip-ansi "^6.0.1" @@ -6551,25 +6367,26 @@ react-dom@^17.0.1: object-assign "^4.1.1" scheduler "^0.20.2" -react-error-overlay@^6.0.10: - version "6.0.10" - resolved "https://registry.yarnpkg.com/react-error-overlay/-/react-error-overlay-6.0.10.tgz#0fe26db4fa85d9dbb8624729580e90e7159a59a6" - integrity sha512-mKR90fX7Pm5seCOfz8q9F+66VCc1PGsWSBxKbITjfKVQHMNF2zudxHnMdJiB1fRCb+XsbQV9sO9DCkgsMQgBIA== +react-error-overlay@^6.0.11: + version "6.0.11" + resolved "https://registry.yarnpkg.com/react-error-overlay/-/react-error-overlay-6.0.11.tgz#92835de5841c5cf08ba00ddd2d677b6d17ff9adb" + integrity sha512-/6UZ2qgEyH2aqzYZgQPxEnz33NJ2gNsnHA2o5+o4wW9bLM/JYQitNP9xPhsXwC08hMMovfGe/8retsdDsczPRg== -react-fast-compare@^3.1.1: +react-fast-compare@^3.2.0: version "3.2.0" resolved "https://registry.yarnpkg.com/react-fast-compare/-/react-fast-compare-3.2.0.tgz#641a9da81b6a6320f270e89724fb45a0b39e43bb" integrity sha512-rtGImPZ0YyLrscKI9xTpV8psd6I8VAtjKCzQDlzyDvqJA8XOW78TXYQwNRNd8g8JZnDu8q9Fu/1v4HPAVwVdHA== -react-helmet@^6.1.0: - version "6.1.0" - resolved "https://registry.yarnpkg.com/react-helmet/-/react-helmet-6.1.0.tgz#a750d5165cb13cf213e44747502652e794468726" - integrity sha512-4uMzEY9nlDlgxr61NL3XbKRy1hEkXmKNXhjbAIOVw5vcFrsdYbH2FEwcNyWvWinl103nXgzYNlns9ca+8kFiWw== +react-helmet-async@*, react-helmet-async@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/react-helmet-async/-/react-helmet-async-1.3.0.tgz#7bd5bf8c5c69ea9f02f6083f14ce33ef545c222e" + integrity sha512-9jZ57/dAn9t3q6hneQS0wukqC2ENOBgMNVEhb/ZG9ZSxUetzVIw4iAmEU38IaVg3QGYauQPhSeUTuIUtFglWpg== dependencies: - object-assign "^4.1.1" + "@babel/runtime" "^7.12.5" + invariant "^2.2.4" prop-types "^15.7.2" - react-fast-compare "^3.1.1" - react-side-effect "^2.1.0" + react-fast-compare "^3.2.0" + shallowequal "^1.1.0" react-is@^16.13.1, react-is@^16.6.0, react-is@^16.7.0: version "16.13.1" @@ -6605,48 +6422,42 @@ react-router-config@^5.1.1: dependencies: "@babel/runtime" "^7.1.2" -react-router-dom@^5.2.0: - version "5.3.0" - resolved "https://registry.yarnpkg.com/react-router-dom/-/react-router-dom-5.3.0.tgz#da1bfb535a0e89a712a93b97dd76f47ad1f32363" - integrity sha512-ObVBLjUZsphUUMVycibxgMdh5jJ1e3o+KpAZBVeHcNQZ4W+uUGGWsokurzlF4YOldQYRQL4y6yFRWM4m3svmuQ== +react-router-dom@^5.3.3: + version "5.3.4" + resolved "https://registry.yarnpkg.com/react-router-dom/-/react-router-dom-5.3.4.tgz#2ed62ffd88cae6db134445f4a0c0ae8b91d2e5e6" + integrity sha512-m4EqFMHv/Ih4kpcBCONHbkT68KoAeHN4p3lAGoNryfHi0dMy0kCzEZakiKRsvg5wHZ/JLrLW8o8KomWiz/qbYQ== dependencies: "@babel/runtime" "^7.12.13" history "^4.9.0" loose-envify "^1.3.1" prop-types "^15.6.2" - react-router "5.2.1" + react-router "5.3.4" tiny-invariant "^1.0.2" tiny-warning "^1.0.0" -react-router@5.2.1, react-router@^5.2.0: - version "5.2.1" - resolved "https://registry.yarnpkg.com/react-router/-/react-router-5.2.1.tgz#4d2e4e9d5ae9425091845b8dbc6d9d276239774d" - integrity sha512-lIboRiOtDLFdg1VTemMwud9vRVuOCZmUIT/7lUoZiSpPODiiH1UQlfXy+vPLC/7IWdFYnhRwAyNqA/+I7wnvKQ== +react-router@5.3.4, react-router@^5.3.3: + version "5.3.4" + resolved "https://registry.yarnpkg.com/react-router/-/react-router-5.3.4.tgz#8ca252d70fcc37841e31473c7a151cf777887bb5" + integrity sha512-Ys9K+ppnJah3QuaRiLxk+jDWOR1MekYQrlytiXxC1RyfbdsZkS5pvKAzCCr031xHixZwpnsYNT5xysdFHQaYsA== dependencies: "@babel/runtime" "^7.12.13" history "^4.9.0" hoist-non-react-statics "^3.1.0" loose-envify "^1.3.1" - mini-create-react-context "^0.4.0" path-to-regexp "^1.7.0" prop-types "^15.6.2" react-is "^16.6.0" tiny-invariant "^1.0.2" tiny-warning "^1.0.0" -react-side-effect@^2.1.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/react-side-effect/-/react-side-effect-2.1.1.tgz#66c5701c3e7560ab4822a4ee2742dee215d72eb3" - integrity sha512-2FoTQzRNTncBVtnzxFOk2mCpcfxQpenBMbk5kSVBg5UcPqV9fRbgY2zhb7GTWWOlpFmAxhClBDlIq8Rsubz1yQ== - react-textarea-autosize@^8.3.2: - version "8.3.3" - resolved "https://registry.yarnpkg.com/react-textarea-autosize/-/react-textarea-autosize-8.3.3.tgz#f70913945369da453fd554c168f6baacd1fa04d8" - integrity sha512-2XlHXK2TDxS6vbQaoPbMOfQ8GK7+irc2fVK6QFIcC8GOnH3zI/v481n+j1L0WaPVvKxwesnY93fEfH++sus2rQ== + version "8.4.0" + resolved "https://registry.yarnpkg.com/react-textarea-autosize/-/react-textarea-autosize-8.4.0.tgz#4d0244d6a50caa897806b8c44abc0540a69bfc8c" + integrity sha512-YrTFaEHLgJsi8sJVYHBzYn+mkP3prGkmP2DKb/tm0t7CLJY5t1Rxix8070LAKb0wby7bl/lf2EeHkuMihMZMwQ== dependencies: "@babel/runtime" "^7.10.2" - use-composed-ref "^1.0.0" - use-latest "^1.0.0" + use-composed-ref "^1.3.0" + use-latest "^1.2.1" react@^17.0.1: version "17.0.2" @@ -6669,7 +6480,7 @@ readable-stream@^2.0.1: string_decoder "~1.1.1" util-deprecate "~1.0.1" -readable-stream@^3.0.6, readable-stream@^3.1.1: +readable-stream@^3.0.6: version "3.6.0" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198" integrity sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA== @@ -6693,21 +6504,21 @@ reading-time@^1.5.0: rechoir@^0.6.2: version "0.6.2" resolved "https://registry.yarnpkg.com/rechoir/-/rechoir-0.6.2.tgz#85204b54dba82d5742e28c96756ef43af50e3384" - integrity sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q= + integrity sha512-HFM8rkZ+i3zrV+4LQjwQ0W+ez98pApMGM3HUrN04j3CqzPOzl9nmP15Y8YXNm8QHGv/eacOVEjqhmWpkRV0NAw== dependencies: resolve "^1.1.6" recursive-readdir@^2.2.2: - version "2.2.2" - resolved "https://registry.yarnpkg.com/recursive-readdir/-/recursive-readdir-2.2.2.tgz#9946fb3274e1628de6e36b2f6714953b4845094f" - integrity sha512-nRCcW9Sj7NuZwa2XvH9co8NPeXUBhZP7CRKJtU+cS6PW9FpCIFoI5ib0NT1ZrbNuPoRy0ylyCaUL8Gih4LSyFg== + version "2.2.3" + resolved "https://registry.yarnpkg.com/recursive-readdir/-/recursive-readdir-2.2.3.tgz#e726f328c0d69153bcabd5c322d3195252379372" + integrity sha512-8HrF5ZsXk5FAH9dgsx3BlUer73nIhuj+9OrQwEbLTPOBzGkL1lsFCR01am+v+0m2Cmbs1nP12hLDl5FA7EszKA== dependencies: - minimatch "3.0.4" + minimatch "^3.0.5" -regenerate-unicode-properties@^9.0.0: - version "9.0.0" - resolved "https://registry.yarnpkg.com/regenerate-unicode-properties/-/regenerate-unicode-properties-9.0.0.tgz#54d09c7115e1f53dc2314a974b32c1c344efe326" - integrity sha512-3E12UeNSPfjrgwjkR81m5J7Aw/T55Tu7nUyZVQYCKEOs+2dkxEY+DpPtZzO4YruuiPb7NkYLVcyJC4+zCbk5pA== +regenerate-unicode-properties@^10.1.0: + version "10.1.0" + resolved "https://registry.yarnpkg.com/regenerate-unicode-properties/-/regenerate-unicode-properties-10.1.0.tgz#7c3192cab6dd24e21cb4461e5ddd7dd24fa8374c" + integrity sha512-d1VudCLoIGitcU/hEg2QqvyGZQmdC0Lf8BqdOMXGFSvJP4bNV1+XqbPQeHHLD51Jh4QJJ225dlIFvY4Ly6MXmQ== dependencies: regenerate "^1.4.2" @@ -6716,44 +6527,36 @@ regenerate@^1.4.2: resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.4.2.tgz#b9346d8827e8f5a32f7ba29637d398b69014848a" integrity sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A== -regenerator-runtime@^0.13.4: - version "0.13.9" - resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz#8925742a98ffd90814988d7566ad30ca3b263b52" - integrity sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA== +regenerator-runtime@^0.13.10: + version "0.13.11" + resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz#f6dca3e7ceec20590d07ada785636a90cdca17f9" + integrity sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg== -regenerator-transform@^0.14.2: - version "0.14.5" - resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.14.5.tgz#c98da154683671c9c4dcb16ece736517e1b7feb4" - integrity sha512-eOf6vka5IO151Jfsw2NO9WpGX58W6wWmefK3I1zEGr0lOD0u8rwPaNqQL1aRxUaxLeKO3ArNh3VYg1KbaD+FFw== +regenerator-transform@^0.15.0: + version "0.15.1" + resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.15.1.tgz#f6c4e99fc1b4591f780db2586328e4d9a9d8dc56" + integrity sha512-knzmNAcuyxV+gQCufkYcvOqX/qIIfHLv0u5x79kRxuGojfYVky1f15TzZEu2Avte8QGepvUNTnLskf8E6X6Vyg== dependencies: "@babel/runtime" "^7.8.4" -regexp.prototype.flags@^1.2.0: - version "1.3.1" - resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.3.1.tgz#7ef352ae8d159e758c0eadca6f8fcb4eef07be26" - integrity sha512-JiBdRBq91WlY7uRJ0ds7R+dU02i6LKi8r3BuQhNXn+kmeLN+EfHhfjqMRis1zJxnlu88hq/4dx0P2OP3APRTOA== - dependencies: - call-bind "^1.0.2" - define-properties "^1.1.3" - -regexpu-core@^4.5.4, regexpu-core@^4.7.1: - version "4.8.0" - resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-4.8.0.tgz#e5605ba361b67b1718478501327502f4479a98f0" - integrity sha512-1F6bYsoYiz6is+oz70NWur2Vlh9KWtswuRuzJOfeYUrfPX2o8n74AnUVaOGDbUqVGO9fNHu48/pjJO4sNVwsOg== +regexpu-core@^5.1.0: + version "5.2.2" + resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-5.2.2.tgz#3e4e5d12103b64748711c3aad69934d7718e75fc" + integrity sha512-T0+1Zp2wjF/juXMrMxHxidqGYn8U4R+zleSJhX9tQ1PUsS8a9UtYfbsF9LdiVgNX3kiX8RNaKM42nfSgvFJjmw== dependencies: regenerate "^1.4.2" - regenerate-unicode-properties "^9.0.0" - regjsgen "^0.5.2" - regjsparser "^0.7.0" + regenerate-unicode-properties "^10.1.0" + regjsgen "^0.7.1" + regjsparser "^0.9.1" unicode-match-property-ecmascript "^2.0.0" - unicode-match-property-value-ecmascript "^2.0.0" + unicode-match-property-value-ecmascript "^2.1.0" registry-auth-token@^4.0.0: - version "4.2.1" - resolved "https://registry.yarnpkg.com/registry-auth-token/-/registry-auth-token-4.2.1.tgz#6d7b4006441918972ccd5fedcd41dc322c79b250" - integrity sha512-6gkSb4U6aWJB4SF2ZvLb76yCBjcvufXBqvvEx1HbmKPkutswjW1xNVRY0+daljIYRbogN7O0etYSlbiaEQyMyw== + version "4.2.2" + resolved "https://registry.yarnpkg.com/registry-auth-token/-/registry-auth-token-4.2.2.tgz#f02d49c3668884612ca031419491a13539e21fac" + integrity sha512-PC5ZysNb42zpFME6D/XlIgtNGdTl8bBOCw90xQLVMpzuuubJKYDWFAEuUNc+Cn8Z8724tg2SDhDRrkVEsqfDMg== dependencies: - rc "^1.2.8" + rc "1.2.8" registry-url@^5.0.0: version "5.1.0" @@ -6762,15 +6565,15 @@ registry-url@^5.0.0: dependencies: rc "^1.2.8" -regjsgen@^0.5.2: - version "0.5.2" - resolved "https://registry.yarnpkg.com/regjsgen/-/regjsgen-0.5.2.tgz#92ff295fb1deecbf6ecdab2543d207e91aa33733" - integrity sha512-OFFT3MfrH90xIW8OOSyUrk6QHD5E9JOTeGodiJeBS3J6IwlgzJMNE/1bZklWz5oTg+9dCMyEetclvCVXOPoN3A== +regjsgen@^0.7.1: + version "0.7.1" + resolved "https://registry.yarnpkg.com/regjsgen/-/regjsgen-0.7.1.tgz#ee5ef30e18d3f09b7c369b76e7c2373ed25546f6" + integrity sha512-RAt+8H2ZEzHeYWxZ3H2z6tF18zyyOnlcdaafLrm21Bguj7uZy6ULibiAFdXEtKQY4Sy7wDTwDiOazasMLc4KPA== -regjsparser@^0.7.0: - version "0.7.0" - resolved "https://registry.yarnpkg.com/regjsparser/-/regjsparser-0.7.0.tgz#a6b667b54c885e18b52554cb4960ef71187e9968" - integrity sha512-A4pcaORqmNMDVwUjWoTzuhwMGpP+NykpfqAsEgI1FSH/EzC7lrN5TMd+kN8YCovX+jMpu8eaqXgXPCa0g8FQNQ== +regjsparser@^0.9.1: + version "0.9.1" + resolved "https://registry.yarnpkg.com/regjsparser/-/regjsparser-0.9.1.tgz#272d05aa10c7c1f67095b1ff0addae8442fc5709" + integrity sha512-dQUtn90WanSNl+7mQKcXAgZxvUe7Z0SqXlgzv0za4LwiUhyzBC58yQO3liFoUgu8GiJVInAhJjkj1N0EtQ5nkQ== dependencies: jsesc "~0.5.0" @@ -6801,16 +6604,7 @@ rehype-mathjax@^4.0.2: unified "^10.0.0" unist-util-visit "^4.0.0" -rehype-parse@^6.0.2: - version "6.0.2" - resolved "https://registry.yarnpkg.com/rehype-parse/-/rehype-parse-6.0.2.tgz#aeb3fdd68085f9f796f1d3137ae2b85a98406964" - integrity sha512-0S3CpvpTAgGmnz8kiCyFLGuW5yA4OQhyNTm/nwPopZ7+PI11WnGl1TTWTGv/2hPEe/g2jRLlhVVSsoDH8waRug== - dependencies: - hast-util-from-parse5 "^5.0.0" - parse5 "^5.0.0" - xtend "^4.0.0" - -rehype-parse@^7.0.0, rehype-parse@^7.0.1: +rehype-parse@^7.0.0: version "7.0.1" resolved "https://registry.yarnpkg.com/rehype-parse/-/rehype-parse-7.0.1.tgz#58900f6702b56767814afc2a9efa2d42b1c90c57" integrity sha512-fOiR9a9xH+Le19i4fGzIEowAbwG7idy2Jzs4mOrFWBSJ0sNUgy0ev871dwWnbOo371SjgjG4pwzrbgSVrKxecw== @@ -6821,18 +6615,9 @@ rehype-parse@^7.0.0, rehype-parse@^7.0.1: relateurl@^0.2.7: version "0.2.7" resolved "https://registry.yarnpkg.com/relateurl/-/relateurl-0.2.7.tgz#54dbf377e51440aca90a4cd274600d3ff2d888a9" - integrity sha1-VNvzd+UUQKypCkzSdGANP/LYiKk= - -remark-admonitions@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/remark-admonitions/-/remark-admonitions-1.2.1.tgz#87caa1a442aa7b4c0cafa04798ed58a342307870" - integrity sha512-Ji6p68VDvD+H1oS95Fdx9Ar5WA2wcDA4kwrrhVU7fGctC6+d3uiMICu7w7/2Xld+lnU7/gi+432+rRbup5S8ow== - dependencies: - rehype-parse "^6.0.2" - unified "^8.4.2" - unist-util-visit "^2.0.1" + integrity sha512-G08Dxvm4iDN3MLM0EsP62EDV9IuhXPR6blNz6Utcp7zyV3tr4HVNINt6MpaRWbxoOHT3Q7YN2P+jaHX8vUbgog== -remark-emoji@^2.1.0: +remark-emoji@^2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/remark-emoji/-/remark-emoji-2.2.0.tgz#1c702090a1525da5b80e15a8f963ef2c8236cac7" integrity sha512-P3cj9s5ggsUvWw5fS2uzCHJMGuXYRb0NnZqYlNecewXt8QBU9n5vW3DUUKOhepS8F9CwdMx9B8a3i7pqFWAI5w== @@ -6851,20 +6636,6 @@ remark-math@3: resolved "https://registry.yarnpkg.com/remark-math/-/remark-math-3.0.1.tgz#85a02a15b15cad34b89a27244d4887b3a95185bb" integrity sha512-epT77R/HK0x7NqrWHdSV75uNLwn8g9qTyMqCRCDujL0vj/6T6+yhdrR7mjELWtkse+Fw02kijAaBuVcHBor1+Q== -remark-mdx-remove-exports@^1.6.22: - version "1.6.22" - resolved "https://registry.yarnpkg.com/remark-mdx-remove-exports/-/remark-mdx-remove-exports-1.6.22.tgz#9e34f3d02c9c54b02ca0a1fde946449338d06ecb" - integrity sha512-7g2uiTmTGfz5QyVb+toeX25frbk1Y6yd03RXGPtqx0+DVh86Gb7MkNYbk7H2X27zdZ3CQv1W/JqlFO0Oo8IxVA== - dependencies: - unist-util-remove "2.0.0" - -remark-mdx-remove-imports@^1.6.22: - version "1.6.22" - resolved "https://registry.yarnpkg.com/remark-mdx-remove-imports/-/remark-mdx-remove-imports-1.6.22.tgz#79f711c95359cff437a120d1fbdc1326ec455826" - integrity sha512-lmjAXD8Ltw0TsvBzb45S+Dxx7LTJAtDaMneMAv8LAUIPEyYoKkmGbmVsiF0/pY6mhM1Q16swCmu1TN+ie/vn/A== - dependencies: - unist-util-remove "2.0.0" - remark-mdx@1.6.22: version "1.6.22" resolved "https://registry.yarnpkg.com/remark-mdx/-/remark-mdx-1.6.22.tgz#06a8dab07dcfdd57f3373af7f86bd0e992108bbd" @@ -6922,7 +6693,7 @@ renderkid@^3.0.0: repeat-string@^1.0.0, repeat-string@^1.5.4: version "1.6.1" resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637" - integrity sha1-jcrkcOHIirwtYA//Sndihtp15jc= + integrity sha512-PV0dzCYDNfRi1jCDbJzpW7jNNDRuCOG/jI5ctQcGKt/clZD+YcPS3yIlWuTJMmESC8aevCFmWJy5wjAFgNqN6w== require-from-string@^2.0.2: version "2.0.2" @@ -6932,12 +6703,12 @@ require-from-string@^2.0.2: "require-like@>= 0.1.1": version "0.1.2" resolved "https://registry.yarnpkg.com/require-like/-/require-like-0.1.2.tgz#ad6f30c13becd797010c468afa775c0c0a6b47fa" - integrity sha1-rW8wwTvs15cBDEaK+ndcDAprR/o= + integrity sha512-oyrU88skkMtDdauHDuKVrgR+zuItqr6/c//FXzvmxRGMexSDc6hNvJInGW3LL46n+8b50RykrvwSUIIQH2LQ5A== requires-port@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff" - integrity sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8= + integrity sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ== resolve-from@^4.0.0: version "4.0.0" @@ -6950,18 +6721,18 @@ resolve-pathname@^3.0.0: integrity sha512-C7rARubxI8bXFNB/hqcp/4iUeIXJhJZvFPFPiSPRnhU5UPxzMFIl+2E6yY6c4k9giDJAhtV+enfA+G89N6Csng== resolve@^1.1.6, resolve@^1.14.2, resolve@^1.3.2: - version "1.21.0" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.21.0.tgz#b51adc97f3472e6a5cf4444d34bc9d6b9037591f" - integrity sha512-3wCbTpk5WJlyE4mSOtDLhqQmGFi0/TD9VPwmiolnk8U0wRgMEktqCXd3vy5buTO3tljvalNvKrjHEfrd2WpEKA== + version "1.22.1" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.1.tgz#27cb2ebb53f91abb49470a928bba7558066ac177" + integrity sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw== dependencies: - is-core-module "^2.8.0" + is-core-module "^2.9.0" path-parse "^1.0.7" supports-preserve-symlinks-flag "^1.0.0" responselike@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/responselike/-/responselike-1.0.2.tgz#918720ef3b631c5642be068f15ade5a46f4ba1e7" - integrity sha1-kYcg7ztjHFZCvgaPFa3lpG9Loec= + integrity sha512-/Fpe5guzJk1gPqdJLJR5u7eG/gNY4nImjbRDaVWVMRhne55TCmj2i9Q+54PBRfatRC8v/rIiv9BN0pMd9OV5EQ== dependencies: lowercase-keys "^1.0.0" @@ -6987,7 +6758,7 @@ rtl-detect@^1.0.4: resolved "https://registry.yarnpkg.com/rtl-detect/-/rtl-detect-1.0.4.tgz#40ae0ea7302a150b96bc75af7d749607392ecac6" integrity sha512-EBR4I2VDSSYr7PkBmFy04uhycIpDKp+21p/jARYXlCSjQksTBQcJ0HFUPOO79EPPH5JS6VAhiIQbycf0O3JAxQ== -rtlcss@^3.3.0: +rtlcss@^3.5.0: version "3.5.0" resolved "https://registry.yarnpkg.com/rtlcss/-/rtlcss-3.5.0.tgz#c9eb91269827a102bac7ae3115dd5d049de636c3" integrity sha512-wzgMaMFHQTnyi9YOwsx9LjOxYXJPzS8sYnFaKm6R5ysvTkwzHiB0vxnbHwchHQT65PTdBjDG21/kQBWI7q9O7A== @@ -7004,10 +6775,10 @@ run-parallel@^1.1.9: dependencies: queue-microtask "^1.2.2" -rxjs@^7.1.0: - version "7.5.2" - resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-7.5.2.tgz#11e4a3a1dfad85dbf7fb6e33cbba17668497490b" - integrity sha512-PwDt186XaL3QN5qXj/H9DGyHhP3/RYYgZZwqBv9Tv8rsAaiwFH1IsJJlcgD37J7UW5a6O67qX0KWKS3/pu0m4w== +rxjs@^7.5.4: + version "7.5.7" + resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-7.5.7.tgz#2ec0d57fdc89ece220d2e702730ae8f1e49def39" + integrity sha512-z9MzKh/UcOqB3i20H6rtrlaE/CgjLOvheWK/9ILrbhROGTweAi1BaFsTT9FbwZi5Trr1qNRs+MXkhmR06awzQA== dependencies: tslib "^2.1.0" @@ -7016,7 +6787,7 @@ safe-buffer@5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1: resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== -safe-buffer@5.2.1, safe-buffer@>=5.1.0, safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@~5.2.0: +safe-buffer@5.2.1, safe-buffer@>=5.1.0, safe-buffer@^5.1.0, safe-buffer@~5.2.0: version "5.2.1" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== @@ -7094,14 +6865,14 @@ section-matter@^1.0.0: select-hose@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/select-hose/-/select-hose-2.0.0.tgz#625d8658f865af43ec962bfc376a37359a4994ca" - integrity sha1-Yl2GWPhlr0Psliv8N2o3NZpJlMo= + integrity sha512-mEugaLK+YfkijB4fx0e6kImuJdCIt2LxCRcbEYPqRGCs4F2ogyfZU5IAZRdjCP8JPq2AtdNoC/Dux63d9Kiryg== -selfsigned@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/selfsigned/-/selfsigned-2.0.0.tgz#e927cd5377cbb0a1075302cff8df1042cc2bce5b" - integrity sha512-cUdFiCbKoa1mZ6osuJs2uDHrs0k0oprsKveFiiaBKCNq3SYyb5gs2HxhQyDNLCmL51ZZThqi4YNDpCK6GOP1iQ== +selfsigned@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/selfsigned/-/selfsigned-2.1.1.tgz#18a7613d714c0cd3385c48af0075abf3f266af61" + integrity sha512-GSL3aowiF7wa/WtSFwnUrludWFoNhftq8bUkH9pkzjpN2XSPOAYEgg6e0sS9s0rZwgJzJiQRPU18A6clnoW5wQ== dependencies: - node-forge "^1.2.0" + node-forge "^1" semver-diff@^3.1.1: version "3.1.1" @@ -7110,11 +6881,6 @@ semver-diff@^3.1.1: dependencies: semver "^6.3.0" -semver@7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/semver/-/semver-7.0.0.tgz#5f3ca35761e47e05b206c6daff2cf814f0316b8e" - integrity sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A== - semver@^5.4.1: version "5.7.1" resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" @@ -7125,31 +6891,31 @@ semver@^6.0.0, semver@^6.1.1, semver@^6.1.2, semver@^6.2.0, semver@^6.3.0: resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== -semver@^7.3.2, semver@^7.3.4, semver@^7.3.5: - version "7.3.5" - resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.5.tgz#0b621c879348d8998e4b0e4be94b3f12e6018ef7" - integrity sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ== +semver@^7.3.2, semver@^7.3.4, semver@^7.3.7, semver@^7.3.8: + version "7.3.8" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.8.tgz#07a78feafb3f7b32347d725e33de7e2a2df67798" + integrity sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A== dependencies: lru-cache "^6.0.0" -send@0.17.2: - version "0.17.2" - resolved "https://registry.yarnpkg.com/send/-/send-0.17.2.tgz#926622f76601c41808012c8bf1688fe3906f7820" - integrity sha512-UJYB6wFSJE3G00nEivR5rgWp8c2xXvJ3OPWPhmuteU0IKj8nKbG3DrjiOmLwpnHGYWAVwA69zmTm++YG0Hmwww== +send@0.18.0: + version "0.18.0" + resolved "https://registry.yarnpkg.com/send/-/send-0.18.0.tgz#670167cc654b05f5aa4a767f9113bb371bc706be" + integrity sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg== dependencies: debug "2.6.9" - depd "~1.1.2" - destroy "~1.0.4" + depd "2.0.0" + destroy "1.2.0" encodeurl "~1.0.2" escape-html "~1.0.3" etag "~1.8.1" fresh "0.5.2" - http-errors "1.8.1" + http-errors "2.0.0" mime "1.6.0" ms "2.1.3" - on-finished "~2.3.0" + on-finished "2.4.1" range-parser "~1.2.1" - statuses "~1.5.0" + statuses "2.0.1" serialize-javascript@^6.0.0: version "6.0.0" @@ -7159,15 +6925,15 @@ serialize-javascript@^6.0.0: randombytes "^2.1.0" serve-handler@^6.1.3: - version "6.1.3" - resolved "https://registry.yarnpkg.com/serve-handler/-/serve-handler-6.1.3.tgz#1bf8c5ae138712af55c758477533b9117f6435e8" - integrity sha512-FosMqFBNrLyeiIDvP1zgO6YoTzFYHxLDEIavhlmQ+knB2Z7l1t+kGLHkZIDN7UVWqQAmKI3D20A6F6jo3nDd4w== + version "6.1.5" + resolved "https://registry.yarnpkg.com/serve-handler/-/serve-handler-6.1.5.tgz#a4a0964f5c55c7e37a02a633232b6f0d6f068375" + integrity sha512-ijPFle6Hwe8zfmBxJdE+5fta53fdIY0lHISJvuikXB3VYFafRjMRpOffSPvCYsbKyBA7pvy9oYr/BT1O3EArlg== dependencies: bytes "3.0.0" content-disposition "0.5.2" fast-url-parser "1.1.3" mime-types "2.1.18" - minimatch "3.0.4" + minimatch "3.1.2" path-is-inside "1.0.2" path-to-regexp "2.2.1" range-parser "1.2.0" @@ -7175,7 +6941,7 @@ serve-handler@^6.1.3: serve-index@^1.9.1: version "1.9.1" resolved "https://registry.yarnpkg.com/serve-index/-/serve-index-1.9.1.tgz#d3768d69b1e7d82e5ce050fff5b453bea12a9239" - integrity sha1-03aNabHn2C5c4FD/9bRTvqEqkjk= + integrity sha512-pXHfKNP4qujrtteMrSBb0rc8HJ9Ms/GrXwcUtUtD5s4ewDJI8bT3Cz2zTVRMKtri49pLx2e0Ya8ziP5Ya2pZZw== dependencies: accepts "~1.3.4" batch "0.6.1" @@ -7185,20 +6951,20 @@ serve-index@^1.9.1: mime-types "~2.1.17" parseurl "~1.3.2" -serve-static@1.14.2: - version "1.14.2" - resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.14.2.tgz#722d6294b1d62626d41b43a013ece4598d292bfa" - integrity sha512-+TMNA9AFxUEGuC0z2mevogSnn9MXKb4fa7ngeRMJaaGv8vTwnIEkKi+QGvPt33HSnf8pRS+WGM0EbMtCJLKMBQ== +serve-static@1.15.0: + version "1.15.0" + resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.15.0.tgz#faaef08cffe0a1a62f60cad0c4e513cff0ac9540" + integrity sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g== dependencies: encodeurl "~1.0.2" escape-html "~1.0.3" parseurl "~1.3.3" - send "0.17.2" + send "0.18.0" setimmediate@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285" - integrity sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU= + integrity sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA== setprototypeof@1.1.0: version "1.1.0" @@ -7217,6 +6983,11 @@ shallow-clone@^3.0.0: dependencies: kind-of "^6.0.2" +shallowequal@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/shallowequal/-/shallowequal-1.1.0.tgz#188d521de95b9087404fd4dcb68b13df0ae4e7f8" + integrity sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ== + shebang-command@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" @@ -7230,11 +7001,11 @@ shebang-regex@^3.0.0: integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== shell-quote@^1.7.3: - version "1.7.3" - resolved "https://registry.yarnpkg.com/shell-quote/-/shell-quote-1.7.3.tgz#aa40edac170445b9a431e17bb62c0b881b9c4123" - integrity sha512-Vpfqwm4EnqGdlsBFNmHhxhElJYrdfcxPThu+ryKS5J8L/fhAwLazFZtq+S+TWZ9ANj2piSQLGj6NQg+lKPmxrw== + version "1.7.4" + resolved "https://registry.yarnpkg.com/shell-quote/-/shell-quote-1.7.4.tgz#33fe15dee71ab2a81fcbd3a52106c5cfb9fb75d8" + integrity sha512-8o/QEhSSRb1a5i7TFR0iM4G16Z0vYB2OQVs4G3aAFXjn3T6yEx8AZxy1PgDF7I00LZHYA3WxaSYIf5e5sAX8Rw== -shelljs@^0.8.4: +shelljs@^0.8.5: version "0.8.5" resolved "https://registry.yarnpkg.com/shelljs/-/shelljs-0.8.5.tgz#de055408d8361bed66c669d2f000538ced8ee20c" integrity sha512-TiwcRcrkhHvbrZbnRcFYMLl30Dfov3HKqzp5tO5b4pt6G/SezKcYhmDg15zXVBswHmctSAQKznqNW2LO5tTDow== @@ -7243,16 +7014,20 @@ shelljs@^0.8.4: interpret "^1.0.0" rechoir "^0.6.2" -signal-exit@^3.0.0: +side-channel@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.4.tgz#efce5c8fdc104ee751b25c58d4290011fa5ea2cf" + integrity sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw== + dependencies: + call-bind "^1.0.0" + get-intrinsic "^1.0.2" + object-inspect "^1.9.0" + +signal-exit@^3.0.2, signal-exit@^3.0.3: version "3.0.7" resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9" integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== -signal-exit@^3.0.2, signal-exit@^3.0.3: - version "3.0.6" - resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.6.tgz#24e630c4b0f03fea446a2bd299e62b4a6ca8d0af" - integrity sha512-sDl4qMFpijcGw22U5w63KmD3cZJfBuFlVNbVMKje2keoKML7X2UzWbc4XrmEbDwg0NXJc3yv4/ox7b+JWb57kQ== - sirv@^1.0.7: version "1.0.19" resolved "https://registry.yarnpkg.com/sirv/-/sirv-1.0.19.tgz#1d73979b38c7fe91fcba49c85280daa9c2363b49" @@ -7267,10 +7042,10 @@ sisteransi@^1.0.5: resolved "https://registry.yarnpkg.com/sisteransi/-/sisteransi-1.0.5.tgz#134d681297756437cc05ca01370d3a7a571075ed" integrity sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg== -sitemap@^7.0.0: - version "7.1.0" - resolved "https://registry.yarnpkg.com/sitemap/-/sitemap-7.1.0.tgz#300cd8b3fa9d45fb63f9b56d962785c3cd799362" - integrity sha512-OctwI2RYFj3Lnoutix0Qhow3AvDoUQ7rsSyzrY8wFKHqXYvmCJXFOBZyVU4/DDtsQ2KnEWY4j4j80hBHBOVEWQ== +sitemap@^7.1.1: + version "7.1.1" + resolved "https://registry.yarnpkg.com/sitemap/-/sitemap-7.1.1.tgz#eeed9ad6d95499161a3eadc60f8c6dce4bea2bef" + integrity sha512-mK3aFtjz4VdJN0igpIJrinf3EO8U8mxOPsTBzSsy06UtjZQJ3YY3o3Xa7zSc5nMqcMrRwlChHZ18Kxg0caiPBg== dependencies: "@types/node" "^17.0.5" "@types/sax" "^1.2.1" @@ -7287,7 +7062,7 @@ slash@^4.0.0: resolved "https://registry.yarnpkg.com/slash/-/slash-4.0.0.tgz#2422372176c4c6c5addb5e2ada885af984b396a7" integrity sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew== -sockjs@^0.3.21: +sockjs@^0.3.24: version "0.3.24" resolved "https://registry.yarnpkg.com/sockjs/-/sockjs-0.3.24.tgz#c9bc8995f33a111bea0395ec30aa3206bdb5ccce" integrity sha512-GJgLTZ7vYb/JtPSSZ10hsOYIvEYsjbNU+zPdIHcUaWVNUEPivzxku31865sSSud0Da0W4lEeOPlmw93zLQchuQ== @@ -7296,20 +7071,15 @@ sockjs@^0.3.21: uuid "^8.3.2" websocket-driver "^0.7.4" -sort-css-media-queries@2.0.4: - version "2.0.4" - resolved "https://registry.yarnpkg.com/sort-css-media-queries/-/sort-css-media-queries-2.0.4.tgz#b2badfa519cb4a938acbc6d3aaa913d4949dc908" - integrity sha512-PAIsEK/XupCQwitjv7XxoMvYhT7EAfyzI3hsy/MyDgTvc+Ft55ctdkctJLOy6cQejaIC+zjpUL4djFVm2ivOOw== - -source-list-map@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/source-list-map/-/source-list-map-2.0.1.tgz#3993bd873bfc48479cca9ea3a547835c7c154b34" - integrity sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw== +sort-css-media-queries@2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/sort-css-media-queries/-/sort-css-media-queries-2.1.0.tgz#7c85e06f79826baabb232f5560e9745d7a78c4ce" + integrity sha512-IeWvo8NkNiY2vVYdPa27MCQiR0MN0M80johAYFVxWWXQ44KU84WNxjslwBHmc/7ZL2ccwkM7/e6S5aiKZXm7jA== -source-map-js@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.0.1.tgz#a1741c131e3c77d048252adfa24e23b908670caf" - integrity sha512-4+TN2b3tqOCd/kaGRJ/sTYA0tR0mdXx26ipdolxcwtJVqEnqNYvlCAt1q3ypy4QMlYus+Zh34RNtYLoq2oQ4IA== +source-map-js@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.0.2.tgz#adbc361d9c62df380125e7f161f71c826f1e490c" + integrity sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw== source-map-support@~0.5.20: version "0.5.21" @@ -7322,32 +7092,22 @@ source-map-support@~0.5.20: source-map@^0.5.0: version "0.5.7" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" - integrity sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w= + integrity sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ== source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.0, source-map@~0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== -source-map@~0.7.2: - version "0.7.3" - resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.7.3.tgz#5302f8169031735226544092e64981f751750383" - integrity sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ== - -sourcemap-codec@^1.4.4: - version "1.4.8" - resolved "https://registry.yarnpkg.com/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz#ea804bd94857402e6992d05a38ef1ae35a9ab4c4" - integrity sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA== - space-separated-tokens@^1.0.0: version "1.1.5" resolved "https://registry.yarnpkg.com/space-separated-tokens/-/space-separated-tokens-1.1.5.tgz#85f32c3d10d9682007e917414ddc5c26d1aa6899" integrity sha512-q/JSVd1Lptzhf5bkYm4ob4iWPjx0KiRe3sRFBNrVqbJkFaBm5vbbowy1mymoPNLRa52+oadOhJ+K49wsSeSjTA== space-separated-tokens@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/space-separated-tokens/-/space-separated-tokens-2.0.1.tgz#43193cec4fb858a2ce934b7f98b7f2c18107098b" - integrity sha512-ekwEbFp5aqSPKaqeY1PGrlGQxPNaq+Cnx4+bE2D8sciBQrHpbwoBbawqTN2+6jPs9IdWxxiUcN0K2pkczD3zmw== + version "2.0.2" + resolved "https://registry.yarnpkg.com/space-separated-tokens/-/space-separated-tokens-2.0.2.tgz#1ecd9d2350a3844572c3f4a312bceb018348859f" + integrity sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q== spdy-transport@^3.0.0: version "3.0.0" @@ -7372,19 +7132,19 @@ spdy@^4.0.2: select-hose "^2.0.0" spdy-transport "^3.0.0" -speech-rule-engine@^3.3.3: - version "3.3.3" - resolved "https://registry.yarnpkg.com/speech-rule-engine/-/speech-rule-engine-3.3.3.tgz#781ed03cbcf3279f94d1d80241025ea954c6d571" - integrity sha512-0exWw+0XauLjat+f/aFeo5T8SiDsO1JtwpY3qgJE4cWt+yL/Stl0WP4VNDWdh7lzGkubUD9lWP4J1ASnORXfyQ== +speech-rule-engine@^4.0.6: + version "4.0.7" + resolved "https://registry.yarnpkg.com/speech-rule-engine/-/speech-rule-engine-4.0.7.tgz#b655dacbad3dae04acc0f7665e26ef258397dd09" + integrity sha512-sJrL3/wHzNwJRLBdf6CjJWIlxC04iYKkyXvYSVsWVOiC2DSkHmxsqOhEeMsBA9XK+CHuNcsdkbFDnoUfAsmp9g== dependencies: - commander ">=7.0.0" - wicked-good-xpath "^1.3.0" - xmldom-sre "^0.1.31" + commander "9.2.0" + wicked-good-xpath "1.3.0" + xmldom-sre "0.1.31" sprintf-js@~1.0.2: version "1.0.3" resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" - integrity sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw= + integrity sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g== stable@^0.1.8: version "0.1.8" @@ -7396,17 +7156,22 @@ state-toggle@^1.0.0: resolved "https://registry.yarnpkg.com/state-toggle/-/state-toggle-1.0.3.tgz#e123b16a88e143139b09c6852221bc9815917dfe" integrity sha512-d/5Z4/2iiCnHw6Xzghyhb+GcmF89bxwgXG60wjIiZaxnymbyOmI8Hk4VqHXiVVp6u2ysaskFfXg3ekCj4WNftQ== -"statuses@>= 1.4.0 < 2", "statuses@>= 1.5.0 < 2", statuses@~1.5.0: +statuses@2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/statuses/-/statuses-2.0.1.tgz#55cb000ccf1d48728bd23c685a063998cf1a1b63" + integrity sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ== + +"statuses@>= 1.4.0 < 2": version "1.5.0" resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c" - integrity sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow= + integrity sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA== std-env@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/std-env/-/std-env-3.0.1.tgz#bc4cbc0e438610197e34c2d79c3df30b491f5182" - integrity sha512-mC1Ps9l77/97qeOZc+HrOL7TIaOboHqMZ24dGVQrlxFcpPpfCHpH+qfUT7Dz+6mlG8+JPA1KfBQo19iC/+Ngcw== + version "3.3.1" + resolved "https://registry.yarnpkg.com/std-env/-/std-env-3.3.1.tgz#93a81835815e618c8aa75e7c8a4dc04f7c314e29" + integrity sha512-3H20QlwQsSm2OvAxWIYhs+j01MzzqwMwGiiO1NQaJYZgJZFPuAbf95/DiKRBSTYIJ2FeGUc+B/6mPGcWP9dO3Q== -"string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.0.0, string-width@^4.1.0, string-width@^4.2.2, string-width@^4.2.3: +string-width@^4.0.0, string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.2: version "4.2.3" resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== @@ -7415,6 +7180,15 @@ std-env@^3.0.1: is-fullwidth-code-point "^3.0.0" strip-ansi "^6.0.1" +string-width@^5.0.1: + version "5.1.2" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-5.1.2.tgz#14f8daec6d81e7221d2a357e668cab73bdbca794" + integrity sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA== + dependencies: + eastasianwidth "^0.2.0" + emoji-regex "^9.2.2" + strip-ansi "^7.0.1" + string_decoder@^1.1.1: version "1.3.0" resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e" @@ -7445,7 +7219,7 @@ strip-ansi@^6.0.0, strip-ansi@^6.0.1: dependencies: ansi-regex "^5.0.1" -strip-ansi@^7.0.0: +strip-ansi@^7.0.1: version "7.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-7.0.1.tgz#61740a08ce36b61e50e65653f07060d000975fb2" integrity sha512-cXNxvT8dFNRVfhVME3JAe98mkXDYN2O1l7jmcwMnOslDeESg1rF/OZMtK0nRAhiari1unG5cD4jG3rapUAkLbw== @@ -7455,7 +7229,7 @@ strip-ansi@^7.0.0: strip-bom-string@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/strip-bom-string/-/strip-bom-string-1.0.0.tgz#e5211e9224369fbb81d633a2f00044dc8cedad92" - integrity sha1-5SEekiQ2n7uB1jOi8ABE3IztrZI= + integrity sha512-uCC2VHvQRYu+lMh4My/sFNmF2klFymLX1wHJeXnbEJERpV/ZsVuonzerjfrGpIGF7LBVa1O7i9kjiWvJiFck8g== strip-final-newline@^2.0.0: version "2.0.0" @@ -7470,7 +7244,7 @@ strip-json-comments@^3.1.1: strip-json-comments@~2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" - integrity sha1-PFMZQukIwml8DsNEhYwobHygpgo= + integrity sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ== style-to-object@0.3.0, style-to-object@^0.3.0: version "0.3.0" @@ -7479,12 +7253,12 @@ style-to-object@0.3.0, style-to-object@^0.3.0: dependencies: inline-style-parser "0.1.1" -stylehacks@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/stylehacks/-/stylehacks-5.0.1.tgz#323ec554198520986806388c7fdaebc38d2c06fb" - integrity sha512-Es0rVnHIqbWzveU1b24kbw92HsebBepxfcqe5iix7t9j0PQqhs0IxXVXv0pY2Bxa08CgMkzD6OWql7kbGOuEdA== +stylehacks@^5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/stylehacks/-/stylehacks-5.1.1.tgz#7934a34eb59d7152149fa69d6e9e56f2fc34bcc9" + integrity sha512-sBpcd5Hx7G6seo7b1LkpttvTz7ikD0LlH5RmdcBNb6fFR0Fl7LQwHDFr300q4cwUqi+IYrFGmsIHieMBfnN/Bw== dependencies: - browserslist "^4.16.0" + browserslist "^4.21.4" postcss-selector-parser "^6.0.4" supports-color@^5.3.0: @@ -7513,12 +7287,12 @@ supports-preserve-symlinks-flag@^1.0.0: resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09" integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== -svg-parser@^2.0.2: +svg-parser@^2.0.4: version "2.0.4" resolved "https://registry.yarnpkg.com/svg-parser/-/svg-parser-2.0.4.tgz#fdc2e29e13951736140b76cb122c8ee6630eb6b5" integrity sha512-e4hG1hRwoOdRb37cIMSgzNsxyzKfayW6VOflrwvR+/bzrkyxY/31WkbgnQpgtrNp1SdpJvpUAGTa/ZoiPNDuRQ== -svgo@^2.5.0, svgo@^2.7.0: +svgo@^2.7.0, svgo@^2.8.0: version "2.8.0" resolved "https://registry.yarnpkg.com/svgo/-/svgo-2.8.0.tgz#4ff80cce6710dc2795f0c7c74101e6764cfccd24" integrity sha512-+N/Q9kV1+F+UeWYoSiULYo4xYSDQlTgb+ayMobAXPwMnLvop7oxKMo9OzIrX5x3eS4L4f2UHhc9axXwY8DpChg== @@ -7546,47 +7320,43 @@ tapable@^2.0.0, tapable@^2.1.1, tapable@^2.2.0: resolved "https://registry.yarnpkg.com/tapable/-/tapable-2.2.1.tgz#1967a73ef4060a82f12ab96af86d52fdb76eeca0" integrity sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ== -terser-webpack-plugin@^5.1.3, terser-webpack-plugin@^5.2.4: - version "5.3.0" - resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-5.3.0.tgz#21641326486ecf91d8054161c816e464435bae9f" - integrity sha512-LPIisi3Ol4chwAaPP8toUJ3L4qCM1G0wao7L3qNv57Drezxj6+VEyySpPw4B1HSO2Eg/hDY/MNF5XihCAoqnsQ== +terser-webpack-plugin@^5.1.3, terser-webpack-plugin@^5.3.3: + version "5.3.6" + resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-5.3.6.tgz#5590aec31aa3c6f771ce1b1acca60639eab3195c" + integrity sha512-kfLFk+PoLUQIbLmB1+PZDMRSZS99Mp+/MHqDNmMA6tOItzRt+Npe3E+fsMs5mfcM0wCtrrdU387UnV+vnSffXQ== dependencies: - jest-worker "^27.4.1" + "@jridgewell/trace-mapping" "^0.3.14" + jest-worker "^27.4.5" schema-utils "^3.1.1" serialize-javascript "^6.0.0" - source-map "^0.6.1" - terser "^5.7.2" + terser "^5.14.1" -terser@^5.10.0, terser@^5.7.2: - version "5.10.0" - resolved "https://registry.yarnpkg.com/terser/-/terser-5.10.0.tgz#b86390809c0389105eb0a0b62397563096ddafcc" - integrity sha512-AMmF99DMfEDiRJfxfY5jj5wNH/bYO09cniSqhfoyxc8sFoYIgkJy86G04UoZU5VjlpnplVu0K6Tx6E9b5+DlHA== +terser@^5.10.0, terser@^5.14.1: + version "5.15.1" + resolved "https://registry.yarnpkg.com/terser/-/terser-5.15.1.tgz#8561af6e0fd6d839669c73b92bdd5777d870ed6c" + integrity sha512-K1faMUvpm/FBxjBXud0LWVAGxmvoPbZbfTCYbSgaaYQaIXI3/TdI7a7ZGA73Zrou6Q8Zmz3oeUTsp/dj+ag2Xw== dependencies: + "@jridgewell/source-map" "^0.3.2" + acorn "^8.5.0" commander "^2.20.0" - source-map "~0.7.2" source-map-support "~0.5.20" text-table@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" - integrity sha1-f17oI66AUgfACvLfSoTsP8+lcLQ= + integrity sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw== thunky@^1.0.2: version "1.1.0" resolved "https://registry.yarnpkg.com/thunky/-/thunky-1.1.0.tgz#5abaf714a9405db0504732bbccd2cedd9ef9537d" integrity sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA== -timsort@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/timsort/-/timsort-0.3.0.tgz#405411a8e7e6339fe64db9a234de11dc31e02bd4" - integrity sha1-QFQRqOfmM5/mTbmiNN4R3DHgK9Q= - tiny-invariant@^1.0.2: - version "1.2.0" - resolved "https://registry.yarnpkg.com/tiny-invariant/-/tiny-invariant-1.2.0.tgz#a1141f86b672a9148c72e978a19a73b9b94a15a9" - integrity sha512-1Uhn/aqw5C6RI4KejVeTg6mIS7IqxnLJ8Mv2tV5rTc0qWobay7pDUz6Wi392Cnc8ak1H0F2cjoRzb2/AW4+Fvg== + version "1.3.1" + resolved "https://registry.yarnpkg.com/tiny-invariant/-/tiny-invariant-1.3.1.tgz#8560808c916ef02ecfd55e66090df23a4b7aa642" + integrity sha512-AD5ih2NlSssTCwsMznbvwMZpJ1cbhkGd2uueNxzv2jDlEeZdU04JQfRnggJQ8DrcVBGjAsCKwFBbDlVNtEMlzw== -tiny-warning@^1.0.0, tiny-warning@^1.0.3: +tiny-warning@^1.0.0: version "1.0.3" resolved "https://registry.yarnpkg.com/tiny-warning/-/tiny-warning-1.0.3.tgz#94a30db453df4c643d0fd566060d60a875d84754" integrity sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA== @@ -7594,7 +7364,7 @@ tiny-warning@^1.0.0, tiny-warning@^1.0.3: to-fast-properties@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e" - integrity sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4= + integrity sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog== to-readable-stream@^1.0.0: version "1.0.0" @@ -7608,14 +7378,6 @@ to-regex-range@^5.0.1: dependencies: is-number "^7.0.0" -to-vfile@^6.1.0: - version "6.1.0" - resolved "https://registry.yarnpkg.com/to-vfile/-/to-vfile-6.1.0.tgz#5f7a3f65813c2c4e34ee1f7643a5646344627699" - integrity sha512-BxX8EkCxOAZe+D/ToHdDsJcVI4HqQfmw0tCkp31zf3dNP/XWIAjU4CmeuSwsSoOzOTqHPOL0KUzyZqJplkD0Qw== - dependencies: - is-buffer "^2.0.0" - vfile "^4.0.0" - toidentifier@1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.1.tgz#3be34321a88a820ed1bd80dfaa33e479fbb8dd35" @@ -7627,13 +7389,14 @@ totalist@^1.0.0: integrity sha512-gduQwd1rOdDMGxFG1gEvhV88Oirdo2p+KjoYFU7k2g+i7n6AFFbDQ5kMPUsW0pNbfQsB/cwXvT1i4Bue0s9g5g== tough-cookie@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-4.0.0.tgz#d822234eeca882f991f0f908824ad2622ddbece4" - integrity sha512-tHdtEpQCMrc1YLrMaqXXcj6AxhYi/xgit6mZu1+EDWUn+qhUf8wMQoFIy9NXuq23zAwtcB0t/MjACGR18pcRbg== + version "4.1.2" + resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-4.1.2.tgz#e53e84b85f24e0b65dd526f46628db6c85f6b874" + integrity sha512-G9fqXWoYFZgTc2z8Q5zaHy/vJMjm+WV0AkAeHxVCQiEB1b+dGvWzFW6QV07cY5jQ5gRkeid2qIkzkxUnmoQZUQ== dependencies: psl "^1.1.33" punycode "^2.1.1" - universalify "^0.1.2" + universalify "^0.2.0" + url-parse "^1.5.3" tr46@^3.0.0: version "3.0.0" @@ -7642,6 +7405,11 @@ tr46@^3.0.0: dependencies: punycode "^2.1.1" +tr46@~0.0.3: + version "0.0.3" + resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a" + integrity sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw== + trim-trailing-lines@^1.0.0: version "1.1.4" resolved "https://registry.yarnpkg.com/trim-trailing-lines/-/trim-trailing-lines-1.1.4.tgz#bd4abbec7cc880462f10b2c8b5ce1d8d1ec7c2c0" @@ -7650,7 +7418,7 @@ trim-trailing-lines@^1.0.0: trim@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/trim/-/trim-0.0.1.tgz#5858547f6b290757ee95cccc666fb50084c460dd" - integrity sha1-WFhUf2spB1fulczMZm+1AITEYN0= + integrity sha512-YzQV+TZg4AxpKxaTHK3c3D+kRDCGVEE7LemdlQZoQXn0iennk10RsIoY6ikzAqJTc9Xjl9C1/waHom/J86ziAQ== trough@^1.0.0: version "1.0.5" @@ -7658,19 +7426,19 @@ trough@^1.0.0: integrity sha512-rvuRbTarPXmMb79SmzEp8aqXNKcK+y0XaB298IXueQ8I2PsrATcPBCSPyK/dDNa2iWOhKlfNnOjdAOTBU/nkFA== trough@^2.0.0: - version "2.0.2" - resolved "https://registry.yarnpkg.com/trough/-/trough-2.0.2.tgz#94a3aa9d5ce379fc561f6244905b3f36b7458d96" - integrity sha512-FnHq5sTMxC0sk957wHDzRnemFnNBvt/gSY99HzK8F7UP5WAbvP70yX5bd7CjEQkN+TjdxwI7g7lJ6podqrG2/w== + version "2.1.0" + resolved "https://registry.yarnpkg.com/trough/-/trough-2.1.0.tgz#0f7b511a4fde65a46f18477ab38849b22c554876" + integrity sha512-AqTiAOLcj85xS7vQ8QkAV41hPDIJ71XJB4RCUrzo/1GM2CQwhkJGaf9Hgr7BOugMRpgGUrqRg/DrBDl4H40+8g== -tslib@^2.0.3, tslib@^2.1.0, tslib@^2.2.0, tslib@^2.3.1: - version "2.3.1" - resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.3.1.tgz#e8a335add5ceae51aa261d32a490158ef042ef01" - integrity sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw== +tslib@^2.0.3, tslib@^2.1.0, tslib@^2.4.0: + version "2.4.1" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.4.1.tgz#0d0bfbaac2880b91e22df0768e55be9753a5b17e" + integrity sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA== type-check@~0.3.2: version "0.3.2" resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.3.2.tgz#5884cab512cf1d355e3fb784f30804b2b520db72" - integrity sha1-WITKtRLPHTVeP7eE8wgEsrUg23I= + integrity sha512-ZCmOJdvOWDBYJlzAoFkC+Q0+bUyEOS1ltgp1MGU03fqHG+dbi9tBFU2Rd9QKiDZFAYrhPh2JUf7rZRIuHRKtOg== dependencies: prelude-ls "~1.1.2" @@ -7679,6 +7447,11 @@ type-fest@^0.20.2: resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.20.2.tgz#1bf207f4b28f91583666cb5fbd327887301cd5f4" integrity sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ== +type-fest@^2.5.0: + version "2.19.0" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-2.19.0.tgz#88068015bb33036a598b952e55e9311a60fd3a9b" + integrity sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA== + type-is@~1.6.18: version "1.6.18" resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.18.tgz#4e552cd05df09467dcbc4ef739de89f2cf37c131" @@ -7695,9 +7468,9 @@ typedarray-to-buffer@^3.1.5: is-typedarray "^1.0.0" ua-parser-js@^0.7.30: - version "0.7.31" - resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.31.tgz#649a656b191dffab4f21d5e053e27ca17cbff5c6" - integrity sha512-qLK/Xe9E2uzmYI3qLeOmI0tEOt+TBBQyUIAh4aAgU05FVYzeZrKUdkAZfBNVGRaHVgV0TDkdEngJSw/SyQchkQ== + version "0.7.32" + resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.32.tgz#cd8c639cdca949e30fa68c44b7813ef13e36d211" + integrity sha512-f9BESNVhzlhEFf2CHMSj40NWOjYPl1YKYbrvIr/hFTDEmLq7SRbWvm7FcdcpCYT95zrOhC7gZSxjdnnTpBcwVw== unherit@^1.0.4: version "1.1.3" @@ -7720,15 +7493,15 @@ unicode-match-property-ecmascript@^2.0.0: unicode-canonical-property-names-ecmascript "^2.0.0" unicode-property-aliases-ecmascript "^2.0.0" -unicode-match-property-value-ecmascript@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.0.0.tgz#1a01aa57247c14c568b89775a54938788189a714" - integrity sha512-7Yhkc0Ye+t4PNYzOGKedDhXbYIBe1XEQYQxOPyhcXNMJ0WCABqqj6ckydd6pWRZTHV4GuCPKdBAUiMc60tsKVw== +unicode-match-property-value-ecmascript@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.1.0.tgz#cb5fffdcd16a05124f5a4b0bf7c3770208acbbe0" + integrity sha512-qxkjQt6qjg/mYscYMC0XKRn3Rh0wFPlfxB0xkt9CfyTvpX1Ra0+rAmdX2QyAobptSEvuy4RtpPRui6XkV+8wjA== unicode-property-aliases-ecmascript@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.0.0.tgz#0a36cb9a585c4f6abd51ad1deddb285c165297c8" - integrity sha512-5Zfuy9q/DFr4tfO7ZPeVXb1aPoeQSdeFMLpYuFebehDAhbuevLs5yxSZmIFN1tP5F9Wl4IpJrYojg85/zgyZHQ== + version "2.1.0" + resolved "https://registry.yarnpkg.com/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.1.0.tgz#43d41e3be698bd493ef911077c9b131f827e8ccd" + integrity sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w== unified@9.2.0: version "9.2.0" @@ -7743,9 +7516,9 @@ unified@9.2.0: vfile "^4.0.0" unified@^10.0.0: - version "10.1.1" - resolved "https://registry.yarnpkg.com/unified/-/unified-10.1.1.tgz#345e349e3ab353ab612878338eb9d57b4dea1d46" - integrity sha512-v4ky1+6BN9X3pQrOdkFIPWAaeDsHPE1svRDxq7YpTc2plkIqFMwukfqM+l0ewpP9EfwARlt9pPFAeWYhHm8X9w== + version "10.1.2" + resolved "https://registry.yarnpkg.com/unified/-/unified-10.1.2.tgz#b1d64e55dafe1f0b98bb6c719881103ecf6c86df" + integrity sha512-pUSWAi/RAnVy1Pif2kAoeWNBa3JVrx0MId2LASj8G+7AiHWoKZNTomq6LG326T68U7/e263X6fTdcXIy7XnF7Q== dependencies: "@types/unist" "^2.0.0" bail "^2.0.0" @@ -7755,18 +7528,7 @@ unified@^10.0.0: trough "^2.0.0" vfile "^5.0.0" -unified@^8.4.2: - version "8.4.2" - resolved "https://registry.yarnpkg.com/unified/-/unified-8.4.2.tgz#13ad58b4a437faa2751a4a4c6a16f680c500fff1" - integrity sha512-JCrmN13jI4+h9UAyKEoGcDZV+i1E7BLFuG7OsaDvTXI5P0qhHX+vZO/kOhz9jn8HGENDKbwSeB0nVOg4gVStGA== - dependencies: - bail "^1.0.0" - extend "^3.0.0" - is-plain-obj "^2.0.0" - trough "^1.0.0" - vfile "^4.0.0" - -unified@^9.0.0: +unified@^9.0.0, unified@^9.2.2: version "9.2.2" resolved "https://registry.yarnpkg.com/unified/-/unified-9.2.2.tgz#67649a1abfc3ab85d2969502902775eb03146975" integrity sha512-Sg7j110mtefBD+qunSLO1lqOEKdrwBFBrR6Qd8f4uwkhWNlbkaqwHse6e7QvD3AP/MNoJdEDLaf8OxYyoWgorQ== @@ -7810,7 +7572,7 @@ unist-util-generated@^1.0.0: resolved "https://registry.yarnpkg.com/unist-util-generated/-/unist-util-generated-1.1.6.tgz#5ab51f689e2992a472beb1b35f2ce7ff2f324d4b" integrity sha512-cln2Mm1/CZzN5ttGK7vkoGw+RZ8VcUH6BtGbq98DDtRGquAAOXig1mrBQYelOwMXYS8rK+vZDyyojSjp7JX+Lg== -unist-util-is@^4.0.0, unist-util-is@^4.0.2: +unist-util-is@^4.0.0: version "4.1.0" resolved "https://registry.yarnpkg.com/unist-util-is/-/unist-util-is-4.1.0.tgz#976e5f462a7a5de73d94b706bac1b90671b57797" integrity sha512-ZOQSsnce92GrxSqlnEEseX0gi7GH9zTJZ0p9dtu87WRb/37mMPO2Ilx1s/t9vBHrFhbgweUwb+t7cIn5dxPhZg== @@ -7832,13 +7594,6 @@ unist-util-remove-position@^2.0.0: dependencies: unist-util-visit "^2.0.0" -unist-util-remove@2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/unist-util-remove/-/unist-util-remove-2.0.0.tgz#32c2ad5578802f2ca62ab808173d505b2c898488" - integrity sha512-HwwWyNHKkeg/eXRnE11IpzY8JT55JNM1YCwwU9YNCnfzk6s8GhPXrVBBZWiwLeATJbI7euvoGSzcy9M29UeW3g== - dependencies: - unist-util-is "^4.0.0" - unist-util-remove@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/unist-util-remove/-/unist-util-remove-2.1.0.tgz#b0b4738aa7ee445c402fda9328d604a02d010588" @@ -7854,9 +7609,9 @@ unist-util-stringify-position@^2.0.0: "@types/unist" "^2.0.2" unist-util-stringify-position@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/unist-util-stringify-position/-/unist-util-stringify-position-3.0.0.tgz#d517d2883d74d0daa0b565adc3d10a02b4a8cde9" - integrity sha512-SdfAl8fsDclywZpfMDTVDxA2V7LjtRDTOFd44wUJamgl6OlVngsqWjxvermMYf60elWHbxhuRCZml7AnuXCaSA== + version "3.0.2" + resolved "https://registry.yarnpkg.com/unist-util-stringify-position/-/unist-util-stringify-position-3.0.2.tgz#5c6aa07c90b1deffd9153be170dce628a869a447" + integrity sha512-7A6eiDCs9UtjcwZOcCpM4aPII3bAAGv13E96IkawkOAW0OhH+yRxtY0lzo8KiHpzEMfH7Q+FizUmwp8Iqy5EWg== dependencies: "@types/unist" "^2.0.0" @@ -7868,15 +7623,15 @@ unist-util-visit-parents@^3.0.0: "@types/unist" "^2.0.0" unist-util-is "^4.0.0" -unist-util-visit-parents@^5.0.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/unist-util-visit-parents/-/unist-util-visit-parents-5.1.0.tgz#44bbc5d25f2411e7dfc5cecff12de43296aa8521" - integrity sha512-y+QVLcY5eR/YVpqDsLf/xh9R3Q2Y4HxkZTp7ViLDU6WtJCEcPmRzW1gpdWDCDIqIlhuPDXOgttqPlykrHYDekg== +unist-util-visit-parents@^5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/unist-util-visit-parents/-/unist-util-visit-parents-5.1.1.tgz#868f353e6fce6bf8fa875b251b0f4fec3be709bb" + integrity sha512-gks4baapT/kNRaWxuGkl5BIhoanZo7sC/cUT/JToSRNL1dYoXRFl75d++NkjYk4TAu2uv2Px+l8guMajogeuiw== dependencies: "@types/unist" "^2.0.0" unist-util-is "^5.0.0" -unist-util-visit@2.0.3, unist-util-visit@^2.0.0, unist-util-visit@^2.0.1, unist-util-visit@^2.0.2, unist-util-visit@^2.0.3: +unist-util-visit@2.0.3, unist-util-visit@^2.0.0, unist-util-visit@^2.0.3: version "2.0.3" resolved "https://registry.yarnpkg.com/unist-util-visit/-/unist-util-visit-2.0.3.tgz#c3703893146df47203bb8a9795af47d7b971208c" integrity sha512-iJ4/RczbJMkD0712mGktuGpm/U4By4FfDonL7N/9tATGIF4imikjOuagyMY53tnZq3NP6BcmlrHhEKAfGWjh7Q== @@ -7886,18 +7641,18 @@ unist-util-visit@2.0.3, unist-util-visit@^2.0.0, unist-util-visit@^2.0.1, unist- unist-util-visit-parents "^3.0.0" unist-util-visit@^4.0.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/unist-util-visit/-/unist-util-visit-4.1.0.tgz#f41e407a9e94da31594e6b1c9811c51ab0b3d8f5" - integrity sha512-n7lyhFKJfVZ9MnKtqbsqkQEk5P1KShj0+//V7mAcoI6bpbUjh3C/OG8HVD+pBihfh6Ovl01m8dkcv9HNqYajmQ== + version "4.1.1" + resolved "https://registry.yarnpkg.com/unist-util-visit/-/unist-util-visit-4.1.1.tgz#1c4842d70bd3df6cc545276f5164f933390a9aad" + integrity sha512-n9KN3WV9k4h1DxYR1LoajgN93wpEi/7ZplVe02IoB4gH5ctI1AaF2670BLHQYbwj+pY83gFtyeySFiyMHJklrg== dependencies: "@types/unist" "^2.0.0" unist-util-is "^5.0.0" - unist-util-visit-parents "^5.0.0" + unist-util-visit-parents "^5.1.1" -universalify@^0.1.2: - version "0.1.2" - resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66" - integrity sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg== +universalify@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.2.0.tgz#6451760566fa857534745ab1dde952d1b1761be0" + integrity sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg== universalify@^2.0.0: version "2.0.0" @@ -7907,7 +7662,15 @@ universalify@^2.0.0: unpipe@1.0.0, unpipe@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" - integrity sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw= + integrity sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ== + +update-browserslist-db@^1.0.9: + version "1.0.10" + resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.0.10.tgz#0f54b876545726f17d00cd9a2561e6dade943ff3" + integrity sha512-OztqDenkfFkbSG+tRxBeAnCVPckDBcvibKd35yDONx6OU8N7sqgwc7rCbkJ/WcYtVRZ4ba68d6byhC21GFh7sQ== + dependencies: + escalade "^3.1.1" + picocolors "^1.0.0" update-notifier@^5.1.0: version "5.1.0" @@ -7948,44 +7711,44 @@ url-loader@^4.1.1: url-parse-lax@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/url-parse-lax/-/url-parse-lax-3.0.0.tgz#16b5cafc07dbe3676c1b1999177823d6503acb0c" - integrity sha1-FrXK/Afb42dsGxmZF3gj1lA6yww= + integrity sha512-NjFKA0DidqPa5ciFcSrXnAltTtzz84ogy+NebPvfEgAck0+TNg4UJ4IN+fB7zRZfbgUf0syOo9MDxFkDSMuFaQ== dependencies: prepend-http "^2.0.0" -url@^0.11.0: - version "0.11.0" - resolved "https://registry.yarnpkg.com/url/-/url-0.11.0.tgz#3838e97cfc60521eb73c525a8e55bfdd9e2e28f1" - integrity sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE= +url-parse@^1.5.3: + version "1.5.10" + resolved "https://registry.yarnpkg.com/url-parse/-/url-parse-1.5.10.tgz#9d3c2f736c1d75dd3bd2be507dcc111f1e2ea9c1" + integrity sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ== dependencies: - punycode "1.3.2" - querystring "0.2.0" + querystringify "^2.1.1" + requires-port "^1.0.0" -use-composed-ref@^1.0.0: - version "1.2.1" - resolved "https://registry.yarnpkg.com/use-composed-ref/-/use-composed-ref-1.2.1.tgz#9bdcb5ccd894289105da2325e1210079f56bf849" - integrity sha512-6+X1FLlIcjvFMAeAD/hcxDT8tmyrWnbSPMU0EnxQuDLIxokuFzWliXBiYZuGIx+mrAMLBw0WFfCkaPw8ebzAhw== +use-composed-ref@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/use-composed-ref/-/use-composed-ref-1.3.0.tgz#3d8104db34b7b264030a9d916c5e94fbe280dbda" + integrity sha512-GLMG0Jc/jiKov/3Ulid1wbv3r54K9HlMW29IWcDFPEqFkSO2nS0MuefWgMJpeHQ9YJeXDL3ZUF+P3jdXlZX/cQ== -use-isomorphic-layout-effect@^1.0.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/use-isomorphic-layout-effect/-/use-isomorphic-layout-effect-1.1.1.tgz#7bb6589170cd2987a152042f9084f9effb75c225" - integrity sha512-L7Evj8FGcwo/wpbv/qvSfrkHFtOpCzvM5yl2KVyDJoylVuSvzphiiasmjgQPttIGBAy2WKiBNR98q8w7PiNgKQ== +use-isomorphic-layout-effect@^1.1.1: + version "1.1.2" + resolved "https://registry.yarnpkg.com/use-isomorphic-layout-effect/-/use-isomorphic-layout-effect-1.1.2.tgz#497cefb13d863d687b08477d9e5a164ad8c1a6fb" + integrity sha512-49L8yCO3iGT/ZF9QttjwLF/ZD9Iwto5LnH5LmEdk/6cFmXddqi2ulF0edxTwjj+7mqvpVVGQWvbXZdn32wRSHA== -use-latest@^1.0.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/use-latest/-/use-latest-1.2.0.tgz#a44f6572b8288e0972ec411bdd0840ada366f232" - integrity sha512-d2TEuG6nSLKQLAfW3By8mKr8HurOlTkul0sOpxbClIv4SQ4iOd7BYr7VIzdbktUCnv7dua/60xzd8igMU6jmyw== +use-latest@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/use-latest/-/use-latest-1.2.1.tgz#d13dfb4b08c28e3e33991546a2cee53e14038cf2" + integrity sha512-xA+AVm/Wlg3e2P/JiItTziwS7FK92LWrDB0p+hgXloIMuVCeJJ8v6f0eeHyPZaJrM+usM1FkFfbNCrJGs8A/zw== dependencies: - use-isomorphic-layout-effect "^1.0.0" + use-isomorphic-layout-effect "^1.1.1" util-deprecate@^1.0.1, util-deprecate@^1.0.2, util-deprecate@~1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" - integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8= + integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw== utila@~0.4: version "0.4.0" resolved "https://registry.yarnpkg.com/utila/-/utila-0.4.0.tgz#8a16a05d445657a3aea5eecc5b12a4fa5379772c" - integrity sha1-ihagXURWV6Oupe7MWxKk+lN5dyw= + integrity sha512-Z0DbgELS9/L/75wZbro8xAnT50pBVFQZ+hUEueGDU5FN51YSCYM+jdxsfCiHjwNP/4LCDD0i/graKpeBnOXKRA== utility-types@^3.10.0: version "3.10.0" @@ -7995,7 +7758,7 @@ utility-types@^3.10.0: utils-merge@1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713" - integrity sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM= + integrity sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA== uuid@^8.3.2: version "8.3.2" @@ -8010,7 +7773,7 @@ value-equal@^1.0.1: vary@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" - integrity sha1-IpnwLG3tMNSllhsLn3RSShj2NPw= + integrity sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg== vfile-location@^3.0.0, vfile-location@^3.2.0: version "3.2.0" @@ -8026,9 +7789,9 @@ vfile-message@^2.0.0: unist-util-stringify-position "^2.0.0" vfile-message@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/vfile-message/-/vfile-message-3.1.0.tgz#5437035aa43185ff4b9210d32fada6c640e59143" - integrity sha512-4QJbBk+DkPEhBXq3f260xSaWtjE4gPKOfulzfMFF8ZNwaPZieWsg3iVlcmF04+eebzpcpeXOOFMfrYzJHVYg+g== + version "3.1.3" + resolved "https://registry.yarnpkg.com/vfile-message/-/vfile-message-3.1.3.tgz#1360c27a99234bebf7bddbbbca67807115e6b0dd" + integrity sha512-0yaU+rj2gKAyEk12ffdSbBfjnnj+b1zqTBv3OQCTn8yEB02bsPizwdBPrLJjHnK+cU9EMMcUnNv938XcZIkmdA== dependencies: "@types/unist" "^2.0.0" unist-util-stringify-position "^3.0.0" @@ -8044,9 +7807,9 @@ vfile@^4.0.0: vfile-message "^2.0.0" vfile@^5.0.0: - version "5.3.0" - resolved "https://registry.yarnpkg.com/vfile/-/vfile-5.3.0.tgz#4990c78cb3157005590ee8c930b71cd7fa6a006e" - integrity sha512-Tj44nY/48OQvarrE4FAjUfrv7GZOYzPbl5OD65HxVKwLJKMPU7zmfV8cCgCnzKWnSfYG2f3pxu+ALqs7j22xQQ== + version "5.3.6" + resolved "https://registry.yarnpkg.com/vfile/-/vfile-5.3.6.tgz#61b2e70690cc835a5d0d0fd135beae74e5a39546" + integrity sha512-ADBsmerdGBs2WYckrLBEmuETSPyTD4TuLxTrw0DvjirxW1ra4ZwkbzG8ndsv3Q57smvHxo677MHaQrY9yxH8cA== dependencies: "@types/unist" "^2.0.0" is-buffer "^2.0.0" @@ -8067,21 +7830,21 @@ w3c-xmlserializer@^3.0.0: dependencies: xml-name-validator "^4.0.0" -wait-on@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/wait-on/-/wait-on-6.0.0.tgz#7e9bf8e3d7fe2daecbb7a570ac8ca41e9311c7e7" - integrity sha512-tnUJr9p5r+bEYXPUdRseolmz5XqJTTj98JgOsfBn7Oz2dxfE2g3zw1jE+Mo8lopM3j3et/Mq1yW7kKX6qw7RVw== +wait-on@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/wait-on/-/wait-on-6.0.1.tgz#16bbc4d1e4ebdd41c5b4e63a2e16dbd1f4e5601e" + integrity sha512-zht+KASY3usTY5u2LgaNqn/Cd8MukxLGjdcZxT2ns5QzDmTFc4XoWBgC+C/na+sMRZTuVygQoMYwdcVjHnYIVw== dependencies: - axios "^0.21.1" - joi "^17.4.0" + axios "^0.25.0" + joi "^17.6.0" lodash "^4.17.21" minimist "^1.2.5" - rxjs "^7.1.0" + rxjs "^7.5.4" -watchpack@^2.3.1: - version "2.3.1" - resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-2.3.1.tgz#4200d9447b401156eeca7767ee610f8809bc9d25" - integrity sha512-x0t0JuydIo8qCNctdDrn1OzH/qDzk2+rdCOC3YzumZ42fiMqmQ7T3xQurykYMhYfHaPHTp4ZxAx2NfUo1K6QaA== +watchpack@^2.4.0: + version "2.4.0" + resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-2.4.0.tgz#fa33032374962c78113f93c7f2fb4c54c9862a5d" + integrity sha512-Lcvm7MGST/4fup+ifyKi2hjyIAwcdI4HRgtvTpIUxBRhB+RFtUh8XtDOxUfctVCnhVi+QQj49i91OyvzkJl6cg== dependencies: glob-to-regexp "^0.4.1" graceful-fs "^4.1.2" @@ -8093,7 +7856,7 @@ wbuf@^1.1.0, wbuf@^1.7.3: dependencies: minimalistic-assert "^1.0.0" -web-namespaces@^1.0.0, web-namespaces@^1.1.2: +web-namespaces@^1.0.0: version "1.1.4" resolved "https://registry.yarnpkg.com/web-namespaces/-/web-namespaces-1.1.4.tgz#bc98a3de60dadd7faefc403d1076d529f5e030ec" integrity sha512-wYxSGajtmoP4WxfejAPIr4l0fVh+jeMXZb08wNc0tMg6xsfZXj3cECqIK0G7ZAqUq0PP8WlMDtaOGVBTAWztNw== @@ -8103,15 +7866,20 @@ web-namespaces@^2.0.0: resolved "https://registry.yarnpkg.com/web-namespaces/-/web-namespaces-2.0.1.tgz#1010ff7c650eccb2592cebeeaf9a1b253fd40692" integrity sha512-bKr1DkiNa2krS7qxNtdrtHAmzuYGFQLiQ13TsorsdT6ULTkPLKuu5+GsFpDlg6JFjUTwX2DyhMPG2be8uPrqsQ== +webidl-conversions@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871" + integrity sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ== + webidl-conversions@^7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-7.0.0.tgz#256b4e1882be7debbf01d05f0aa2039778ea080a" integrity sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g== -webpack-bundle-analyzer@^4.4.2: - version "4.5.0" - resolved "https://registry.yarnpkg.com/webpack-bundle-analyzer/-/webpack-bundle-analyzer-4.5.0.tgz#1b0eea2947e73528754a6f9af3e91b2b6e0f79d5" - integrity sha512-GUMZlM3SKwS8Z+CKeIFx7CVoHn3dXFcUAjT/dcZQQmfSZGvitPfMob2ipjai7ovFFqPvTqkEZ/leL4O0YOdAYQ== +webpack-bundle-analyzer@^4.5.0: + version "4.7.0" + resolved "https://registry.yarnpkg.com/webpack-bundle-analyzer/-/webpack-bundle-analyzer-4.7.0.tgz#33c1c485a7fcae8627c547b5c3328b46de733c66" + integrity sha512-j9b8ynpJS4K+zfO5GGwsAcQX4ZHpWV+yRiHDiL+bE0XHJ8NiPYLTNVQdlFYWxtpg9lfAQNlwJg16J9AJtFSXRg== dependencies: acorn "^8.0.4" acorn-walk "^8.0.0" @@ -8123,51 +7891,51 @@ webpack-bundle-analyzer@^4.4.2: sirv "^1.0.7" ws "^7.3.1" -webpack-dev-middleware@^5.3.0: - version "5.3.0" - resolved "https://registry.yarnpkg.com/webpack-dev-middleware/-/webpack-dev-middleware-5.3.0.tgz#8fc02dba6e72e1d373eca361623d84610f27be7c" - integrity sha512-MouJz+rXAm9B1OTOYaJnn6rtD/lWZPy2ufQCH3BPs8Rloh/Du6Jze4p7AeLYHkVi0giJnYLaSGDC7S+GM9arhg== +webpack-dev-middleware@^5.3.1: + version "5.3.3" + resolved "https://registry.yarnpkg.com/webpack-dev-middleware/-/webpack-dev-middleware-5.3.3.tgz#efae67c2793908e7311f1d9b06f2a08dcc97e51f" + integrity sha512-hj5CYrY0bZLB+eTO+x/j67Pkrquiy7kWepMHmUMoPsmcUaeEnQJqFzHJOyxgWlq746/wUuA64p9ta34Kyb01pA== dependencies: colorette "^2.0.10" - memfs "^3.2.2" + memfs "^3.4.3" mime-types "^2.1.31" range-parser "^1.2.1" schema-utils "^4.0.0" -webpack-dev-server@^4.7.1: - version "4.7.3" - resolved "https://registry.yarnpkg.com/webpack-dev-server/-/webpack-dev-server-4.7.3.tgz#4e995b141ff51fa499906eebc7906f6925d0beaa" - integrity sha512-mlxq2AsIw2ag016nixkzUkdyOE8ST2GTy34uKSABp1c4nhjZvH90D5ZRR+UOLSsG4Z3TFahAi72a3ymRtfRm+Q== +webpack-dev-server@^4.9.3: + version "4.11.1" + resolved "https://registry.yarnpkg.com/webpack-dev-server/-/webpack-dev-server-4.11.1.tgz#ae07f0d71ca0438cf88446f09029b92ce81380b5" + integrity sha512-lILVz9tAUy1zGFwieuaQtYiadImb5M3d+H+L1zDYalYoDl0cksAB1UNyuE5MMWJrG6zR1tXkCP2fitl7yoUJiw== dependencies: "@types/bonjour" "^3.5.9" "@types/connect-history-api-fallback" "^1.3.5" + "@types/express" "^4.17.13" "@types/serve-index" "^1.9.1" + "@types/serve-static" "^1.13.10" "@types/sockjs" "^0.3.33" - "@types/ws" "^8.2.2" + "@types/ws" "^8.5.1" ansi-html-community "^0.0.8" - bonjour "^3.5.0" - chokidar "^3.5.2" + bonjour-service "^1.0.11" + chokidar "^3.5.3" colorette "^2.0.10" compression "^1.7.4" - connect-history-api-fallback "^1.6.0" + connect-history-api-fallback "^2.0.0" default-gateway "^6.0.3" - del "^6.0.0" - express "^4.17.1" + express "^4.17.3" graceful-fs "^4.2.6" html-entities "^2.3.2" - http-proxy-middleware "^2.0.0" + http-proxy-middleware "^2.0.3" ipaddr.js "^2.0.1" open "^8.0.9" p-retry "^4.5.0" - portfinder "^1.0.28" + rimraf "^3.0.2" schema-utils "^4.0.0" - selfsigned "^2.0.0" + selfsigned "^2.1.1" serve-index "^1.9.1" - sockjs "^0.3.21" + sockjs "^0.3.24" spdy "^4.0.2" - strip-ansi "^7.0.0" - webpack-dev-middleware "^5.3.0" - ws "^8.1.0" + webpack-dev-middleware "^5.3.1" + ws "^8.4.2" webpack-merge@^5.8.0: version "5.8.0" @@ -8177,48 +7945,40 @@ webpack-merge@^5.8.0: clone-deep "^4.0.1" wildcard "^2.0.0" -webpack-sources@^1.1.0, webpack-sources@^1.4.3: - version "1.4.3" - resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-1.4.3.tgz#eedd8ec0b928fbf1cbfe994e22d2d890f330a933" - integrity sha512-lgTS3Xhv1lCOKo7SA5TjKXMjpSM4sBjNV5+q2bqesbSPs5FjGmU6jjtBSkX9b4qW87vDIsCIlUPOEhbZrMdjeQ== - dependencies: - source-list-map "^2.0.0" - source-map "~0.6.1" - -webpack-sources@^3.2.2: +webpack-sources@^3.2.2, webpack-sources@^3.2.3: version "3.2.3" resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-3.2.3.tgz#2d4daab8451fd4b240cc27055ff6a0c2ccea0cde" integrity sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w== -webpack@^5.61.0: - version "5.66.0" - resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.66.0.tgz#789bf36287f407fc92b3e2d6f978ddff1bfc2dbb" - integrity sha512-NJNtGT7IKpGzdW7Iwpn/09OXz9inIkeIQ/ibY6B+MdV1x6+uReqz/5z1L89ezWnpPDWpXF0TY5PCYKQdWVn8Vg== +webpack@^5.73.0: + version "5.75.0" + resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.75.0.tgz#1e440468647b2505860e94c9ff3e44d5b582c152" + integrity sha512-piaIaoVJlqMsPtX/+3KTTO6jfvrSYgauFVdt8cr9LTHKmcq/AMd4mhzsiP7ZF/PGRNPGA8336jldh9l2Kt2ogQ== dependencies: - "@types/eslint-scope" "^3.7.0" - "@types/estree" "^0.0.50" + "@types/eslint-scope" "^3.7.3" + "@types/estree" "^0.0.51" "@webassemblyjs/ast" "1.11.1" "@webassemblyjs/wasm-edit" "1.11.1" "@webassemblyjs/wasm-parser" "1.11.1" - acorn "^8.4.1" + acorn "^8.7.1" acorn-import-assertions "^1.7.6" browserslist "^4.14.5" chrome-trace-event "^1.0.2" - enhanced-resolve "^5.8.3" + enhanced-resolve "^5.10.0" es-module-lexer "^0.9.0" eslint-scope "5.1.1" events "^3.2.0" glob-to-regexp "^0.4.1" graceful-fs "^4.2.9" - json-parse-better-errors "^1.0.2" + json-parse-even-better-errors "^2.3.1" loader-runner "^4.2.0" mime-types "^2.1.27" neo-async "^2.6.2" schema-utils "^3.1.0" tapable "^2.1.1" terser-webpack-plugin "^5.1.3" - watchpack "^2.3.1" - webpack-sources "^3.2.2" + watchpack "^2.4.0" + webpack-sources "^3.2.3" webpackbar@^5.0.2: version "5.0.2" @@ -8264,6 +8024,22 @@ whatwg-url@^10.0.0: tr46 "^3.0.0" webidl-conversions "^7.0.0" +whatwg-url@^11.0.0: + version "11.0.0" + resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-11.0.0.tgz#0a849eebb5faf2119b901bb76fd795c2848d4018" + integrity sha512-RKT8HExMpoYx4igMiVMY83lN6UeITKJlBQ+vR/8ZJ8OCdSiN3RwCq+9gH0+Xzj0+5IrM6i4j/6LuvzbZIQgEcQ== + dependencies: + tr46 "^3.0.0" + webidl-conversions "^7.0.0" + +whatwg-url@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-5.0.0.tgz#966454e8765462e37644d3626f6742ce8b70965d" + integrity sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw== + dependencies: + tr46 "~0.0.3" + webidl-conversions "^3.0.0" + which@^1.3.1: version "1.3.1" resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" @@ -8278,17 +8054,10 @@ which@^2.0.1: dependencies: isexe "^2.0.0" -wicked-good-xpath@^1.3.0: +wicked-good-xpath@1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/wicked-good-xpath/-/wicked-good-xpath-1.3.0.tgz#81b0e95e8650e49c94b22298fff8686b5553cf6c" - integrity sha1-gbDpXoZQ5JyUsiKY//hoa1VTz2w= - -wide-align@^1.1.2: - version "1.1.5" - resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.5.tgz#df1d4c206854369ecf3c9a4898f1b23fbd9d15d3" - integrity sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg== - dependencies: - string-width "^1.0.2 || 2 || 3 || 4" + integrity sha512-Gd9+TUn5nXdwj/hFsPVx5cuHHiF5Bwuc30jZ4+ronF1qHK5O7HD0sgmXWSEgwKquT3ClLoKPVbO6qGwVwLzvAw== widest-line@^3.1.0: version "3.1.0" @@ -8297,6 +8066,13 @@ widest-line@^3.1.0: dependencies: string-width "^4.0.0" +widest-line@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/widest-line/-/widest-line-4.0.1.tgz#a0fc673aaba1ea6f0a0d35b3c2795c9a9cc2ebf2" + integrity sha512-o0cyEG0e8GPzT4iGHphIOh0cJOV8fivsXxddQasHPHfoZf1ZexrfeA21w2NaEN1RHE+fXlfISmOE8R9N3u3Qig== + dependencies: + string-width "^5.0.1" + wildcard@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/wildcard/-/wildcard-2.0.0.tgz#a77d20e5200c6faaac979e4b3aadc7b3dd7f8fec" @@ -8316,10 +8092,19 @@ wrap-ansi@^7.0.0: string-width "^4.1.0" strip-ansi "^6.0.0" +wrap-ansi@^8.0.1: + version "8.0.1" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-8.0.1.tgz#2101e861777fec527d0ea90c57c6b03aac56a5b3" + integrity sha512-QFF+ufAqhoYHvoHdajT/Po7KoXVBPXS2bgjIam5isfWJPfIOnQZ50JtUiVvCv/sjgacf3yRrt2ZKUZ/V4itN4g== + dependencies: + ansi-styles "^6.1.0" + string-width "^5.0.1" + strip-ansi "^7.0.1" + wrappy@1: version "1.0.2" resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" - integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= + integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== write-file-atomic@^3.0.0: version "3.0.3" @@ -8332,19 +8117,14 @@ write-file-atomic@^3.0.0: typedarray-to-buffer "^3.1.5" ws@^7.3.1: - version "7.5.6" - resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.6.tgz#e59fc509fb15ddfb65487ee9765c5a51dec5fe7b" - integrity sha512-6GLgCqo2cy2A2rjCNFlxQS6ZljG/coZfZXclldI8FB/1G3CCI36Zd8xy2HrFVACi8tfk5XrgLQEk+P0Tnz9UcA== - -ws@^8.1.0: - version "8.4.0" - resolved "https://registry.yarnpkg.com/ws/-/ws-8.4.0.tgz#f05e982a0a88c604080e8581576e2a063802bed6" - integrity sha512-IHVsKe2pjajSUIl4KYMQOdlyliovpEPquKkqbwswulszzI7r0SfQrxnXdWAEqOlDCLrVSJzo+O1hAwdog2sKSQ== + version "7.5.9" + resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.9.tgz#54fa7db29f4c7cec68b1ddd3a89de099942bb591" + integrity sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q== -ws@^8.2.3: - version "8.4.1" - resolved "https://registry.yarnpkg.com/ws/-/ws-8.4.1.tgz#ce1a17e553d2b794e017fa94887808db5c67f614" - integrity sha512-6eqQ4yN2y2xv8b+BgbkUzPPyfo/PDl3VOWb06ZE0jIFYwuHMsMQN6F7o84yxJYCblfCRAxzpU59We4Rr4w0Luw== +ws@^8.2.3, ws@^8.4.2: + version "8.11.0" + resolved "https://registry.yarnpkg.com/ws/-/ws-8.11.0.tgz#6a0d36b8edfd9f96d8b25683db2f8d7de6e8e143" + integrity sha512-HPG3wQd9sNQoT9xHyNCXoDUa+Xw/VevmY9FoHyQ+g+rrMn4j6FB4np7Z0OhdTgjx6MgQLK7jwSy1YecU1+4Asg== xdg-basedir@^4.0.0: version "4.0.0" @@ -8368,7 +8148,7 @@ xmlchars@^2.2.0: resolved "https://registry.yarnpkg.com/xmlchars/-/xmlchars-2.2.0.tgz#060fe1bcb7f9c76fe2a17db86a9bc3ab894210cb" integrity sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw== -xmldom-sre@^0.1.31: +xmldom-sre@0.1.31: version "0.1.31" resolved "https://registry.yarnpkg.com/xmldom-sre/-/xmldom-sre-0.1.31.tgz#10860d5bab2c603144597d04bf2c4980e98067f4" integrity sha512-f9s+fUkX04BxQf+7mMWAp5zk61pciie+fFLC9hX9UVvCeJQfNHRHXpeo5MPcR0EUf57PYLdt+ZO4f3Ipk2oZUw== From 111c56fcb1e27ebfef2db91260581974a744a68e Mon Sep 17 00:00:00 2001 From: Michael Birch Date: Mon, 21 Nov 2022 08:53:54 -0500 Subject: [PATCH 086/150] Chunk and block producer selection (#167) # Summary Write up of the new chunk and block producer selection algorithms for Simple Nightshade. Based on the [discussion on the forum](https://gov.near.org/t/block-and-chunk-producer-selection-algorithm-in-simple-nightshade/66). Fixes #156 # Motivation Simple Nightshade is a stepping stone toward the full sharding solution. In Simple Nightshade block producers track all shards (because challenges are not ready yet), and there is a new role "chunk-only producers" which track just one shard and only produce chunks. The purpose of this new role is to maintain decentralization since block producers will need to run more expensive hardware to track all shards, and this is not accessible to everyone. Therefore, we need to specify how chunk and block producers get selected taking into account the separation between chunk and block producers. # Guide-level explanation There are two separate proposal sets: one for block producers and one for chunk-only producers. This ensures that nodes which are not running the proper hardware to track all shards will never accidentally become a block producer. The top `N` (in terms of stake) proposals from the block producers proposals become the block producers in the next epoch. The top `N + M` proposals from the combined chunk-only and block producer set become chunk producers (note: this means block producers are also chunk producers, hence the need for the chunk-only nomenclature when referencing validators which are not block producers). The chunk producers are divided (approximately) evenly between all shards. At each height, a specific block producer is chosen at random (weighted by their stakes) to produce the block for that height. Additionally, a random chunk producer (weighted by stake) is chosen in each shard to produce the chunk for that shard at that height. We also enforce the condition that the block producer at `h + 1` will produce the chunk for some shard at `h` (to reduce network overhead). Rewards given to validators are also separated into two pools: one for block producers and one for chunk-only producers. A fraction `f` of the total rewards is given to the block producers, and the remainder is given to the chunk-only producers. Within each pool the rewards are split in proportion to stake. `f` should be greater than 1/2 since block producers have more expensive hardware. # Reference-level explanation All algorithms are given in full detail in the changes to the spec done in this PR. --- specs/ChainSpec/SelectingBlockProducers.md | 335 +++++++++++++++++++++ specs/Economics/README.md | 53 +--- 2 files changed, 345 insertions(+), 43 deletions(-) create mode 100644 specs/ChainSpec/SelectingBlockProducers.md diff --git a/specs/ChainSpec/SelectingBlockProducers.md b/specs/ChainSpec/SelectingBlockProducers.md new file mode 100644 index 000000000..78bf6eaea --- /dev/null +++ b/specs/ChainSpec/SelectingBlockProducers.md @@ -0,0 +1,335 @@ +# Selecting Chunk and Block Producers + +## Background + +Near is intended to be a sharded blockchain. At the time of writing (March 2021), challenges (an +important security feature for a sharded network) are not fully implemented. As a stepping stone +towards the full sharded solution, Near will go through a phase called "Simple Nightshade". In this +protocol, block producers will track all shards (i.e. validate all transactions, eliminating the need +for challenges), and there will be an additional type of participant called a "chunk-only producer" +which tracks only a single shard. A block includes one chunk for each shard, and it is the chunks +which include the transactions that were executed for its associated shard. The purpose of this +design is to allow decentralization (running a node which supports a chunk-only producer should be +possible for a large number of participants) while maintaining security (since block producers track +all shards). For more details on chunks see the subsequent chapter on Transactions. Note: the +purpose of the "chunk-only" nomenclature is to reduce confusion since block producers will also +produce chunks some times (they track all shards, so they will be able to produce chunks for any +shard easily); thus the key distinction is that chunk-only producers only produce chunks, i.e. never +produce blocks. + +Near is a permissionless blockchain, so anyone (with sufficient stake) can become a chunk-only +producer, or a block producer. In this section we outline the algorithm by which chunk-only +producers and block producers are selected in each epoch from the proposals of participants in the +network. Additionally, we will specify the algorithm for assigning those chunk-only producers and +block producers to be the one responsible for producing the chunk/block at each height and for each +shard. + +There are several desiderata for these algorithms: +* Larger stakes should be preferred (more staked tokens means more security) +* The frequency with which a given participant is selected to produce a particular chunk/block is + proportional to that participant's stake +* All participants selected as chunk/block producers should be selected to produce at least one + chunk/block during the epoch +* It should be possible to determine which chunk/block producer is supposed to produce the + chunk/block at height $h$, for any $h$ within the epoch, in constant time +* The block producer chosen at height $h$ should have been a chunk producer for some shard at + height $h - 1$, this minimizes network communication between chunk producers and block + producers +* The number of distinct chunk-only/block producers should be as large as is allowed by the + scalability in the consensus algorithm (too large and the system would be too slow, too small and + the system would be too centralized) $^{\dagger}$ + +> $\dagger$ Note: By "distinct block producers" we mean the number of different signing keys. +> We recognize it is possible for a single "logical entity" to split their stake into two or more +> proposals (Sybil attack), however steps to prevent this kind of attack against centralization are +> out of scope for this document. + +## Assumptions + +* The maximum number of distinct chunk-only producers and block producers supported by the consensus + algorithm is a fixed constant. This will be a parameter of the protocol itself (i.e. all nodes + must agree on the constant). In this document, we will denote the maximum number of chunk-only + producers as `MAX_NUM_CP` and the maximum number of block producers by `MAX_NUM_BP`. +* The minimum number of blocks in the epoch is known at the time of block producer selection. This + minimum does not need to be incredibly accurate, but we will assume it is within a factor of 2 of + the actual number of blocks in the epoch. In this document we will refer to this as the "length of + the epoch", denoted by `epoch_length`. +* To meet the requirement that any chosen validator will be selected to produce at least one + chunk/block in the epoch, we assume it is acceptable for the probability of this *not* happening + to be sufficiently low. Let `PROBABILITY_NEVER_SELECTED` be a protocol constant which gives the + maximum allowable probability that the chunk-only/block producer with the least stake will never + be selected to produce a chunk/block during the epoch. We will additionally assume the chunk/block + producer assigned to make each chunk/block is chosen independently, and in proportion to the + participant's stake. Therefore, the probability that the block producer with least stake is never + chosen is given by the expression $(1 - (s_\text{min} / S))^\text{epoch\_length}$, where + $s_\text{min}$ is the least stake of any block producer and $S$ is the total relevant + stake (what stake is "relevant" depends on whether the validator is a chunk-only producer or a + block producer; more details below). Hence, the algorithm will enforce the condition $(1 - + (s_\text{min} / S))^\text{epoch\_length} < \text{PROBABILITY\_NEVER\_SELECTED}$. + +## Algorithm for selecting block producers + +### Input + +* `MAX_NUM_BP: u16` (see Assumptions above for definition) +* `epoch_length: u64` +* `PROBABILITY_NEVER_SELECTED: Ratio` + - `Ratio` means a fraction where the numerator and denominator are represented by unsigned + 128-bit numbers +* `block_producer_proposals: Vec` (proposed stakes for the next epoch from nodes sending + staking transactions) + - Note: there are separate actions to propose to be a chunk-only producer or a block producer. + Here only block producer proposals are considered. + +### Output + +* `block_producers: Vec` (chosen block producers for the next epoch) +* `block_producer_sampler: WeightedIndex` + - Data structure to allow $O(1)$ sampling from the block producers with probability + proportional to their stake + - This structure will be based on the + [WeightedIndex](https://rust-random.github.io/rand/rand/distributions/weighted/alias_method/struct.WeightedIndex.html) + implementation (see a description of [Vose's Alias + Method](https://en.wikipedia.org/wiki/Alias_method) for details) + +### Steps + +```python +sorted_proposals = + sorted_descending(block_producer_proposals, key=lambda v: (v.stake, v.account_id)) + +# smallest value of s_min / S such that +# (1 - (s_min / S))^epoch_length < PROBABILITY_NEVER_SELECTED +min_stake_fraction = + 1 - PROBABILITY_NEVER_SELECTED^(1/epoch_length) + +total_stake = 0 + +block_producers = [] +for v in sorted_proposals[0:MAX_NUM_BP]: + total_stake += v.stake + if (v.stake / total_stake) > min_stake_fraction: + block_producers.append(v) + else: + break + +block_producer_sampler = WeightedIndex([v.stake for v in block_producers]) + +return (block_producers, block_producer_sampler) +``` + +## Algorithm for assigning chunk producers to shards + +Note: no algorithm for assigning block producers to shards is needed because we are working within +"Simple Nightshade" where block producers track all shards. + +### Input + +* `chunk_producers: Vec` +* `num_shards: usize` +* `min_validators_per_shard: usize` + +### Output + +* `validator_shard_assignments: Vec>` + - $i$-th element gives the validators assigned to shard $i$ + +### Steps + +* While any shard has fewer than `min_validators_per_shard` validators assigned to it: + - Let `cp_i` be the next element of `chunk_producers` (cycle back to the beginning as needed) + - Note: if there are more shards than chunk producers, then some chunk producers will + be assigned to multiple shards. This is undesirable because we want each chunk-only producer + to be a assigned to exactly one shard. However, block producers are also chunk producers, + so even if we must wrap around a little, chunk-only producers may still not be assigned + multiple shards. Moreover, we assume that in practice there will be many more chunk producers + than shards (in particular because block producers are also chunk producers). + - Let `shard_id` be the shard with the fewest number of assigned validators such that `cp_i` has + not been assigned to `shard_id` + - Assign `cp_i` to `shard_id` +* While there are any validators which have not been assigned to any shard: + - Let `cp_i` be the next validator not assigned to any shard + - Let `shard_id` be the shard with the least total stake (total stake = sum of stakes of all + validators assigned to that shard) + - Assign `cp_i` to `shard_id` +* Return the shard assignments + +In addition to the above description, we have a [proof-of-concept (PoC) on +GitHub](https://github.com/birchmd/bp-shard-assign-poc). Note: this PoC has not been updated since +the change to Simple Nightshade, so it assumes we are assigning block producers to shards. However, +the same algorithm works to assign chunk producers to shards; it is only a matter of renaming +variables referencing "block producers" to reference "chunk producers" instead. + +## Algorithm for selecting chunk producers + +### Input + +* `MAX_NUM_BP: u16` +* `MAX_NUM_CP: u16` +* `epoch_length: u64` +* `PROBABILITY_NEVER_SELECTED: Ratio` +* `num_shards: usize` +* `min_validators_per_shard: usize` +* `block_producers_proposals: Vec` +* `chunk_only_producer_proposals: Vec` + +### Output + +* `chunk_producers: Vec` (chosen chunk producers for the next epoch) +* `validator_shard_assignments: Vec>` + - $i$-th element gives the validators assigned to shard $i$ +* `chunk_producer_sampler: Vec` + +### Steps + +```python +# Group both sets of proposals together since all block producers +# can also serve as chunk producers. +validator_proposals = block_producers_proposals + chunk_only_producer_proposals +sorted_proposals = + sorted_descending(validator_proposals, key=lambda v: (v.stake, v.account_id)) + +# smallest value of s_min / S such that +# (1 - (s_min / S))^epoch_length < PROBABILITY_NEVER_SELECTED +min_stake_fraction = + 1 - PROBABILITY_NEVER_SELECTED^(1/epoch_length) + +# we assume the stake from chunk producers will be roughly +# evenly distributed among all the shards, so the stake fraction +# we care about is really smaller than the quantity above. +min_stake_fraction /= num_shards + +chunk_producers = [] +total_stake = 0 +for v in sorted_proposals[0:(MAX_NUM_BP + MAX_NUM_CP)]: + total_stake += v.stake + if (v.stake / total_stake) > min_stake_fraction: + chunk_producers.append(v) + else: + break + +chunk_producers.sort_descending(key=lambda v: (v.stake, v.account_id)) +# using the algorithm above to assign shards +validator_shard_assignments = + assign_chunk_producers(chunk_producers, num_shards, min_validators_per_shard) + +chunk_producer_sampler = [ + WeightedIndex([v.stake for v in shard_cps]) for shard_cps in validator_shard_assignments +] + +return (chunk_producers, validator_shard_assignments, chunk_producer_sampler) +``` + +## Algorithm for sampling validators proportional to stake + +This algorithm is applied using both chunk-only producers and block producers in the subsequent +algorithms for selecting a specific block producer and chunk producer at each height. + +### Input + +* `rng_seed: [u8; 32]` + - See usages of this algorithm below to see how this seed is generated +* `validators: Vec` +* `sampler: WeightedIndex` + +### Output + +* `selection: ValidatorStake` + +### Steps + +```python +# The seed is used as an entropy source for the random numbers. +# The first 8 bytes select a block producer uniformly. +uniform_index = int.from_bytes(rng_seed[0:8], byteorder='little') % len(validators) + +# The next 16 bytes uniformly pick some weight between 0 and the total +# weight (i.e. stake) of all block producers. +let uniform_weight = int.from_bytes(rng_seed[8:24], byteorder='little') \ + % sampler.weight_sum() + +# Return either the uniformly selected block producer, or its "alias" +# depending on the uniformly selected weight. +index = uniform_index \ + if uniform_weight < sampler.no_alias_odds[uniform_index] \ + else sampler.aliases[uniform_index] + +return validators[index] +``` + +## Algorithm for selecting producer of block at height $h$ + +### Input + +* `h: BlockHeight` + - Height to compute the block producer for + - Only heights within the epoch corresponding to the given block producers make sense as input +* `block_producers: Vec` (output from above) +* `block_producer_sampler: WeightedIndex` +* `epoch_rng_seed: [u8; 32]` + - Fixed seed for the epoch determined from Verified Random Function (VRF) output of last block in + the previous epoch + +### Output + +* `block_producer: ValidatorStake` + +### Steps + +```python +# Concatenates the bytes of the epoch seed with the height, +# then computes the sha256 hash. +block_seed = combine(epoch_rng_seed, h) + +# Use the algorithm defined above +return select_validator(rng_seed=block_seed, validators=block_producers, sampler=block_producer_sampler) +``` + +## Algorithm for selection of chunk producer at height $h$ for all shards + +### Input + +* (same inputs as selection of block producer at height h) +* `num_shards: usize` +* `chunk_producer_sampler: Vec` (outputs from chunk-only producer selection) +* `validator_shard_assignments: Vec>` + +### Output + +* `chunk_producers: Vec` + - `i`th element gives the validator that will produce the chunk for shard `i`. Note: at least one + of these will be a block producer, while others will be chunk-only producers. + +### Steps + +```python +bp = block_producer_at_height( + h + 1, + block_producers, + block_producer_sampler, + epoch_rng_seed, +) + +result = [] +for shard_id in range(num_shards): + # concatenate bytes and take hash to create unique seed + shard_seed = combine(epoch_rng_seed, h, shard_id) + # Use selection algorithm defined above + cp = select_validator( + rng_seed=shard_seed, + validators=validator_shard_assignments[shard_id], + sampler=chunk_producer_sampler[shard_id] + ) + result.append(cp) + +# Ensure the block producer for the next block also produces one of the shards. +# `bp` could already be in the result because block producers are also +# chunk producers (see algorithm for selecting chunk producers from proposals). +if bp not in result: + # select a random shard for the block producer to also create the chunk for + rand_shard_seed = combine(epoch_rng_seed, h) + bp_shard_id = int.from_bytes(rand_shard_seed[0:8], byteorder='little') % num_shards + result[bp_shard_id] = bp + +return result +``` diff --git a/specs/Economics/README.md b/specs/Economics/README.md index 8f608ee69..c9bc8018b 100644 --- a/specs/Economics/README.md +++ b/specs/Economics/README.md @@ -111,17 +111,6 @@ NEAR validators provide their resources in exchange for a reward `epochReward[t] ### Validator Selection -| Name | Description | -| - | - | -| `proposals: Proposal[]` | The array of all new staking transactions that have happened during the epoch (if one account has multiple only last one is used) | -| `current_validators` | The array of all existing validators during the epoch | -| `epoch[T]` | The epoch when validator[v] is selected from the `proposals` auction array | -| `seat_price` | The minimum stake needed to become validator in epoch[T] | -| `stake[v]` | The amount in NEAR tokens staked by validator[v] during the auction at the end of epoch[T-2], minus `INCLUSION_FEE` | -| `shard[v]` | The shard is randomly assigned to validator[v] at epoch[T-1], such that its node can download and sync with its state | -| `num_allocated_seats[v]` | Number of seats assigned to validator[v], calculated from stake[v]/seatPrice | -| `validatorAssignments` | The resulting ordered array of all `proposals` with a stake higher than `seatPrice` | - ```rust struct Proposal { account_id: AccountId, @@ -131,40 +120,14 @@ struct Proposal { ``` During the epoch, outcome of staking transactions produce `proposals`, which are collected, in the form of `Proposal`s. +There are separate proposals for block producers and chunk-only producers, see [Selecting Chunk and Block Producers](../ChainSpec/SelectingBlockProducers.md). +for more information. At the end of every epoch `T`, next algorithm gets executed to determine validators for epoch `T + 2`: -1. For every validator in `current_validators` determine `num_blocks_produced`, `num_chunks_produced` based on what they produced during the epoch. +1. For every chunk/block producer in `epoch[T]` determine `num_blocks_produced`, `num_chunks_produced` based on what they produced during the epoch. 2. Remove validators, for whom `num_blocks_produced < num_blocks_expected * BLOCK_PRODUCER_KICKOUT_THRESHOLD` or `num_chunks_produced < num_chunks_expected * CHUNK_PRODUCER_KICKOUT_THRESHOLD`. -3. Add validators from `proposals`, if validator is also in `current_validators`, considered stake of the proposal is `0 if proposal.stake == 0 else proposal.stake + reward[proposal.account_id]`. -4. Find seat price `seat_price = findSeatPrice(current_validators - kickedout_validators + proposals, num_seats)`, where each validator gets `floor(stake[v] / seat_price)` seats and `seat_price` is highest integer number such that total number of seats is at least `num_seats`. -5. Filter validators and proposals to only those with stake greater or equal than seat price. -6. For every validator, replicate them by number of seats they get `floor(stake[v] / seat_price)`. -7. Randomly shuffle (TODO: define random number sampler) with seed from randomness generated on the last block of current epoch (via `VRF(block_producer.private_key, block_hash)`). -8. Cut off all seats which are over the `num_seats` needed. -9. Use this set for block producers and shifting window over it as chunk producers. - -```python -def findSeatPrice(stakes, num_seats): - """Find seat price given set of stakes and number of seats required. - - Seat price is highest integer number such that if you sum `floor(stakes[i] / seat_price)` it is at least `num_seats`. - """ - stakes = sorted(stakes) - total_stakes = sum(stakes) - assert total_stakes >= num_seats, "Total stakes should be above number of seats" - left, right = 1, total_stakes + 1 - while True: - if left == right - 1: - return left - mid = (left + right) // 2 - sum = 0 - for stake in stakes: - sum += stake // mid - if sum >= num_seats: - left = mid - break - right = mid -``` +3. Collect chunk-only and block producer `proposals`, if validator was also a validator in `epoch[T]`, considered stake of the proposal is `0 if proposal.stake == 0 else proposal.stake + reward[proposal.account_id]`. +4. Use the chunk/block producer selection algorithms outlined in [Selecting Chunk and Block Producers](../ChainSpec/SelectingBlockProducers.md). ### Validator Rewards Calculation @@ -184,6 +147,9 @@ treasury_reward[t] = floor(reward[t] * protocol_reward_rate) validator_reward[t] = total_reward[t] - treasury_reward[t] ``` +The validator reward is split between block producers and chunk only producers. A fraction `f` is given to block producers, +while the remainder is given to chunk-only producers (i.e. validators who were not block producers). + Validators that didn't meet the threshold for either blocks or chunks get kicked out and don't get any reward, otherwise uptime of a validator is computed: @@ -200,7 +166,8 @@ Where `expected_produced_blocks` and `expected_produced_chunks` is the number of The specific `validator[t][j]` reward for epoch `t` is then proportional to the fraction of stake of this validator from total stake: ```python -validatorReward[t][j] = floor(uptime[t][j] * stake[t][j] * validator_reward[t] / total_stake[t]) +blockProducerReward[t][j] = floor(uptime[t][j] * stake[t][j] * f * validator_reward[t] / total_stake[t]) +chunkOnlyProducerReward[t][j] = floor(uptime[t][j] * stake[t][j] * (1 - f) * validator_reward[t] / total_stake[t]) ``` ### Slashing From 36c96b7f09c0fb01b90a715dad5839f70eddba3c Mon Sep 17 00:00:00 2001 From: Thor <7041313+thor314@users.noreply.github.com> Date: Mon, 21 Nov 2022 06:02:05 -0800 Subject: [PATCH 087/150] chore: Added code snippet in Rust to the reference-level explanation of ApprovalManagement.md (#187) --- .../Tokens/NonFungibleToken/ApprovalManagement.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/specs/Standards/Tokens/NonFungibleToken/ApprovalManagement.md b/specs/Standards/Tokens/NonFungibleToken/ApprovalManagement.md index e7219dd96..c1407332e 100644 --- a/specs/Standards/Tokens/NonFungibleToken/ApprovalManagement.md +++ b/specs/Standards/Tokens/NonFungibleToken/ApprovalManagement.md @@ -283,6 +283,15 @@ Example token data: } ``` +In Rust, the standard library `HashMap` is the recommended type for the `approvals` field, though any `map` may be used. +```diff + pub struct Token = { + pub id: String, + pub owner_id: String, ++ pub approvals: std::collections::HashMap, + } +``` + ### What is an "approval ID"? This is a unique number given to each approval that allows well-intentioned marketplaces or other 3rd-party NFT resellers to avoid a race condition. The race condition occurs when: From 69626eb07725341e8bb7944a91246e0781b51470 Mon Sep 17 00:00:00 2001 From: Daniel Wang Date: Mon, 21 Nov 2022 23:36:06 +0800 Subject: [PATCH 088/150] chore: Update description to mark `approval_id` as optional in NFT Core NEP (#263) --- specs/Standards/Tokens/NonFungibleToken/Core.md | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/specs/Standards/Tokens/NonFungibleToken/Core.md b/specs/Standards/Tokens/NonFungibleToken/Core.md index 749773e89..842e0231a 100644 --- a/specs/Standards/Tokens/NonFungibleToken/Core.md +++ b/specs/Standards/Tokens/NonFungibleToken/Core.md @@ -70,7 +70,7 @@ type Token = { // Arguments: // * `receiver_id`: the valid NEAR account receiving the token // * `token_id`: the token to transfer -// * `approval_id`: expected approval ID. A number smaller than +// * `approval_id` (optional): expected approval ID. A number smaller than // 2^53, and therefore representable as JSON. See Approval Management // standard for full explanation. // * `memo` (optional): for use cases that may benefit from indexing or @@ -109,7 +109,7 @@ function nft_transfer( // Arguments: // * `receiver_id`: the valid NEAR account receiving the token. // * `token_id`: the token to send. -// * `approval_id`: expected approval ID. A number smaller than +// * `approval_id` (optional): expected approval ID. A number smaller than // 2^53, and therefore representable as JSON. See Approval Management // standard for full explanation. // * `memo` (optional): for use cases that may benefit from indexing or @@ -120,9 +120,9 @@ function nft_transfer( function nft_transfer_call( receiver_id: string, token_id: string, + msg: string, approval_id: number|null, memo: string|null, - msg: string, ): Promise {} @@ -158,7 +158,7 @@ The following behavior is required, but contract authors may name this function // * `owner_id`: the original owner of the NFT. // * `receiver_id`: the `receiver_id` argument given to `nft_transfer_call` // * `token_id`: the `token_id` argument given to `nft_transfer_call` -// * `approved_account_ids `: if using Approval Management, contract MUST provide +// * `approved_account_ids` (optional): if using Approval Management, contract MUST provide // record of original approved accounts in this argument, and restore these // approved accounts and their approval IDs in case of revert. // @@ -202,6 +202,7 @@ function nft_on_transfer( ## Errata +* **2022-11-21**: Mark `approval_id` parameter as optional in function description as well. * **2022-02-03**: updated `Token` struct field names. `id` was changed to `token_id`. This is to be consistent with current implementations of the standard and the rust SDK docs. * **2021-12-20**: updated `nft_resolve_transfer` argument `approved_account_ids` to be type `null|Record` instead of `null|string[]`. This gives contracts a way to restore the original approved accounts and their approval IDs. More information can be found in [this](https://github.com/near/NEPs/issues/301) discussion. From f018916843cb7534c12056d4765e84f05c93d513 Mon Sep 17 00:00:00 2001 From: Vlad Frolov Date: Mon, 21 Nov 2022 16:52:38 +0100 Subject: [PATCH 089/150] chore: Fixed the example provided in the NFT Motivation section (#434) --- specs/Standards/Tokens/NonFungibleToken/Core.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/specs/Standards/Tokens/NonFungibleToken/Core.md b/specs/Standards/Tokens/NonFungibleToken/Core.md index 842e0231a..bd296965f 100644 --- a/specs/Standards/Tokens/NonFungibleToken/Core.md +++ b/specs/Standards/Tokens/NonFungibleToken/Core.md @@ -21,7 +21,7 @@ Given these attributes, this NFT standard can accomplish with one user interacti * An [Exquisite Corpse](https://en.wikipedia.org/wiki/Exquisite_corpse) contract allows three drawings to be submitted, one for each section of a final composition, to be minted as its own NFT and sold on a marketplace, splitting royalties amongst the original artists. * Alice draws the top third and submits it, Bob the middle third, and Carol follows up with the bottom third. Since they each use `nft_transfer_call` to both transfer their NFT to the Exquisite Corpse contract as well as call a `submit` method on it, the call from Carol can automatically kick off minting a composite NFT from the three submissions, as well as listing this composite NFT in a marketplace. -* When Dan attempts to also call `nft_transfer_call` to submit an unneeded top third of the drawing, the Exquisite Corpse contract can throw an error, and the transfer will be rolled back so that Bob maintains ownership of his NFT. +* When Dan attempts to also call `nft_transfer_call` to submit an unneeded top third of the drawing, the Exquisite Corpse contract can throw an error, and the transfer will be rolled back so that Dan maintains ownership of his NFT. While this is already flexible and powerful enough to handle all sorts of existing and new use-cases, apps such as marketplaces may still benefit from the [Approval Management] extension. From 343ac9214912c4e5b2eb9be7bb76fe756a17158e Mon Sep 17 00:00:00 2001 From: Illia Polosukhin Date: Wed, 23 Nov 2022 16:23:09 -0800 Subject: [PATCH 090/150] NEP-366: Meta transactions (#366) ## Summary In-protocol meta transactions allowing for third-party account to initiate and pay transaction fees on behalf of the account. ## Motivation NEAR has been designed with simplify of onboarding in mind. One of the large hurdles right now is that after creating an implicit or even named account user doesn't have NEAR to pay gas fees to interact with apps. For example, apps that pay user for doing work (like NEARCrowd or Sweatcoin) or free-to-play games. [Aurora Plus](https://aurora.plus) has shown viability of the relayers that can offer some number of free transactions and a subscription model. Shifting the complexity of dealing with fees to the infrastructure from the user space. ## Rationale and alternatives Proposed here design provides the easiest for users and developers way to onboard and pay for user transactions. There is no requirement on the user account, including user account may not even exist on chain and implicit account can be used. An alterantive is a proxy contracts deployed on the user account. This design has severe limitations as it requires user to deploy such contract and additional costs for storage. ## Specification Next changes to protocol are required: - New Action kind: `DelegateAction(receiver_id, Action, signer_pk, signature)` - On conversion to Receipt, such action is sent as `DelegateAction` to the `receiver_id`. - On processing Receipt, it verifies the `signature` over the given account and `signer_pk`. Unwraps into `receiver_id: AccountId`, `action: Action` inside into new Receipt with given `receiver_id` and `action`. This means that `predeccessor_id` of such action has been overriden. See the [DelegateAction specification](specs/RuntimeSepc/Actions.md#DelegateAction) for details. ## Security Implications Delegate actions do not override `signer_pk`, leaving that to the original signer that initiated transaction (eg relayer in meta transaction case). Although it is possible to override `signer_pk` in the context with one from `DelegateAction`, there is no clear value to do that. See ***Validation*** section in [DelegateAction specification](specs/RuntimeSepc/Actions.md#DelegateAction) for security considerations around what user signs and validation of actions with different permissions. ## Drawbacks Increases complexity of the NEAR's transactional model. Meta transactions take an extra block to execute, as they first need to be included by the originating account, then routed to the delegate account and only after that to the real destination. Delegate actions are not programmable as they require having signatures. Original proposal contained a new `AccessKey` kind that would support programmable delegated actions. On the other hand, that would be limiting without progamability of smart contracts, hence that idea evolved into [Account Extensions](https://github.com/nearprotocol/neps/pull/0000). ## Future possibilities Supporting ZK proofs instead of just signatures can allow for anonymous transactions, which pay fees to relayers in anonymous way. ## Copyright [copyright]: #copyright Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). Co-authored-by: ori-near <110252255+ori-near@users.noreply.github.com> Co-authored-by: e-uleyskiy <70713560+e-uleyskiy@users.noreply.github.com> Co-authored-by: Egor Uleyskiy --- README.md | 3 +- neps/assets/nep-0366/NEP-DelegateAction.png | Bin 0 -> 144319 bytes neps/nep-0366.md | 203 ++++++++++++++++++++ specs/RuntimeSpec/Receipts.md | 1 + 4 files changed, 206 insertions(+), 1 deletion(-) create mode 100644 neps/assets/nep-0366/NEP-DelegateAction.png create mode 100644 neps/nep-0366.md diff --git a/README.md b/README.md index 315643f23..33494d582 100644 --- a/README.md +++ b/README.md @@ -25,6 +25,7 @@ Changes to the protocol specification and standards are called NEAR Enhancement |[0245](https://github.com/near/NEPs/blob/master/neps/nep-0245.md) | Multi Token Standard | @zcstarr @riqi @jriemann @marcos.sun | Review | |[0297](https://github.com/near/NEPs/blob/master/neps/nep-0297.md) | Events Standard | @telezhnaya | Final | |[0330](https://github.com/near/NEPs/blob/master/neps/nep-0330.md) | Source Metadata | @BenKurrek | Review | +|[0366](https://github.com/near/NEPs/blob/master/neps/nep-0366.md) | Meta Transactions | @ilblackdragon @e-uleyskiy @fadeevab | Draft | @@ -68,7 +69,7 @@ Spec changes are ultimately done via pull requests to this repository (formalize ``` * Once complete, submit the pull request for editor review. - + * The formalization dance begins: * NEP Editors, who are unopinionated shepherds of the process, check document formatting, completeness and adherence to [NEP-0001](neps/nep-0001.md) and approve the pull request. * Once ready, the author updates the NEP status to `Review` allowing further community participation, to address any gaps or clarifications, normally part of the Review PR. diff --git a/neps/assets/nep-0366/NEP-DelegateAction.png b/neps/assets/nep-0366/NEP-DelegateAction.png new file mode 100644 index 0000000000000000000000000000000000000000..00aeed8972643bfbdc0150f4d1a32a6254386c40 GIT binary patch literal 144319 zcmdqJbyQW|*9IyGN(mfVx|>5wcXxM#l&ExfcT0yfNJ=Ov9V!hHD&5^6&0WX$_xrwg zjQfpo|G$pyP!Id;z1CcF&H2n{KFdf|WtnFvgeZ?5J$fc5E2;kI5rWa9NANmGPrxT) zl}za14>)Ia8SzKeBgET}9+5wilN8hRFy6~S&W@dW7!a{Qvp}WznfARsTve|isZy$p zzRt=-!cAOHLN6+!K>Z|I^_?m*g8^j4_hG1}6d^?f{2!OBiyGPg`BF?c5%AcRr)A5TYvq=^wPxqq#C$$zX;35S62)

Rx^eI@_M4fpp@yBI(VGx# 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 literal 0 HcmV?d00001 diff --git a/neps/nep-0366.md b/neps/nep-0366.md new file mode 100644 index 000000000..d27ddea7a --- /dev/null +++ b/neps/nep-0366.md @@ -0,0 +1,203 @@ +--- +NEP: 366 +Title: Meta Transactions +Author: Illia Polosukhin , Egor Uleyskiy (egor.ulieiskii@gmail.com), Alexander Fadeev (fadeevab.com@gmail.com) +DiscussionsTo: https://github.com/nearprotocol/neps/pull/366 +Status: Draft +Type: Protocol Track +Category: Runtime +Created: 19-Oct-2022 +--- + +## Summary + +In-protocol meta transactions allowing for third-party account to initiate and pay transaction fees on behalf of the account. + +## Motivation + +NEAR has been designed with simplicity of onboarding in mind. One of the large hurdles right now is that after creating an implicit or even named account the user does not have NEAR to pay gas fees to interact with apps. + +For example, apps that pay user for doing work (like NEARCrowd or Sweatcoin) or free-to-play games. + +[Aurora Plus](https://aurora.plus) has shown viability of the relayers that can offer some number of free transactions and a subscription model. Shifting the complexity of dealing with fees to the infrastructure from the user space. + +## Rationale and alternatives + +The proposed design here provides the easiest way for users and developers to onboard and to pay for user transactions. + +An alternative is to a proxy contracts deployed on the user account. +This design has severe limitations as it requires the user to deploy such contract and incur additional costs for storage. + +## Specification + +* **User** (Sender) is the one who is going to send the `DelegateAction` to Receiver via Relayer. +* **Relayer** is the one who publishes the `DelegateAction` to the protocol. +* **User** and Relayer doesn't trust each other. + +The main flow of the meta transaction will be as follows: + - User specifies `sender_id` (the user's account id), `receiver_id` (the receiver's account id) and other information (see `DelegateAction` format). + - User signs `DelegateAction` specifying the set of actions that they need to be executed. + - User forms `SignedDelegateAction` with the `DelegateAction` and the signature. + - User forms `DelegateActionMessage` with the `SignedDelegateAction`. + - User sends `DelegateActionMessage` data to the relayer. + - Relayer verifies actions specified in `DelegateAction`: the total cost and whether the user included the reward for the relayer. + - Relayer forms a `Transaction` with `receiver_id` equals to `delegate_action.sender_id` and `actions: [SignedDelegateAction { ... }]`. Signs it with its key. Note that such transactions can contain other actions toward user's account (for example calling a function). + - This transaction is processed normally. A `Receipt` is created with a copy of the actions in the transaction. + - When processing a `SignedDelegateAction`, a number of checks are done (see below), mainly a check to ensure that the `signature` matches the user account's key. + - When a `Receipt` with a valid `SignedDelegateAction` in actions arrives at the user's account, it gets executed. Execution means creation of a new Receipt with `receiver_id: AccountId` and `actions: Action` matching `receiver_id` and `actions` in the `DelegateAction`. + - The new `Receipt` looks like a normal receipt that could have originated from the user's account, with `predeccessor_id` equal to tbe user's account, `signer_id` equal to the relayer's account, `signer_public_key` equal to the relayer's public key. + +## Diagram +![](assets/nep-0366/NEP-DelegateAction.png) + + ## Limitations + * If User account exist, then deposit and gas are refunded as usual: gas is refuned to Relayer, deposit is refunded to User. + * If User account doesn't exist then gas is refunded to Relayer, deposit is burnt. + * `DelegateAction` actions mustn't contain another `DelegateAction` (`DelegateAction` can't conatin the nested ones). + +### DelegateAction + +Delegate actions allows for an account to initiate a batch of actions on behalf of a receiving account, allowing proxy actions. This can be used to implement meta transactions. + +```rust +pub struct DelegateAction { + /// Signer of the delegated actions + sender_id: AccountId, + /// Receiver of the delegated actions. + receiver_id: AccountId, + /// List of actions to be executed. + actions: Vec, + /// Nonce to ensure that the same delegate action is not sent twice by a relayer and should match for given account's `public_key`. + /// After this action is processed it will increment. + nonce: Nonce, + /// The maximal height of the block in the blockchain below which the given DelegateAction is valid. + max_block_height: BlockHeight, + /// Public key that is used to sign this delegated action. + public_key: PublicKey, +} +``` + +```rust +pub struct SignedDelegateAction { + delegate_action: DelegateAction, + /// Signature of the `DelegateAction`. + signature: Signature, +} +``` + + Supporting batches of `actions` means `DelegateAction` can be used initiate a complex steps like creating new accounts, transferring funds, deploying contracts, and executing an initialization function all within the same transaction. + +***Validation***: +1. Validate `DelegateAction` doesn't contain a nested `DelegateAction` in actions. +2. To ensure that a `DelegateAction` is correct, on receipt the following signature verification is performed: `verify_signature(hash(delegate_action), delegate_action.public_key, signature)`. +3. Verify `transaction.receiver_id` matches `delegate_action.sender_id`. +4. Verify `delegate_action.max_block_height`. The `max_block_height` must be greater than the current block height (at the `DelegateAction` processing time). +5. Verify `delegate_action.sender_id` owns `delegate_action.public_key`. +6. Verify `delegate_action.nonce > sender.access_key.nonce`. + +A `message` is formed in the following format: +```rust +struct DelegateActionMessage { + signed_delegate_action: SignedDelegateAction +} +``` + +The next set of security concerns are addressed by this format: + - `sender_id` is included to ensure that the relayer set correct `transaction.receiver_id`. + - `max_block_height` is included to ensure that the `DelegateAction` isn't expired. + - `nonce` is included to ensure that the `DelegateAction` can't be replayed again. + - `public_key` and `sender_id` are needed to ensure that on the right account, work across rotating keys and fetch correct `nonce`. + +The permissions are verified based on the variant of `public_key`: + - `AccessKeyPermission::FullAccess`, all actions are allowed. + - `AccessKeyPermission::FunctionCall`, only a single `FunctionCall` action is allowed in `actions`. + - `DelegateAction.receiver_id` must match to the `account[public_key].receiver_id` + - `DelegateAction.actions[0].method_name` must be in the `account[public_key].method_names` + +***Outcomes***: +- If the `signature` matches the receiver's account's `public_key`, a new receipt is created from this account with a set of `ActionReceipt { receiver_id, action }` for each action in `actions`. + + +***Recommendations*** +- Because the User doesn't trust the Relayer, the User should verify whether the Relayer has submitted the `DelegateAction` and the execution result. + +#### Errors + +- If the Sender's account doesn't exist +```rust +/// Happens when TX receiver_id doesn't exist +AccountDoesNotExist +``` + +- If the `signature` does not match the data and the `public_key` of the given key, then the following error will be returned +```rust +/// Signature does not match the provided actions and given signer public key. +DelegateActionInvalidSignature +``` + +- If the `sender_id` doesn't match the `tx.receiver_id` +```rust +/// Receiver of the transaction doesn't match Sender of the delegate action +DelegateActionSenderDoesNotMatchReceiver +``` + +- If the current block is equal or greater than `max_block_height` +```rust +/// Delegate action has expired +DelegateActionExpired +``` + +- If the `public_key` does not exist for Sender account +```rust +/// The given public key doesn't exist for Sender account +DelegateActionAccessKeyError +``` + +- If the `nonce` does match the `public_key` for the `sender_id` +```rust +/// Nonce must be greater sender[public_key].nonce +DelegateActionInvalidNonce +``` + +- If `nonce` is too large +```rust +/// DelegateAction nonce is larger than the upper bound given by the block height (block_height * 1e6) +DelegateActionNonceTooLarge +``` + +- If the list of delegated actions contains another `DelegateAction` +```rust +/// DelegateAction actions contain another DelegateAction +DelegateActionCantContainNestedOne +``` + +- If the list of Transaction actions contains several `DelegateAction` +```rust +/// There should be the only one DelegateAction +DelegateActionMustBeOnlyOne +``` + +See the [DelegateAction specification](/specs/RuntimeSpec/Actions.md#DelegateAction) for details. + +## Security Implications + +Delegate actions do not override `signer_public_key`, leaving that to the original signer that initiated transaction (e.g. the relayer in the meta transaction case). Although it is possible to override the `signer_public_key` in the context with one from the `DelegateAction`, there is no clear value in that. + +See the ***Validation*** section in [DelegateAction specification](/specs/RuntimeSpec/Actions.md#DelegateAction) for security considerations around what the user signs and the validation of actions with different permissions. + +## Drawbacks + +* Increases complexity of NEAR's transactional model. +* Meta transactions take an extra block to execute, as they first need to be included by the originating account, then routed to the delegate account, and only after that to the real destination. +* User can't call functions from different contracts in same `DelegateAction`. This is because `DelegateAction` has only one receiver for all inner actions. +* The Relayer must verify the most of parameters before submitting `DelegateAction`, making sure that one of the function calls is the reward action. Either way, this is a risk for Relayer in general. +* User must not trust Relayer’s response and should check execution errors in Blockchain. + +## Future possibilities + +Supporting ZK proofs instead of just signatures can allow for anonymous transactions, which pay fees to relayers anonymously. + +## Copyright +[copyright]: #copyright + +Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). diff --git a/specs/RuntimeSpec/Receipts.md b/specs/RuntimeSpec/Receipts.md index 814c07082..1eec90bf3 100644 --- a/specs/RuntimeSpec/Receipts.md +++ b/specs/RuntimeSpec/Receipts.md @@ -1,6 +1,7 @@ # Receipt All cross-contract (we assume that each account lives in its own shard) communication in Near happens through Receipts. + Receipts are stateful in a sense that they serve not only as messages between accounts but also can be stored in the account storage to await DataReceipts. Each receipt has a [`predecessor_id`](#predecessor_id) (who sent it) and [`receiver_id`](#receiver_id) the current account. From d472932a5ad6732090d6a78053e50b61e821770c Mon Sep 17 00:00:00 2001 From: Anton Puhach Date: Mon, 5 Dec 2022 19:51:13 +0100 Subject: [PATCH 091/150] chore: reformat transaction validation section (#439) Bullet list layout indentation doesn't seem to look nice with multi-line code snippets, especially for the last section. In this PR I propose to use subtitles instead. This also includes a couple of minor fixes such as typos and rewording of signature validation description (to avoid potential confusion that transaction is actually signed by `public_key`). --- specs/RuntimeSpec/Transactions.md | 77 ++++++++++++++++++++----------- 1 file changed, 51 insertions(+), 26 deletions(-) diff --git a/specs/RuntimeSpec/Transactions.md b/specs/RuntimeSpec/Transactions.md index 55f64a53d..548715ed9 100644 --- a/specs/RuntimeSpec/Transactions.md +++ b/specs/RuntimeSpec/Transactions.md @@ -53,63 +53,91 @@ and potentially errors returned when they fail. ### Basic Validation -Basic validation of a transaction can be done without the state. Such validation includes -- Whether `signer_id` is valid. If not, a +Basic validation of a transaction can be done without the state. + +#### Valid `signer_id` format + +Whether `signer_id` is valid. If not, a ```rust /// TX signer_id is not in a valid format or not satisfy requirements see `near_core::primitives::utils::is_valid_account_id` InvalidSignerId { signer_id: AccountId }, ``` error is returned. -- Whether `receiver_id` is valid. If not, a + +#### Valid `receiver_id` format + +Whether `receiver_id` is valid. If not, a ```rust /// TX receiver_id is not in a valid format or not satisfy requirements see `near_core::primitives::utils::is_valid_account_id` InvalidReceiverId { receiver_id: AccountId }, ``` error is returned. -- Whether `signature` is signed by `public_key`. If not, a + +#### Valid `signature` + +Whether transaction is signed by the access key that corresponds to `public_key`. If not, a ```rust /// TX signature is not valid InvalidSignature ``` error is returned. -- Whether the number of actions included in the transaction is no greater than `max_actions_per_receipt`. If not, a + +#### Number of actions does not exceed `max_actions_per_receipt` + +Whether the number of actions included in the transaction is not greater than `max_actions_per_receipt`. If not, a ```rust /// The number of actions exceeded the given limit. TotalNumberOfActionsExceeded { total_number_of_actions: u64, limit: u64 } ``` error is returned. -- Among the actions in the transaction, whether `DeleteAccount`, if present, is the last action. If not, a + +#### `DeleteAccount` is the last action + +Among the actions in the transaction, whether `DeleteAccount`, if present, is the last action. If not, a ```rust /// The delete action must be a final action in transaction DeleteActionMustBeFinal ``` error is returned. -- Whether total prepaid gas does not exceed `max_total_prepaid_gas`. If not, a + +#### Prepaid gas does not exceed `max_total_prepaid_gas` + +Whether total prepaid gas does not exceed `max_total_prepaid_gas`. If not, a ```rust /// The total prepaid gas (for all given actions) exceeded the limit. TotalPrepaidGasExceeded { total_prepaid_gas: Gas, limit: Gas } ``` error is returned. -- Whether each action included is valid. Details of such check can be found in [action](Actions.md). + +#### Valid actions + +Whether each included action is valid. Details of such check can be found in [Actions](Actions.md). ### Validation With State -After the basic validation is done, we check the transaction against current state to perform further validation. This includes -- Whether `signer_id` exists. If not, a +After the basic validation is done, we check the transaction against current state to perform further validation. + +#### Existing `signer_id` + +Whether `signer_id` exists. If not, a ```rust /// TX signer_id is not found in a storage SignerDoesNotExist { signer_id: AccountId }, ``` error is returned. -- Whether the transaction nonce is greater than the existing nonce on the access key. If not, a +#### Valid transaction nonce + +Whether the transaction nonce is greater than the existing nonce on the access key. If not, a ```rust /// Transaction nonce must be account[access_key].nonce + 1 InvalidNonce { tx_nonce: Nonce, ak_nonce: Nonce }, ``` error is returned. -- If `signer_id` account has enough balance to cover the cost of the transaction. If not, a +#### Enough balance to cover transaction cost + +If `signer_id` account has enough balance to cover the cost of the transaction. If not, a ```rust /// Account does not have enough balance to cover TX cost NotEnoughBalance { @@ -120,7 +148,9 @@ NotEnoughBalance { ``` error is returned. -- If the transaction is signed by a function call access key and the function call access key does not have enough +#### Access Key is allowed to cover transaction cost + +If the transaction is signed by a function call access key and the function call access key does not have enough allowance to cover the cost of the transaction, a ```rust /// Access Key does not have enough allowance to cover transaction cost @@ -133,7 +163,9 @@ NotEnoughAllowance { ``` error is returned. -- If `signer_id` account does not have enough balance to cover its storage after paying for the cost of the transaction, a +#### Sufficient account balance to cover storage + +If `signer_id` account does not have enough balance to cover its storage after paying for the cost of the transaction, a ```rust /// Signer account doesn't have enough balance after transaction. LackBalanceForState { @@ -145,18 +177,11 @@ LackBalanceForState { ``` error is returned. -- If a transaction is signed by a function call access key, the following errors are possible: +#### Function call access key validations + +If a transaction is signed by a function call access key, the following errors are possible: * `InvalidAccessKeyError::RequiresFullAccess` if the transaction contains more than one action or if the only action it contains is not a `FunctionCall` action. * `InvalidAccessKeyError::DepositWithFunctionCall` if the function call action has nonzero `deposit`. -```rust -/// Transaction `receiver_id` doesn't match the access key receiver_id -InvalidAccessKeyError::ReceiverMismatch { tx_receiver: AccountId, ak_receiver: AccountId }, -``` -is returned when transaction's `receiver_id` does not match the `receiver_id` of the access key. -* -```rust -/// Transaction method name isn't allowed by the access key -InvalidAccessKeyError::MethodNameMismatch { method_name: String }, -``` -is returned if the name of the method that the transaction tries to call is not allowed by the access key. +* `InvalidAccessKeyError::ReceiverMismatch { tx_receiver: AccountId, ak_receiver: AccountId }` if transaction's `receiver_id` does not match the `receiver_id` of the access key. +* `InvalidAccessKeyError::MethodNameMismatch { method_name: String }` if the name of the method that the transaction tries to call is not allowed by the access key. From f9ce1825ca65e6688d1037a9a72d03c4b417eeeb Mon Sep 17 00:00:00 2001 From: Austin Abell Date: Sun, 18 Dec 2022 18:08:09 -0500 Subject: [PATCH 092/150] fix: typos and confusing wording in meta transaction spec (#442) --- neps/nep-0366.md | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/neps/nep-0366.md b/neps/nep-0366.md index d27ddea7a..b53da8d71 100644 --- a/neps/nep-0366.md +++ b/neps/nep-0366.md @@ -11,7 +11,7 @@ Created: 19-Oct-2022 ## Summary -In-protocol meta transactions allowing for third-party account to initiate and pay transaction fees on behalf of the account. +In-protocol meta transactions allow third-party accounts to initiate and pay transaction fees on behalf of the account. ## Motivation @@ -25,7 +25,7 @@ For example, apps that pay user for doing work (like NEARCrowd or Sweatcoin) or The proposed design here provides the easiest way for users and developers to onboard and to pay for user transactions. -An alternative is to a proxy contracts deployed on the user account. +An alternative is to have a proxy contract deployed on the user account. This design has severe limitations as it requires the user to deploy such contract and incur additional costs for storage. ## Specification @@ -53,11 +53,11 @@ The main flow of the meta transaction will be as follows: ## Limitations * If User account exist, then deposit and gas are refunded as usual: gas is refuned to Relayer, deposit is refunded to User. * If User account doesn't exist then gas is refunded to Relayer, deposit is burnt. - * `DelegateAction` actions mustn't contain another `DelegateAction` (`DelegateAction` can't conatin the nested ones). + * `DelegateAction` actions mustn't contain another `DelegateAction` (`DelegateAction` can't contain the nested ones). ### DelegateAction -Delegate actions allows for an account to initiate a batch of actions on behalf of a receiving account, allowing proxy actions. This can be used to implement meta transactions. +Delegate actions allow an account to initiate a batch of actions on behalf of a receiving account, allowing proxy actions. This can be used to implement meta transactions. ```rust pub struct DelegateAction { @@ -85,7 +85,7 @@ pub struct SignedDelegateAction { } ``` - Supporting batches of `actions` means `DelegateAction` can be used initiate a complex steps like creating new accounts, transferring funds, deploying contracts, and executing an initialization function all within the same transaction. + Supporting batches of `actions` means `DelegateAction` can be used to initiate complex steps like creating new accounts, transferring funds, deploying contracts, and executing an initialization function all within the same transaction. ***Validation***: 1. Validate `DelegateAction` doesn't contain a nested `DelegateAction` in actions. @@ -103,10 +103,10 @@ struct DelegateActionMessage { ``` The next set of security concerns are addressed by this format: - - `sender_id` is included to ensure that the relayer set correct `transaction.receiver_id`. + - `sender_id` is included to ensure that the relayer sets the correct `transaction.receiver_id`. - `max_block_height` is included to ensure that the `DelegateAction` isn't expired. - `nonce` is included to ensure that the `DelegateAction` can't be replayed again. - - `public_key` and `sender_id` are needed to ensure that on the right account, work across rotating keys and fetch correct `nonce`. + - `public_key` and `sender_id` are needed to ensure that on the right account, work across rotating keys and fetch the correct `nonce`. The permissions are verified based on the variant of `public_key`: - `AccessKeyPermission::FullAccess`, all actions are allowed. @@ -181,7 +181,7 @@ See the [DelegateAction specification](/specs/RuntimeSpec/Actions.md#DelegateAct ## Security Implications -Delegate actions do not override `signer_public_key`, leaving that to the original signer that initiated transaction (e.g. the relayer in the meta transaction case). Although it is possible to override the `signer_public_key` in the context with one from the `DelegateAction`, there is no clear value in that. +Delegate actions do not override `signer_public_key`, leaving that to the original signer that initiated the transaction (e.g. the relayer in the meta transaction case). Although it is possible to override the `signer_public_key` in the context with one from the `DelegateAction`, there is no clear value in that. See the ***Validation*** section in [DelegateAction specification](/specs/RuntimeSpec/Actions.md#DelegateAction) for security considerations around what the user signs and the validation of actions with different permissions. @@ -190,7 +190,7 @@ See the ***Validation*** section in [DelegateAction specification](/specs/Runtim * Increases complexity of NEAR's transactional model. * Meta transactions take an extra block to execute, as they first need to be included by the originating account, then routed to the delegate account, and only after that to the real destination. * User can't call functions from different contracts in same `DelegateAction`. This is because `DelegateAction` has only one receiver for all inner actions. -* The Relayer must verify the most of parameters before submitting `DelegateAction`, making sure that one of the function calls is the reward action. Either way, this is a risk for Relayer in general. +* The Relayer must verify most of the parameters before submitting `DelegateAction`, making sure that one of the function calls is the reward action. Either way, this is a risk for Relayer in general. * User must not trust Relayer’s response and should check execution errors in Blockchain. ## Future possibilities From 12a37762a7dc25976304472166da19909628bf3d Mon Sep 17 00:00:00 2001 From: Anson VanDoren Date: Tue, 20 Dec 2022 10:40:22 -0800 Subject: [PATCH 093/150] fix: fixes min/max slippage typo and indented code blocks in FT Core standard (#203) --- specs/Standards/Tokens/FungibleToken/Core.md | 29 ++++++++++++-------- 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/specs/Standards/Tokens/FungibleToken/Core.md b/specs/Standards/Tokens/FungibleToken/Core.md index 72fe77c0e..736633c7a 100644 --- a/specs/Standards/Tokens/FungibleToken/Core.md +++ b/specs/Standards/Tokens/FungibleToken/Core.md @@ -135,7 +135,7 @@ Alice wants to swap 5 wrapped NEAR (wNEAR) for BNNA tokens at current market rat **High-level explanation** -Alice needs to issue one transaction to wNEAR contract to transfer 5 tokens (multiplied by precision) to `amm`, specifying her desired action (swap), her destination token (BNNA) & minimum slippage (<2%) in `msg`. +Alice needs to issue one transaction to wNEAR contract to transfer 5 tokens (multiplied by precision) to `amm`, specifying her desired action (swap), her destination token (BNNA) & maximum slippage (<2%) in `msg`. Alice will probably make this call via a UI that knows how to construct `msg` in a way the `amm` contract will understand. However, it's possible that the `amm` contract itself may provide view functions which take desired action, destination token, & slippage as input and return data ready to pass to `msg` for `ft_transfer_call`. For the sake of this example, let's say `amm` implements a view function called `ft_data_to_msg`. @@ -145,22 +145,27 @@ Altogether then, Alice may take two steps, though the first may be a background **Technical calls** -1. View `amm::ft_data_to_msg({ action: "swap", destination_token: "bnna", min_slip: 2 })`. Using [NEAR CLI](https://docs.near.org/docs/tools/near-cli): +1. View `amm::ft_data_to_msg({ action: "swap", destination_token: "bnna", max_slip: 2 })`. Using [NEAR CLI](https://docs.near.org/docs/tools/near-cli): - near view amm ft_data_to_msg '{ - "action": "swap", - "destination_token": "bnna", - "min_slip": 2 - }' + ```sh + near view amm ft_data_to_msg '{ + "action": "swap", + "destination_token": "bnna", + "max_slip": 2 + }' + ``` Then Alice (or the app she uses) will hold onto the result and use it in the next step. Let's say this result is `"swap:bnna,2"`. 2. Call `wnear::ft_transfer_call`. Using NEAR CLI: - near call wnear ft_transfer_call '{ - "receiver_id": "amm", - "amount": "5000000000000000000000000", - "msg": "swap:bnna,2" - }' --accountId alice --depositYocto 1 + + ```sh + near call wnear ft_transfer_call '{ + "receiver_id": "amm", + "amount": "5000000000000000000000000", + "msg": "swap:bnna,2" + }' --accountId alice --depositYocto 1 + ``` During the `ft_transfer_call` call, `wnear` does the following: From 91bab9782aa63c86b113ed2ecc569cd8a864570b Mon Sep 17 00:00:00 2001 From: Chad Ostrowski <221614+chadoh@users.noreply.github.com> Date: Tue, 20 Dec 2022 14:08:45 -0500 Subject: [PATCH 094/150] fix: Fixed the argument naming (owner_id -> previous_owner_id) for `nft_resolve_transfer` to align with the near-sdk-rs and near-sdk-js (#238) --- specs/Standards/Tokens/NonFungibleToken/Core.md | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/specs/Standards/Tokens/NonFungibleToken/Core.md b/specs/Standards/Tokens/NonFungibleToken/Core.md index bd296965f..717e15ffa 100644 --- a/specs/Standards/Tokens/NonFungibleToken/Core.md +++ b/specs/Standards/Tokens/NonFungibleToken/Core.md @@ -82,8 +82,6 @@ function nft_transfer( memo: string|null, ) {} -// Returns `true` if the token was transferred from the sender's account. - // Transfer token and call a method on a receiver contract. A successful // workflow will end in a success execution outcome to the callback on the NFT // contract at the method `nft_resolve_transfer`. @@ -155,7 +153,7 @@ The following behavior is required, but contract authors may name this function // `owner_id` // // Arguments: -// * `owner_id`: the original owner of the NFT. +// * `previous_owner_id`: the original owner of the NFT. // * `receiver_id`: the `receiver_id` argument given to `nft_transfer_call` // * `token_id`: the `token_id` argument given to `nft_transfer_call` // * `approved_account_ids` (optional): if using Approval Management, contract MUST provide @@ -164,7 +162,7 @@ The following behavior is required, but contract authors may name this function // // Returns true if token was successfully transferred to `receiver_id`. function nft_resolve_transfer( - owner_id: string, + previous_owner_id: string, receiver_id: string, token_id: string, approved_account_ids: null|Record, From c7ff808082a2e85857b6daedd286581a1639e8fd Mon Sep 17 00:00:00 2001 From: Ben Sayeg Date: Tue, 20 Dec 2022 14:14:23 -0500 Subject: [PATCH 095/150] refactor: Updated Transactions page in the nomicon fixing a few typos and grammar (#337) --- specs/ChainSpec/Transactions.md | 39 +++++++++++++++++---------------- 1 file changed, 20 insertions(+), 19 deletions(-) diff --git a/specs/ChainSpec/Transactions.md b/specs/ChainSpec/Transactions.md index de7402a6c..710d50228 100644 --- a/specs/ChainSpec/Transactions.md +++ b/specs/ChainSpec/Transactions.md @@ -3,11 +3,11 @@ A client creates a transaction, computes the transaction hash and signs this hash to get a signed transaction. Now this signed transaction can be sent to a node. -When a node receives a new signed transaction, it validates the transaction (if the node tracks the shard) and gossips it to the peers. Eventually, the valid transaction is added to a transaction pool. +When a node receives a new signed transaction, it validates the transaction (if the node tracks the shard) and gossips about it to all its peers. Eventually, the valid transaction is added to a transaction pool. -Every validating node has its own transaction pool. The transaction pool maintains transactions that were not yet discarded and not yet included into the chain. +Every validating node has its own transaction pool. The transaction pool maintains transactions that were either not yet discarded, or not yet included onto the chain. -Before producing a chunk transactions are ordered and validated again. This is done to produce chunks with only valid transactions. +Before producing a chunk, transactions are ordered and validated again. This is done to produce chunks with only valid transactions. ## Transaction ordering @@ -24,13 +24,13 @@ The valid order of the transactions in a chunk is the following: Note: -- the order within a batch is undefined. Each node should use a unique secret seed for that ordering to users from finding the lowest keys to get advantage of every node. +- the order within a batch is undefined. Each node should use a unique secret seed for that ordering to prevent users from finding the lowest keys, and then using that information to take advantage of every node. -Transaction pool provides a draining structure that allows to pull transactions in a proper order. +Transaction pool provides a draining structure that allows it to pull transactions in a proper order. ## Transaction validation -The transaction validation happens twice, once before adding to the transaction pool, next before adding to a chunk. +The transaction validation happens twice, once before adding it to the transaction pool, then before adding it to a chunk. ### Before adding to a transaction pool @@ -38,13 +38,14 @@ This is done to quickly filter out transactions that have an invalid signature o ### Before adding to a chunk -A chunk producer has to create a chunk with valid and ordered transactions up to some limits. -One limit is the maximum number of transactions, another is the total gas burnt for transactions. +A chunk producer has to create a chunk with valid and ordered transactions limited by two criteria: + - the maximum number of transactions for a chunk. + - the total gas burnt for transactions within a chunk. -To order and filter transactions, chunk producer gets a pool iterator and passes it to the runtime adapter. +To order and filter transactions, the chunk producer gets a pool iterator and passes it to the runtime adapter. The runtime adapter pulls transactions one by one. -The valid transactions are added to the result, invalid transactions are discarded. -Once the limit is reached, all the remaining transactions from the iterator are returned back to the pool. +The valid transactions are added to the result; invalid transactions are discarded. +Once one of the chunk limits is reached, all the remaining transactions from the iterator are returned back to the pool. ## Pool iterator @@ -122,9 +123,9 @@ sorted_groups: [], The first group to be selected is for key `("A", "a")`, the pool iterator sorts transactions by nonces and returns the mutable references to the group. Sorted nonces are: `[1, 1, 2, 2, 3]`. Runtime adapter pulls `1`, then `1`, and then `2`. Both transactions with nonce `1` are invalid because of odd nonce. -Transaction with nonce `2` is added to the list of valid transactions. +Transaction with nonce `2` is even, and since we don't know of any previous nonces, it is valid, and therefore added to the list of valid transactions. -The transaction group is dropped and the pool iterator wrapper becomes the following: +Since the runtime adapter found a valid transaction, the transaction group is dropped, and the pool iterator wrapper becomes the following: ``` pool: { @@ -141,7 +142,7 @@ sorted_groups: [ ##### Transaction #2 -The next group is for key `("B", "b")`, the pool iterator sorts transactions by nonces and returns the mutable references to the group. Sorted nonces are: +The next group is for key `("B", "b")`, the pool iterator sorts transactions by nonce and returns the mutable references to the group. Sorted nonces are: `[13, 14]`. Runtime adapter pulls `13`, then `14`. The transaction with nonce `13` is invalid because of odd nonce. Transaction with nonce `14` is added to the list of valid transactions. @@ -185,7 +186,7 @@ The next group is for key `("A", "c")`, the pool iterator sorts transactions by It's a valid transaction, so it's added to the list of valid transactions. -The transaction group is dropped, so the pool iterator drops it completely: +Again, the transaction group is dropped, it's empty, so the pool iterator drops it completely: ``` pool: { @@ -208,7 +209,7 @@ The new nonce has to be larger than the previous nonce, so this transaction is i The transaction with nonce `3` is invalid because of odd nonce. -No valid transactions is added for this group. +No valid transactions are added for this group. The transaction group is dropped, it's empty, so the pool iterator drops it completely: @@ -239,7 +240,7 @@ When runtime adapter tries to pull the next group, the pool iterator returns `No ##### Dropping iterator -If the iterator was not fully drained, but some transactions still remained. They would be reinserted back into the pool. +If the iterator was not fully drained, but some transactions still remained, they would be reinserted back into the pool. ##### Chunk Transactions @@ -270,12 +271,12 @@ The valid transactions are: ("A", "c", 2), ``` -In total there were only 3 valid transactions, that resulted in one batch. +In total there were only 3 valid transactions that resulted in one batch. ### Order validation Other validators need to check the order of transactions in the produced chunk. -It can be done in linear time, using a greedy algorithm. +It can be done in linear time using a greedy algorithm. To select a first batch we need to iterate over transactions one by one until we see a transaction with the key that we've already included in the first batch. From 9aca1ba52c3f8b5ec68b6698b1afb6e741bb8982 Mon Sep 17 00:00:00 2001 From: Benjamin Kurrek <57506486+BenKurrek@users.noreply.github.com> Date: Tue, 20 Dec 2022 14:25:45 -0500 Subject: [PATCH 096/150] refactor: Clarified the FunctionCall access key permissions (#361) --- specs/DataStructures/AccessKey.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/specs/DataStructures/AccessKey.md b/specs/DataStructures/AccessKey.md index b18ad4fca..9dca6ae57 100644 --- a/specs/DataStructures/AccessKey.md +++ b/specs/DataStructures/AccessKey.md @@ -15,7 +15,7 @@ pub struct AccessKey { } ``` -There are 2 types of `AccessKeyPermission` in Near currently: `FullAccess` and `FunctionCall`. `FullAccess` grants permission to request any action on an account like [DeployContract](Transaction.md#DeployContract), [Transfer](Transaction.md#Transfer) tokens to other account, calling functions on smart contracts [FunctionCall](Transaction.md#FunctionCall), [Stake](Transaction.md#Stake) and even delete accounts [DeleteAccountAction](Transaction.md#DeleteAccountAction). `FullAccess` also allows managing access keys. `AccessKeyPermission::FunctionCall` is limited to only having permission to call non-payable methods on contracts. +There are 2 types of `AccessKeyPermission` in NEAR currently: `FullAccess` and `FunctionCall`. `FullAccess` grants permissions to issue any action on the account. This includes [DeployContract](../RuntimeSpec/Actions.md#DeployContractAction), [Transfer](../RuntimeSpec/Actions.md#TransferAction) tokens, call functions [FunctionCall](../RuntimeSpec/Actions.md#FunctionCallAction), [Stake](../RuntimeSpec/Actions.md#StakeAction) and even permission to delete the account [DeleteAccountAction](../RuntimeSpec/Actions.md#DeleteAccountAction). `FunctionCall` on the other hand, **only** grants permission to call any or a specific set of methods on one given contract. It has an allowance of $NEAR that can be spent on **GAS and transaction fees only**. Function call access keys **cannot** be used to transfer $NEAR. ```rust pub enum AccessKeyPermission { @@ -26,7 +26,7 @@ pub enum AccessKeyPermission { ## AccessKeyPermission::FunctionCall -Grants limited permission to make [FunctionCall](Transaction.md#FunctionCall) to a specified `receiver_id` and methods of a particular contract with a limit of allowed balance to spend. +Grants limited permission to make [FunctionCall](../RuntimeSpec/Actions.md#FunctionCall) to a specified `receiver_id` and methods of a particular contract with a limit of allowed balance to spend. ```rust pub struct FunctionCallPermission { From 87463e232a452c870c6d1470c4cc655e2d0b8c9d Mon Sep 17 00:00:00 2001 From: Blas Rodriguez Irizar Date: Tue, 20 Dec 2022 16:29:45 -0300 Subject: [PATCH 097/150] refactor: Nits on NEP template (#373) --- nep-0000-template.md | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/nep-0000-template.md b/nep-0000-template.md index b1b631ced..5769a8bb7 100644 --- a/nep-0000-template.md +++ b/nep-0000-template.md @@ -29,10 +29,10 @@ Explain the proposal as if it was already implemented and you were teaching it t - Introducing new named concepts. - Explaining the feature largely in terms of examples. -- If feature introduces new abstractions, explaining how users and/or developers should *think* about it; +- If the feature introduces new abstractions, explaining how users and/or developers should _think_ about it; - If applicable, describe the differences between the existing functionality. -For user-facing NEPs this section should focus on user stories. +For user-facing NEPs, this section should focus on user stories. ## Reference Implementation (Required for Protocol Working Group proposals, optional for other categories) @@ -47,11 +47,11 @@ The section should return to the examples given in the previous section, and exp ## Security Implications (Optional) -If there are security concerns in relation to the NEP, those concerns should be explicitly written out to make sure reviewers of the NEP are aware of them. +If there are security concerns concerning the NEP, those concerns should be explicitly written out to make sure reviewers of the NEP are aware of them. ## Drawbacks (Optional) -Why should we *not* do this? +Why should we **not** do this? ## Unresolved Issues (Optional) @@ -65,10 +65,10 @@ Think about what the natural extension and evolution of your proposal would be and how it would affect the project as a whole in a holistic way. Try to use this section as a tool to more fully consider all possible interactions with the project in your proposal. -Also consider how the this all fits into the roadmap for the project +Also, consider how all fits into the roadmap for the project and of the relevant sub-team. -This is also a good place to "dump ideas", if they are out of scope for the +This is also a good place to "dump ideas"; if they are out of scope for the NEP you are writing but otherwise related. If you have tried and cannot think of any future possibilities, @@ -80,6 +80,7 @@ in the section on motivation or rationale in this or subsequent NEPs. The section merely provides additional information. ## Copyright + [copyright]: #copyright Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). From 93be7a8d44aa54da66cb5412d8c860d5876b234f Mon Sep 17 00:00:00 2001 From: mzhangmzz <34969888+mzhangmzz@users.noreply.github.com> Date: Mon, 9 Jan 2023 17:39:23 -0500 Subject: [PATCH 098/150] refactor: Remove specs/Economics/README.md (#444) --- .../EpochManager/EpochManager.md | 4 +- specs/Economics/Economic.md | 52 +--- specs/Economics/README.md | 226 ------------------ specs/GenesisConfig/GenesisConfig.md | 2 +- specs/README.md | 2 +- specs/RuntimeSpec/ApplyingChunk.md | 4 +- 6 files changed, 14 insertions(+), 276 deletions(-) delete mode 100644 specs/Economics/README.md diff --git a/specs/BlockchainLayer/EpochManager/EpochManager.md b/specs/BlockchainLayer/EpochManager/EpochManager.md index 9492aea17..6efb1b24f 100644 --- a/specs/BlockchainLayer/EpochManager/EpochManager.md +++ b/specs/BlockchainLayer/EpochManager/EpochManager.md @@ -73,7 +73,7 @@ the following way: then its reward for epoch `T` is automatically added to the proposal. The adjusted set of proposals is used to compute the seat price, and determine `validators`,`block_producers_settlement`, -`chunk_producers_settlement`sets. This algorithm is described in [Economics](../../Economics/README.md#validator-selection). +`chunk_producers_settlement`sets. This algorithm is described in [Economics](../../Economics/Economic.md#validator-selection). ### Validator reward -Rewards calculation is described in the [Economics](../../Economics/README.md#rewards-calculation) section. +Rewards calculation is described in the [Economics](../../Economics/Economic.md#rewards-calculation) section. diff --git a/specs/Economics/Economic.md b/specs/Economics/Economic.md index 82a9584c2..1436faf21 100644 --- a/specs/Economics/Economic.md +++ b/specs/Economics/Economic.md @@ -46,11 +46,12 @@ The protocol sets a ceiling for the maximum issuance of tokens, and dynamically | Name | Description | | - | - | -| `reward[t]` | `totalSupply[t]` * ((`1 + REWARD_PCT_PER_YEAR`) ** (`1/EPOCHS_A_YEAR`) - `1`) | +| `reward[t]` | `totalSupply[t]` * `REWARD_PCT_PER_YEAR` * `epochTime[t]` / `NUM_SECONDS_IN_A_YEAR` | | `epochFee[t]` | `sum([(1 - DEVELOPER_PCT_PER_YEAR) * block.txFee + block.stateFee for block in epoch[t]])` | | `issuance[t]` | The amount of token issued at a certain epoch[t], `issuance[t] = reward[t] - epochFee[t]` | -Where `totalSupply[t]` is the total number of tokens in the system at a given time *t*. +Where `totalSupply[t]` is the total number of tokens in the system at a given time *t* and `epochTime[t]` is the +duration of the epoch in seconds. If `epochFee[t] > reward[t]` the issuance is negative, thus the `totalSupply[t]` decreases in given epoch. ## Transaction Fees @@ -110,17 +111,6 @@ NEAR validators provide their resources in exchange for a reward `epochReward[t] ### Validator Selection -| Name | Description | -| - | - | -| `proposals: Proposal[]` | The array of all new staking transactions that have happened during the epoch (if one account has multiple only last one is used) | -| `current_validators` | The array of all existing validators during the epoch | -| `epoch[T]` | The epoch when validator[v] is selected from the `proposals` auction array | -| `seat_price` | The minimum stake needed to become validator in epoch[T] | -| `stake[v]` | The amount in NEAR tokens staked by validator[v] during the auction at the end of epoch[T-2], minus `INCLUSION_FEE` | -| `shard[v]` | The shard is randomly assigned to validator[v] at epoch[T-1], such that its node can download and sync with its state | -| `num_allocated_seats[v]` | Number of seats assigned to validator[v], calculated from stake[v]/seatPrice | -| `validatorAssignments` | The resulting ordered array of all `proposals` with a stake higher than `seatPrice` | - ```rust struct Proposal { account_id: AccountId, @@ -130,40 +120,14 @@ struct Proposal { ``` During the epoch, outcome of staking transactions produce `proposals`, which are collected, in the form of `Proposal`s. +There are separate proposals for block producers and chunk-only producers, see [Selecting Chunk and Block Producers](../ChainSpec/SelectingBlockProducers.md). +for more information. At the end of every epoch `T`, next algorithm gets executed to determine validators for epoch `T + 2`: -1. For every validator in `current_validators` determine `num_blocks_produced`, `num_chunks_produced` based on what they produced during the epoch. +1. For every chunk/block producer in `epoch[T]` determine `num_blocks_produced`, `num_chunks_produced` based on what they produced during the epoch. 2. Remove validators, for whom `num_blocks_produced < num_blocks_expected * BLOCK_PRODUCER_KICKOUT_THRESHOLD` or `num_chunks_produced < num_chunks_expected * CHUNK_PRODUCER_KICKOUT_THRESHOLD`. -3. Add validators from `proposals`, if validator is also in `current_validators`, considered stake of the proposal is `0 if proposal.stake == 0 else proposal.stake + reward[proposal.account_id]`. -4. Find seat price `seat_price = findSeatPrice(current_validators - kickedout_validators + proposals, num_seats)`, where each validator gets `floor(stake[v] / seat_price)` seats and `seat_price` is highest integer number such that total number of seats is at least `num_seats`. -5. Filter validators and proposals to only those with stake greater or equal than seat price. -6. For every validator, replicate them by number of seats they get `floor(stake[v] / seat_price)`. -7. Randomly shuffle (TODO: define random number sampler) with seed from randomness generated on the last block of current epoch (via `VRF(block_producer.private_key, block_hash)`). -8. Cut off all seats which are over the `num_seats` needed. -9. Use this set for block producers and shifting window over it as chunk producers. - -```python -def findSeatPrice(stakes, num_seats): - """Find seat price given set of stakes and number of seats required. - - Seat price is highest integer number such that if you sum `floor(stakes[i] / seat_price)` it is at least `num_seats`. - """ - stakes = sorted(stakes) - total_stakes = sum(stakes) - assert total_stakes >= num_seats, "Total stakes should be above number of seats" - left, right = 1, total_stakes + 1 - while True: - if left == right - 1: - return left - mid = (left + right) // 2 - sum = 0 - for stake in stakes: - sum += stake // mid - if sum >= num_seats: - left = mid - break - right = mid -``` +3. Collect chunk-only and block producer `proposals`, if validator was also a validator in `epoch[T]`, considered stake of the proposal is `0 if proposal.stake == 0 else proposal.stake + reward[proposal.account_id]`. +4. Use the chunk/block producer selection algorithms outlined in [Selecting Chunk and Block Producers](../ChainSpec/SelectingBlockProducers.md). ### Validator Rewards Calculation diff --git a/specs/Economics/README.md b/specs/Economics/README.md deleted file mode 100644 index c9bc8018b..000000000 --- a/specs/Economics/README.md +++ /dev/null @@ -1,226 +0,0 @@ -# Economics - -**This is under heavy development** - -## Units - -| Name | Value | -| - | - | -| yoctoNEAR | smallest undividable amount of native currency *NEAR*. | -| NEAR | `10**24` yoctoNEAR | -| block | smallest on-chain unit of time | -| gas | unit to measure usage of blockchain | - -## General Parameters - -| Name | Value | -| - | - | -| `INITIAL_SUPPLY` | `10**33` yoctoNEAR | -| `MIN_GAS_PRICE` | `10**5` yoctoNEAR | -| `REWARD_PCT_PER_YEAR` | `0.05` | -| `EPOCH_LENGTH` | `43,200` blocks | -| `EPOCHS_A_YEAR` | `730` epochs | -| `INITIAL_MAX_STORAGE` | `10 * 2**40` bytes == `10` TB | -| `TREASURY_PCT` | `0.1` | -| `TREASURY_ACCOUNT_ID` | `treasury` | -| `CONTRACT_PCT` | `0.3` | -| `INVALID_STATE_SLASH_PCT` | `0.05` | -| `ADJ_FEE` | `0.001` | -| `TOTAL_SEATS` | `100` | -| `ONLINE_THRESHOLD_MIN` | `0.9` | -| `ONLINE_THRESHOLD_MAX` | `0.99` | -| `BLOCK_PRODUCER_KICKOUT_THRESHOLD` | `0.9` | -| `CHUNK_PRODUCER_KICKOUT_THRESHOLD` | `0.6` | - -## General Variables - -| Name | Description | Initial value | -| - | - | - | -| `totalSupply[t]` | Total supply of NEAR at given epoch[t] | `INITIAL_SUPPLY` | -| `gasPrice[t]` | The cost of 1 unit of *gas* in NEAR tokens (see Transaction Fees section below) | `MIN_GAS_PRICE` | -| `storageAmountPerByte[t]` | keeping constant, `INITIAL_SUPPLY / INITIAL_MAX_STORAGE` | `~9.09 * 10**19` yoctoNEAR | - -## Issuance - -The protocol sets a ceiling for the maximum issuance of tokens, and dynamically decreases this issuance depending on the amount of total fees in the system. - -| Name | Description | -| - | - | -| `reward[t]` | `totalSupply[t]` * `REWARD_PCT_PER_YEAR` * `epochTime[t]` / `NUM_SECONDS_IN_A_YEAR` | -| `epochFee[t]` | `sum([(1 - DEVELOPER_PCT_PER_YEAR) * block.txFee + block.stateFee for block in epoch[t]])` | -| `issuance[t]` | The amount of token issued at a certain epoch[t], `issuance[t] = reward[t] - epochFee[t]` | - -Where `totalSupply[t]` is the total number of tokens in the system at a given time *t* and `epochTime[t]` is the -duration of the epoch in seconds. -If `epochFee[t] > reward[t]` the issuance is negative, thus the `totalSupply[t]` decreases in given epoch. - -## Transaction Fees - -Each transaction before inclusion must buy gas enough to cover the cost of bandwidth and execution. - -Gas unifies execution and bytes of bandwidth usage of blockchain. Each WASM instruction or pre-compiled function gets assigned an amount of gas based on measurements on common-denominator computer. Same goes for weighting the used bandwidth based on general unified costs. For specific gas mapping numbers see [???](#). - -Gas is priced dynamically in `NEAR` tokens. At each block `t`, we update `gasPrice[t] = gasPrice[t - 1] * (gasUsed[t - 1] / gasLimit[t - 1] - 0.5) * ADJ_FEE`. - -Where `gasUsed[t] = sum([sum([gas(tx) for tx in chunk]) for chunk in block[t]])`. -`gasLimit[t]` is defined as `gasLimit[t] = gasLimit[t - 1] + validatorGasDiff[t - 1]`, where `validatorGasDiff` is parameter with which each chunk producer can either increase or decrease gas limit based on how long it to execute the previous chunk. `validatorGasDiff[t]` can be only within `±0.1%` of `gasLimit[t]` and only if `gasUsed[t - 1] > 0.9 * gasLimit[t - 1]`. - -## State Stake - -Amount of `NEAR` on the account represents right for this account to take portion of the blockchain's overall global state. Transactions fail if account doesn't have enough balance to cover the storage required for given account. - -```python -def check_storage_cost(account): - # Compute requiredAmount given size of the account. - requiredAmount = sizeOf(account) * storageAmountPerByte - return Ok() if account.amount + account.locked >= requiredAmount else Error(requiredAmount) - -# Check when transaction is received to verify that it is valid. -def verify_transaction(tx, signer_account): - # ... - # Updates signer's account with the amount it will have after executing this tx. - update_post_amount(signer_account, tx) - result = check_storage_cost(signer_account) - # If enough balance OR account is been deleted by the owner. - if not result.ok() or DeleteAccount(tx.signer_id) in tx.actions: - assert LackBalanceForState(signer_id: tx.signer_id, amount: result.err()) - -# After account touched / changed, we check it still has enough balance to cover it's storage. -def on_account_change(block_height, account): - # ... execute transaction / receipt changes ... - # Validate post-condition and revert if it fails. - result = check_storage_cost(sender_account) - if not result.ok(): - assert LackBalanceForState(signer_id: tx.signer_id, amount: result.err()) -``` - -Where `sizeOf(account)` includes size of `account_id`, `account` structure and size of all the data stored under the account. - -Account can end up with not enough balance in case it gets slashed. Account will become unusable as all originating transactions will fail (including deletion). -The only way to recover it in this case is by sending extra funds from a different accounts. - -## Validators - -NEAR validators provide their resources in exchange for a reward `epochReward[t]`, where [t] represents the considered epoch - -| Name | Description | -| - | - | -| `epochReward[t]` | `= coinbaseReward[t] + epochFee[t]` | -| `coinbaseReward[t]` | The maximum inflation per epoch[t], as a function of `REWARD_PCT_PER_YEAR / EPOCHS_A_YEAR` | - - -### Validator Selection - -```rust -struct Proposal { - account_id: AccountId, - stake: Balance, - public_key: PublicKey, -} -``` - -During the epoch, outcome of staking transactions produce `proposals`, which are collected, in the form of `Proposal`s. -There are separate proposals for block producers and chunk-only producers, see [Selecting Chunk and Block Producers](../ChainSpec/SelectingBlockProducers.md). -for more information. -At the end of every epoch `T`, next algorithm gets executed to determine validators for epoch `T + 2`: - -1. For every chunk/block producer in `epoch[T]` determine `num_blocks_produced`, `num_chunks_produced` based on what they produced during the epoch. -2. Remove validators, for whom `num_blocks_produced < num_blocks_expected * BLOCK_PRODUCER_KICKOUT_THRESHOLD` or `num_chunks_produced < num_chunks_expected * CHUNK_PRODUCER_KICKOUT_THRESHOLD`. -3. Collect chunk-only and block producer `proposals`, if validator was also a validator in `epoch[T]`, considered stake of the proposal is `0 if proposal.stake == 0 else proposal.stake + reward[proposal.account_id]`. -4. Use the chunk/block producer selection algorithms outlined in [Selecting Chunk and Block Producers](../ChainSpec/SelectingBlockProducers.md). - -### Validator Rewards Calculation - -Note: all calculations are done in Rational numbers. - -Total reward every epoch `t` is equal to: -```python -total_reward[t] = floor(totalSupply * max_inflation_rate * num_blocks_per_year / epoch_length) -``` - -where `max_inflation_rate`, `num_blocks_per_year`, `epoch_length` are genesis parameters and `totalSupply` is -taken from the last block in the epoch. - -After that a fraction of the reward goes to the treasury and the remaining amount will be used for computing validator rewards: -```python -treasury_reward[t] = floor(reward[t] * protocol_reward_rate) -validator_reward[t] = total_reward[t] - treasury_reward[t] -``` - -The validator reward is split between block producers and chunk only producers. A fraction `f` is given to block producers, -while the remainder is given to chunk-only producers (i.e. validators who were not block producers). - -Validators that didn't meet the threshold for either blocks or chunks get kicked out and don't get any reward, otherwise uptime -of a validator is computed: - -```python -pct_online[t][j] = (num_produced_blocks[t][j] / expected_produced_blocks[t][j] + num_produced_chunks[t][j] / expected_produced_chunks[t][j]) / 2 -if pct_online > ONLINE_THRESHOLD: - uptime[t][j] = min(1, (pct_online[t][j] - ONLINE_THRESHOLD_MIN) / (ONLINE_THRESHOLD_MAX - ONLINE_THRESHOLD_MIN)) -else: - uptime[t][j] = 0 -``` - -Where `expected_produced_blocks` and `expected_produced_chunks` is the number of blocks and chunks respectively that is expected to be produced by given validator `j` in the epoch `t`. - -The specific `validator[t][j]` reward for epoch `t` is then proportional to the fraction of stake of this validator from total stake: - -```python -blockProducerReward[t][j] = floor(uptime[t][j] * stake[t][j] * f * validator_reward[t] / total_stake[t]) -chunkOnlyProducerReward[t][j] = floor(uptime[t][j] * stake[t][j] * (1 - f) * validator_reward[t] / total_stake[t]) -``` - -### Slashing - -#### ChunkProofs - -```python -# Check that chunk is invalid, because the proofs in header don't match the body. -def chunk_proofs_condition(chunk): - # TODO - -# At the end of the epoch, run update validators and -# determine how much to slash validators. -def end_of_epoch_update_validators(validators): - # ... - for validator in validators: - if validator.is_slashed: - validator.stake -= INVALID_STATE_SLASH_PCT * validator.stake -``` - -#### ChunkState - -```python -# Check that chunk header post state root is invalid, -# because the execution of previous chunk doesn't lead to it. -def chunk_state_condition(prev_chunk, prev_state, chunk_header): - # TODO - -# At the end of the epoch, run update validators and -# determine how much to slash validators. -def end_of_epoch(..., validators): - # ... - for validator in validators: - if validator.is_slashed: - validator.stake -= INVALID_STATE_SLASH_PCT * validator.stake -``` - -## Protocol Treasury - -Treasury account `TREASURY_ACCOUNT_ID` receives fraction of reward every epoch `t`: - -```python -# At the end of the epoch, update treasury -def end_of_epoch(..., reward): - # ... - accounts[TREASURY_ACCOUNT_ID].amount = treasury_reward[t] -``` - -## Contract Rewards - -Contract account is rewarded with 30% of gas burnt during the execution of its functions. -The reward is credited to the contract account after applying the corresponding receipt with [`FunctionCallAction`](../RuntimeSpec/Actions.md#functioncallaction), gas is converted to tokens using gas price of the current block. - -You can read more about: -- [receipts execution](../RuntimeSpec/Receipts.md); -- [runtime fees](../RuntimeSpec/Fees/Fees.md) with description [how gas is charged](../RuntimeSpec/Fees/Fees.md#gas-tracking). diff --git a/specs/GenesisConfig/GenesisConfig.md b/specs/GenesisConfig/GenesisConfig.md index a2556a81c..17adb9bbd 100644 --- a/specs/GenesisConfig/GenesisConfig.md +++ b/specs/GenesisConfig/GenesisConfig.md @@ -148,5 +148,5 @@ Protocol treasury account ## protocol economics -> For the specific economic specs, refer to [Economics Section](../Economics/README.md). +> For the specific economic specs, refer to [Economics Section](../Economics/Economic.md). diff --git a/specs/README.md b/specs/README.md index 50e91f184..3cca1ff02 100644 --- a/specs/README.md +++ b/specs/README.md @@ -13,7 +13,7 @@ For the overview of the NEAR Protocol, read the following documents in numerical 4. [Chain specification](ChainSpec/) 5. [Runtime specification](RuntimeSpec/) 6. [Network specification](NetworkSpec/NetworkSpec.md) -7. [Economics](Economics/README.md) +7. [Economics](Economics/Economic.md) ## Standards diff --git a/specs/RuntimeSpec/ApplyingChunk.md b/specs/RuntimeSpec/ApplyingChunk.md index d3ce047c0..38c0434b5 100644 --- a/specs/RuntimeSpec/ApplyingChunk.md +++ b/specs/RuntimeSpec/ApplyingChunk.md @@ -17,9 +17,9 @@ and produces following outputs: ## Processing order -* If this is first block of an epoch, dispense [epoch rewards](../Economics/README.md#validator-rewards-calculation) to validators (in order of *validator_accounts_update.stake_info*) +* If this is first block of an epoch, dispense [epoch rewards](../Economics/Economic.md#validator-rewards-calculation) to validators (in order of *validator_accounts_update.stake_info*) * Slash locked balance for malicious behavior (in order of *validator_accounts_update.slashing_info*) -* If [treasury account](../Economics/README.md#protocol-treasury) was not one of validators and this is first block of an epoch, dispense treasury account reward +* If [treasury account](../Economics/Economic.md#protocol-treasury) was not one of validators and this is first block of an epoch, dispense treasury account reward * If this is first block of new version or first block with chunk of new version, apply corresponding migrations * If this block do not have chunk for this shard, end process early * Process [transactions](Transactions.md) (in order of *transactions*) From 3da1c84c631c4ca3ee9bab6f5a09aecf48e24b72 Mon Sep 17 00:00:00 2001 From: Andrei Kashin Date: Wed, 11 Jan 2023 13:57:33 +0000 Subject: [PATCH 099/150] doc: Fix gas price calculation formula and ADJ_FEE (#447) As according to the https://github.com/near/nearcore/blob/master/nearcore/src/config.rs#L139 and the code, the actual formula and value are different --- specs/Economics/Economic.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/specs/Economics/Economic.md b/specs/Economics/Economic.md index 1436faf21..13f7be421 100644 --- a/specs/Economics/Economic.md +++ b/specs/Economics/Economic.md @@ -25,7 +25,7 @@ | `TREASURY_ACCOUNT_ID` | `treasury` | | `CONTRACT_PCT` | `0.3` | | `INVALID_STATE_SLASH_PCT` | `0.05` | -| `ADJ_FEE` | `0.001` | +| `ADJ_FEE` | `0.01` | | `TOTAL_SEATS` | `100` | | `ONLINE_THRESHOLD_MIN` | `0.9` | | `ONLINE_THRESHOLD_MAX` | `0.99` | @@ -60,7 +60,7 @@ Each transaction before inclusion must buy gas enough to cover the cost of bandw Gas unifies execution and bytes of bandwidth usage of blockchain. Each WASM instruction or pre-compiled function gets assigned an amount of gas based on measurements on common-denominator computer. Same goes for weighting the used bandwidth based on general unified costs. For specific gas mapping numbers see [???](#). -Gas is priced dynamically in `NEAR` tokens. At each block `t`, we update `gasPrice[t] = gasPrice[t - 1] * (gasUsed[t - 1] / gasLimit[t - 1] - 0.5) * ADJ_FEE`. +Gas is priced dynamically in `NEAR` tokens. At each block `t`, we update `gasPrice[t] = gasPrice[t - 1] * (1 + (gasUsed[t - 1] / gasLimit[t - 1] - 0.5) * ADJ_FEE)`. Where `gasUsed[t] = sum([sum([gas(tx) for tx in chunk]) for chunk in block[t]])`. `gasLimit[t]` is defined as `gasLimit[t] = gasLimit[t - 1] + validatorGasDiff[t - 1]`, where `validatorGasDiff` is parameter with which each chunk producer can either increase or decrease gas limit based on how long it to execute the previous chunk. `validatorGasDiff[t]` can be only within `±0.1%` of `gasLimit[t]` and only if `gasUsed[t - 1] > 0.9 * gasLimit[t - 1]`. From 75b61c1eb1f5069042ca0d79c1b409d954ad66d7 Mon Sep 17 00:00:00 2001 From: mzhangmzz <34969888+mzhangmzz@users.noreply.github.com> Date: Wed, 11 Jan 2023 09:12:12 -0500 Subject: [PATCH 100/150] fix: Update SelecitonBlockProducers.md to be up to date (#445) #167 is merged but the final implementation we went for chunk-only producers actually diverged from what was described there. This PR updates the block/chunk producers section so our documentation is up to date. --- specs/ChainSpec/SelectingBlockProducers.md | 151 ++++++++------------- 1 file changed, 59 insertions(+), 92 deletions(-) diff --git a/specs/ChainSpec/SelectingBlockProducers.md b/specs/ChainSpec/SelectingBlockProducers.md index 78bf6eaea..532b515db 100644 --- a/specs/ChainSpec/SelectingBlockProducers.md +++ b/specs/ChainSpec/SelectingBlockProducers.md @@ -66,50 +66,41 @@ There are several desiderata for these algorithms: stake (what stake is "relevant" depends on whether the validator is a chunk-only producer or a block producer; more details below). Hence, the algorithm will enforce the condition $(1 - (s_\text{min} / S))^\text{epoch\_length} < \text{PROBABILITY\_NEVER\_SELECTED}$. - -## Algorithm for selecting block producers - + +In mainnet and testnet, `epoch_length` is set to `43200`. Let $\text{PROBABILITY\_NEVER\_SELECTED}=0.001$, +we obtain, $s_\text{min} / S = 160/1000,000$. + +## Algorithm for selecting block and chunk producers +A potential validator cannot specify whether they want to become a block producer or a chunk-only producer. +There is only one type of proposal. The same algorithm is used for selecting block producers and chunk producers, +but with different thresholds. The threshold for becoming block producers is higher, so if a node is selected as a block +producer, it will also be a chunk producer, but not the other way around. Validators who are selected as chunk producers +but not block producers are chunk-only producers. + +### select_validators ### Input - -* `MAX_NUM_BP: u16` (see Assumptions above for definition) -* `epoch_length: u64` -* `PROBABILITY_NEVER_SELECTED: Ratio` - - `Ratio` means a fraction where the numerator and denominator are represented by unsigned - 128-bit numbers -* `block_producer_proposals: Vec` (proposed stakes for the next epoch from nodes sending +* `max_num_validators: u16` max number of validators to be selected +* `min_stake_fraction: Ratio` minimum stake ratio for selected validator +* `validator_proposals: Vec` (proposed stakes for the next epoch from nodes sending staking transactions) - - Note: there are separate actions to propose to be a chunk-only producer or a block producer. - Here only block producer proposals are considered. ### Output -* `block_producers: Vec` (chosen block producers for the next epoch) -* `block_producer_sampler: WeightedIndex` - - Data structure to allow $O(1)$ sampling from the block producers with probability - proportional to their stake - - This structure will be based on the - [WeightedIndex](https://rust-random.github.io/rand/rand/distributions/weighted/alias_method/struct.WeightedIndex.html) - implementation (see a description of [Vose's Alias - Method](https://en.wikipedia.org/wiki/Alias_method) for details) +* `validators: Vec` ### Steps ```python sorted_proposals = - sorted_descending(block_producer_proposals, key=lambda v: (v.stake, v.account_id)) - -# smallest value of s_min / S such that -# (1 - (s_min / S))^epoch_length < PROBABILITY_NEVER_SELECTED -min_stake_fraction = - 1 - PROBABILITY_NEVER_SELECTED^(1/epoch_length) + sorted_descending(validator_proposals, key=lambda v: (v.stake, v.account_id)) total_stake = 0 -block_producers = [] -for v in sorted_proposals[0:MAX_NUM_BP]: +validators = [] +for v in sorted_proposals[0:max_num_validators]: total_stake += v.stake if (v.stake / total_stake) > min_stake_fraction: - block_producers.append(v) + validators.append(v) else: break @@ -118,10 +109,39 @@ block_producer_sampler = WeightedIndex([v.stake for v in block_producers]) return (block_producers, block_producer_sampler) ``` -## Algorithm for assigning chunk producers to shards +### Algorithm for selecting block producers +### Input +* `MAX_NUM_BP: u16` Max number of block producers, see Assumptions +* `min_stake_fraction: Ratio` $s_\text{min} / S$, see Assumptions +* `validator_proposals: Vec` (proposed stakes for the next epoch from nodes sending + staking transactions) -Note: no algorithm for assigning block producers to shards is needed because we are working within -"Simple Nightshade" where block producers track all shards. +```python +select_validators(MAX_NUM_BP, min_stake_fraction, validator_proposals) +``` + +### Algorithm for selecting chunk producers +### Input +* `MAX_NUM_CP: u16` max number of chunk producers, see Assumptions` +* `min_stake_fraction: Ratio` $s_\text{min} / S$, see Assumptions +* `num_shards: u64` number of shards +* `validator_proposals: Vec` (proposed stakes for the next epoch from nodes sending + staking transactions) + +```python +select_validators(MAX_NUM_CP, min_stake_fraction/num_shards, validator_proposals) +``` +The reasoning for using `min_stake_fraction/num_shards` as the threshold here is that +we will assign chunk producers to shards later and the algorithm (described below) will try to assign +them in a way that the total stake in each shard is distributed as evenly as possible. +So the total stake in each shard will be roughly be `total_stake_all_chunk_producers / num_shards`. + +## Algorithm for assigning chunk producers to shards +Note that block producers are a subset of chunk producers, so this algorithm will also assign block producers +to shards. This also means that a block producer may only be assigned to a subset of shards. For the security of +the protocol, all block producers must track all shards, even if they are not assigned to produce chunks for all shards. +We enforce that in the implementation level, not the protocol level. A validator node will panic if it doesn't track all +shards. ### Input @@ -160,67 +180,14 @@ the change to Simple Nightshade, so it assumes we are assigning block producers the same algorithm works to assign chunk producers to shards; it is only a matter of renaming variables referencing "block producers" to reference "chunk producers" instead. -## Algorithm for selecting chunk producers - -### Input - -* `MAX_NUM_BP: u16` -* `MAX_NUM_CP: u16` -* `epoch_length: u64` -* `PROBABILITY_NEVER_SELECTED: Ratio` -* `num_shards: usize` -* `min_validators_per_shard: usize` -* `block_producers_proposals: Vec` -* `chunk_only_producer_proposals: Vec` - -### Output - -* `chunk_producers: Vec` (chosen chunk producers for the next epoch) -* `validator_shard_assignments: Vec>` - - $i$-th element gives the validators assigned to shard $i$ -* `chunk_producer_sampler: Vec` - -### Steps - -```python -# Group both sets of proposals together since all block producers -# can also serve as chunk producers. -validator_proposals = block_producers_proposals + chunk_only_producer_proposals -sorted_proposals = - sorted_descending(validator_proposals, key=lambda v: (v.stake, v.account_id)) - -# smallest value of s_min / S such that -# (1 - (s_min / S))^epoch_length < PROBABILITY_NEVER_SELECTED -min_stake_fraction = - 1 - PROBABILITY_NEVER_SELECTED^(1/epoch_length) - -# we assume the stake from chunk producers will be roughly -# evenly distributed among all the shards, so the stake fraction -# we care about is really smaller than the quantity above. -min_stake_fraction /= num_shards - -chunk_producers = [] -total_stake = 0 -for v in sorted_proposals[0:(MAX_NUM_BP + MAX_NUM_CP)]: - total_stake += v.stake - if (v.stake / total_stake) > min_stake_fraction: - chunk_producers.append(v) - else: - break - -chunk_producers.sort_descending(key=lambda v: (v.stake, v.account_id)) -# using the algorithm above to assign shards -validator_shard_assignments = - assign_chunk_producers(chunk_producers, num_shards, min_validators_per_shard) - -chunk_producer_sampler = [ - WeightedIndex([v.stake for v in shard_cps]) for shard_cps in validator_shard_assignments -] - -return (chunk_producers, validator_shard_assignments, chunk_producer_sampler) -``` - ## Algorithm for sampling validators proportional to stake +We sample validators with probability proportional to their stake using the following data structure. +* `weighted_sampler: WeightedIndex` + - Allow $O(1)$ sampling + - This structure will be based on the + [WeightedIndex](https://rust-random.github.io/rand/rand/distributions/weighted/alias_method/struct.WeightedIndex.html) + implementation (see a description of [Vose's Alias + Method](https://en.wikipedia.org/wiki/Alias_method) for details) This algorithm is applied using both chunk-only producers and block producers in the subsequent algorithms for selecting a specific block producer and chunk producer at each height. From 3e23a5ebcda68b424297dba8ea1d3689069a3c8a Mon Sep 17 00:00:00 2001 From: Osman Abdelnasir Date: Tue, 24 Jan 2023 17:47:17 +0400 Subject: [PATCH 101/150] feat: add `standards` key to NEP-330 `ContractSourceMetadata` (#351) --- neps/nep-0330.md | 87 ++++++++++++++++++++++++++++--- specs/Standards/SourceMetadata.md | 58 +++++++++++++++++---- 2 files changed, 128 insertions(+), 17 deletions(-) diff --git a/neps/nep-0330.md b/neps/nep-0330.md index ed8840a26..51cbd89d5 100644 --- a/neps/nep-0330.md +++ b/neps/nep-0330.md @@ -1,12 +1,14 @@ --- NEP: 330 Title: Source Metadata -Author: Ben Kurrek +Author: Ben Kurrek , Osman Abdelnasir DiscussionsTo: https://github.com/near/NEPs/discussions/329 -Status: Review +Status: Approved Type: Standards Track Category: Contract +Version: 1.1.0 Created: 27-Feb-2022 +Updated: 13-Jan-2023 --- ## Summary @@ -17,6 +19,8 @@ The contract source metadata is a standard interface that allows auditing and vi There is no trivial way of finding the source code or author of a deployed smart contract. Having a standard that outlines how to view the source code of an arbitrary smart contract creates an environment of openness and collaboration. +Additionally, we would like for wallets and dApps to be able to parse this information and determine which methods they are able to call and render UIs that provide that functionality. + The initial discussion can be found [here](https://github.com/near/NEPs/discussions/329). ## Rationale and alternatives @@ -25,16 +29,23 @@ There is a lot of information that can be held about a contract. Ultimately, we ## Specification -Successful implementations of this standard will introduce a new (`ContractMetadata`) struct that will hold all the necessary information to be queried for. This struct will be kept on the contract level. +Successful implementations of this standard will introduce a new (`ContractSourceMetadata`) struct that will hold all the necessary information to be queried for. This struct will be kept on the contract level. -The metadata will include two optional fields: +The metadata will include three optional fields: - `version`: a string that references the specific commit hash or version of the code that is currently deployed on-chain. This can be included regardless of whether or not the contract is open-sourced and can also be used for organizational purposes. - `link`: a string that references the link to the open-source code. This can be anything such as Github or a CID to somewhere on IPFS. +- `standards`: a list of objects (see type definition below) that enumerates the NEPs supported by the contract. If this extension is supported, it is advised to also include NEP-330 version 1.1.0 in the list (`{standard: "nep330", version: "1.1.0"}`). ```ts type ContractSourceMetadata = { version: string|null, // optional, commit hash being used for the currently deployed wasm. If the contract is not open-sourced, this could also be a numbering system for internal organization / tracking such as "1.0.0" and "2.1.0". - link: string|null, //optional, link to open source code such as a Github repository or a CID to somewhere on IPFS. + link: string|null, // optional, link to open source code such as a Github repository or a CID to somewhere on IPFS. + standards: Standard[]|null, // optional, standards and extensions implemented in the currently deployed wasm e.g. [{standard: "nep330", version: "1.1.0"},{standard: "nep141", version: "1.0.0"}]. +} + +type Standard { + standard: string, // standard name e.g. "nep141" + version: string, // semantic version number of the Standard e.g. "1.0.0" } ``` @@ -51,7 +62,21 @@ As an example, say there was an NFT contract deployed on-chain which was current ```ts type ContractSourceMetadata = { version: "39f2d2646f2f60e18ab53337501370dc02a5661c" - link: "https://github.com/near-examples/nft-tutorial" + link: "https://github.com/near-examples/nft-tutorial", + standards: [ + { + standard: "nep330", + version: "1.1.0" + }, + { + standard: "nep171", + version: "1.0.0" + }, + { + standard: "nep177", + version: "2.0.0" + } + ] } ``` @@ -60,7 +85,21 @@ If someone were to call the view function `contract_metadata`, the contract woul ```bash { version: "39f2d2646f2f60e18ab53337501370dc02a5661c" - link: "https://github.com/near-examples/nft-tutorial" + link: "https://github.com/near-examples/nft-tutorial", + standards: [ + { + standard: "nep330", + version: "1.1.0" + }, + { + standard: "nep171", + version: "1.0.0" + }, + { + standard: "nep177", + version: "2.0.0" + } + ] } ``` @@ -73,15 +112,22 @@ pub struct Contract { pub contract_metadata: ContractSourceMetadata } +// Standard structure +pub struct Standard { + pub standard: String, + pub version: String +} + /// Contract metadata structure pub struct ContractSourceMetadata { pub version: String, pub link: String, + pub standards: Vec } /// Minimum Viable Interface pub trait ContractSourceMetadataTrait { - fn contract_source_metadata(&self) -> ContractMetadata; + fn contract_source_metadata(&self) -> ContractSourceMetadata; } /// Implementation of the view function @@ -97,6 +143,31 @@ impl ContractSourceMetadataTrait for Contract { - By having a standard outlining metadata for an arbitrary contract, any information that pertains on a contract level can be added based on the requests of the developer community. +## Decision Context + +### 1.0.0 - Initial Version + +The initial version of NEP-330 was approved by @jlogelin on Mar 29, 2022. + +### 1.1.0 - Contract Metadata Extension + +The extension NEP-351 that added Contract Metadata to this NEP-330 was approved by Contract Standards Working Group members on January 17, 2023 ([meeting recording](https://youtu.be/pBLN9UyE6AA)). + +#### Benefits + +- Unlocks NEP extensions that otherwise would be hard to integrate into the tooling as it would be guess-based (e.g. see "interface detection" concerns in the Non-transferrable NFT NEP) +- Standardization enables composability as it makes it easier to interact with contracts when you can programmatically check compatibility +- This NEP extension introduces an optional field, so there is no breaking change to the original NEP + +#### Concerns + +| # | Concern | Resolution | Status | +| - | - | - | - | +| 1 | Integer field as a standard reference is limiting as third-party projects may want to introduce their own standards without pushing it through the NEP process | Author accepted the proposed string-value standard reference (e.g. “nep123” instead of just 123, and allow “xyz001” as previously it was not possible to express it) | Resolved | +| 2 | NEP-330 and NEP-351 should be included in the list of the supported NEPs | There seems to be a general agreement that it is a good default, so NEP was updated | Resolved | +| 3 | JSON Event could be beneficial, so tooling can react to the changes in the supported standards | It is outside the scope of this NEP. Also, list of supported standards only changes with contract re-deployment, so tooling can track DEPLOY_CODE events and check the list of supported standards when new code is deployed | Won’t fix | + + ## Copyright [copyright]: #copyright diff --git a/specs/Standards/SourceMetadata.md b/specs/Standards/SourceMetadata.md index 8da02aec7..3090e8817 100644 --- a/specs/Standards/SourceMetadata.md +++ b/specs/Standards/SourceMetadata.md @@ -2,11 +2,7 @@ ## [NEP-330](https://github.com/near/NEPs/blob/master/neps/nep-0330.md) -:::caution -This is part of proposed spec [NEP-330](https://github.com/near/NEPs/blob/master/neps/nep-0330.md) and subject to change. -::: - -Version `1.0.0` +Version `1.1.0` ## Summary @@ -16,6 +12,8 @@ The contract source metadata is a standard interface that allows auditing and vi There is no trivial way of finding the source code or author of a deployed smart contract. Having a standard that outlines how to view the source code of an arbitrary smart contract creates an environment of openness and collaboration. +Additionally, we would like for wallets and dApps to be able to parse this information and determine which methods they are able to call and render UIs that provide that functionality. + The initial discussion can be found [here](https://github.com/near/NEPs/discussions/329). ## Rationale and alternatives @@ -29,11 +27,18 @@ Successful implementations of this standard will introduce a new (`ContractSour The metadata will include two optional fields: - `version`: a string that references the specific commit hash or version of the code that is currently deployed on-chain. This can be included regardless of whether or not the contract is open-sourced and can also be used for organizational purposes. - `link`: a string that references the link to the open-source code. This can be anything such as Github or a CID to somewhere on IPFS. +- `standards`: a list of objects (see type definition below) that enumerates the NEPs supported by the contract. If this extension is supported, it is advised to also include NEP-330 version 1.1.0 in the list (`{standard: "nep330", version: "1.1.0"}`). ```ts type ContractSourceMetadata = { version: string|null, // optional, commit hash being used for the currently deployed wasm. If the contract is not open-sourced, this could also be a numbering system for internal organization / tracking such as "1.0.0" and "2.1.0". - link: string|null, //optional, link to open source code such as a Github repository or a CID to somewhere on IPFS. + link: string|null, // optional, link to open source code such as a Github repository or a CID to somewhere on IPFS. + standards: Standard[]|null, // optional, standards and extensions implemented in the currently deployed wasm e.g. [{standard: "nep330", version: "1.1.0"},{standard: "nep141", version: "1.0.0"}]. +} + +type Standard { + standard: string, // standard name e.g. "nep141" + version: string, // semantic version number of the Standard e.g. "1.0.0" } ``` @@ -50,7 +55,21 @@ As an example, say there was an NFT contract deployed on-chain which was current ```ts type ContractSourceMetadata = { version: "39f2d2646f2f60e18ab53337501370dc02a5661c" - link: "https://github.com/near-examples/nft-tutorial" + link: "https://github.com/near-examples/nft-tutorial", + standards: [ + { + standard: "nep330", + version: "1.1.0" + }, + { + standard: "nep171", + version: "1.0.0" + }, + { + standard: "nep177", + version: "2.0.0" + } + ] } ``` @@ -59,7 +78,21 @@ If someone were to call the view function `contract_metadata`, the contract woul ```bash { version: "39f2d2646f2f60e18ab53337501370dc02a5661c" - link: "https://github.com/near-examples/nft-tutorial" + link: "https://github.com/near-examples/nft-tutorial", + standards: [ + { + standard: "nep330", + version: "1.1.0" + }, + { + standard: "nep171", + version: "1.0.0" + }, + { + standard: "nep177", + version: "2.0.0" + } + ] } ``` @@ -72,10 +105,17 @@ pub struct Contract { pub contract_metadata: ContractSourceMetadata } +// Standard structure +type Standard { + standard: string, // standard name e.g. "nep141" + version: string // semantic version number of the Standard e.g. "1.0.0" +} + /// Contract metadata structure pub struct ContractSourceMetadata { pub version: String, pub link: String, + pub standards: Vec } /// Minimum Viable Interface @@ -94,4 +134,4 @@ impl ContractSourceMetadataTrait for Contract { ## Future possibilities -- By having a standard outlining metadata for an arbitrary contract, any information that pertains on a contract level can be added based on the requests of the developer community. \ No newline at end of file +- By having a standard outlining metadata for an arbitrary contract, any information that pertains on a contract level can be added based on the requests of the developer community. From 1ec32ec388fe8a420d1d58f78f7541a12fadff6b Mon Sep 17 00:00:00 2001 From: Austin Abell Date: Fri, 27 Jan 2023 06:40:03 -0500 Subject: [PATCH 102/150] NEP-418: Proposal to allow attached_deposit in view contexts (#418) --- neps/nep-0418.md | 102 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 102 insertions(+) create mode 100644 neps/nep-0418.md diff --git a/neps/nep-0418.md b/neps/nep-0418.md new file mode 100644 index 000000000..d6788a155 --- /dev/null +++ b/neps/nep-0418.md @@ -0,0 +1,102 @@ +--- +NEP: 0418 +Title: Remove attached_deposit view panic +Author: Austin Abell +DiscussionsTo: https://github.com/nearprotocol/neps/pull/418 +Status: Approved +Type: Standards Track +Category: Tools +Version: 1.0.0 +Created: 18-Oct-2022 +Updated: 27-Jan-2023 +--- + +## Summary + +This proposal is to switch the behavior of the `attached_deposit` host function on the runtime from panicking in view contexts to returning 0. This results in a better devX because instead of having to configure an assertion that there was no attached deposit to a function call only for transactions and not view calls, which is impossible because you can send a transaction to any method, you could just apply this assertion without the runtime aborting in view contexts. + +## Motivation + +This will allow contract SDK frameworks to add the `attached_deposit == 0` assertion for every function on a contract by default. This behavior matches the Solidity/Eth payable modifier and will ensure that funds aren't sent accidentally to a contract in more cases than currently possible. + +This can't be done at a contract level because there is no way of checking if a function call is within view context to call `attached_deposit` conditionally. This means that there is no way of restricting the sending of funds to functions intended to be view only because the abort from within `attached_deposit` can't be caught and ignored from inside the contract. + +Initial discussion: https://near.zulipchat.com/#narrow/stream/295306-pagoda.2Fcontract-runtime/topic/attached_deposit.20view.20error + +## Rationale and alternatives + +The rationale for assigning `0u128` to the pointer (`u64`) passed into `attached_deposit` is that it's the least breaking change. + +The alternative of returning some special value, say `u128::MAX`, is that it would cause some unintended side effects for view calls using the `attached_deposit`. For example, if `attached_deposit` is called within a function, older versions of a contract that do not check the special value will return a result assuming that the attached deposit is `u128::MAX`. This is not a large concern since it would just be a view call, but it might be a bad UX in some edge cases, where returning 0 wouldn't be an issue. + +## Specification + +The error inside `attached_deposit` for view calls will be removed, and for all view calls, `0u128` will be set at the pointer passed in. + +## Reference Implementation + + +Currently, the implementation for `attached_deposit` is as follows: +```rust +pub fn attached_deposit(&mut self, balance_ptr: u64) -> Result<()> { + self.gas_counter.pay_base(base)?; + + if self.context.is_view() { + return Err(HostError::ProhibitedInView { + method_name: "attached_deposit".to_string(), + } + .into()); + } + self.memory_set_u128(balance_ptr, self.context.attached_deposit) +} +``` + +Which would just remove the check for `is_view` to no longer throw an error: + +```rust +pub fn attached_deposit(&mut self, balance_ptr: u64) -> Result<()> { + self.gas_counter.pay_base(base)?; + + self.memory_set_u128(balance_ptr, self.context.attached_deposit) +} +``` + +This assumes that in all cases, `self.context.attached_deposit` is set to 0 in all cases. This can be asserted, or just to be safe, can check if `self.context.is_view()` and set `0u128` explicitly. + +## Security Implications + +This won't have any implications outside of view calls, so this will not affect anything that is persisted on-chain. This only affects view calls. This can only have a negative side effect if a contract is under the assumption that `attached_deposit` will panic in view contexts. The possibility that this is done _and_ has some value connected with a view call result off-chain seems extremely unlikely. + +## Drawbacks + +This has a breaking change of the functionality of `attached_deposit` and affects the behavior of some function calls in view contexts if they use `attached_deposit` and no other prohibited host functions. + +## Future possibilities + +- The Rust SDK, as well as other SDKs, can add the `attached_deposit() == 0` check by default to all methods for safety of use. +- Potentially, other host functions can be allowed where reasonable values can be inferred. For example, `prepaid_gas`, `used_gas` could return 0. + +## Decision Context + +### 1.0.0 - Initial Version + +The initial version of NEP-418 was approved by Tools Working Group members on January 19, 2023 ([meeting recording](https://youtu.be/poVmblmc3L4)). + +#### Benefits + +- This will allow contract SDK frameworks to add the `attached_deposit == 0` assertion for every function on a contract by default. +- This behavior matches the Solidity/Eth payable modifier and will ensure that funds aren't sent accidentally to a contract in more cases than currently possible. +- Given that there is no way of checking if a function call is within view context to call `attached_deposit` conditionally, this NEP only changes a small surface of the API instead of introducing a new host function. + +#### Concerns + +| # | Concern | Resolution | Status | +| - | - | - | - | +| 1 | Proposal potentially triggers the protocol version change | It does not trigger the protocol version change. Current update could be considered a client-breaking change update. | Resolved | +| 2 | The contract can assume that `attached_deposit` will panic in view contexts. | The possibility that this is done _and_ has some value connected with a view call result off-chain seems extremely unlikely. | Won't Fix | +| 3 | Can we assume that in all view calls, the `attached_deposit` in the VMContext always zero? | Yes, there is no way to set `attached_deposit` in view calls context | Resolved | + +## Copyright +[copyright]: #copyright + +Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). From 25e9b0a914e97c4d39105028b4277f337ea0dcbb Mon Sep 17 00:00:00 2001 From: Andrei Kashin Date: Wed, 1 Feb 2023 13:08:46 +0000 Subject: [PATCH 103/150] fix(nomicon): Fix inaccuracies about chunk gas limit (#457) This PR fixes two inaccuracies: - The fact that chunk includes one more receipt after reaching the gas limit - The current gas limit being 1000 TGas --- specs/RuntimeSpec/ApplyingChunk.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/specs/RuntimeSpec/ApplyingChunk.md b/specs/RuntimeSpec/ApplyingChunk.md index 38c0434b5..f9569ab6c 100644 --- a/specs/RuntimeSpec/ApplyingChunk.md +++ b/specs/RuntimeSpec/ApplyingChunk.md @@ -28,8 +28,8 @@ and produces following outputs: then incoming receipts, ordered by *incoming_receipts* order) * Process incoming [receipts](Receipts.md) (ordered by *incoming_receipts*) -When processing receipts we track gas used (including gas used on migrations). If we use up gas limit, we immediately stop to process delayed receipts, and for local and incoming -receipts we add them to delayed receipts) +When processing receipts we track gas used (including gas used on migrations). If we use up gas limit, we finish processing the last receipt and stop to process delayed receipts, and for local +and incoming receipts we add them to delayed receipts. * If any of the delayed receipts were processed or any new receipts were delayed, update indices of first and last unprocessed receipts in state * Remove duplicate validator proposals (for each account we only keep last one in receipts processing order) @@ -38,4 +38,4 @@ Please note that local receipts are receipts generated by transaction where rece ## Delayed receipts -In each block we have maximal amount of Gas we can use to process receipts and migrations, currently 500 TGas. If any incoming or local receipts are not processed due to lack of remaining Gas, they are stored in state with key

TrieKey::DelayedReceipt { id }
where id is unique index for each shard, assigned consecutively. Currently sender does not need to stake any tokens to store delayed receipts. State also contains special key
TrieKey::DelayedReceiptIndices
where first and last ids of delayed receipts not yet processed are stored. +In each block we have maximal amount of Gas we can use to process receipts and migrations, currently 1000 TGas. If any incoming or local receipts are not processed due to lack of remaining Gas, they are stored in state with key
TrieKey::DelayedReceipt { id }
where id is unique index for each shard, assigned consecutively. Currently sender does not need to stake any tokens to store delayed receipts. State also contains special key
TrieKey::DelayedReceiptIndices
where first and last ids of delayed receipts not yet processed are stored. From 024e06e71ebc7a5bce0963f1ad4b6cbfb8d6de09 Mon Sep 17 00:00:00 2001 From: Andrei Kashin Date: Wed, 1 Feb 2023 13:10:01 +0000 Subject: [PATCH 104/150] fix(nomicon): Fix variable names in `select_validators` (#456) The previous name `block_producers` was not defined and also not generic enough as the algorithm would be used for both block producer selection and chunk-only producer selection, so using `validators` instead. Also, the function returns 2 outputs, so reflecting this in signature. --- specs/ChainSpec/SelectingBlockProducers.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/specs/ChainSpec/SelectingBlockProducers.md b/specs/ChainSpec/SelectingBlockProducers.md index 532b515db..875ac9fa9 100644 --- a/specs/ChainSpec/SelectingBlockProducers.md +++ b/specs/ChainSpec/SelectingBlockProducers.md @@ -86,7 +86,7 @@ but not block producers are chunk-only producers. ### Output -* `validators: Vec` +* `(validators: Vec, sampler: WeightedIndex)` ### Steps @@ -104,9 +104,9 @@ for v in sorted_proposals[0:max_num_validators]: else: break -block_producer_sampler = WeightedIndex([v.stake for v in block_producers]) +validator_sampler = WeightedIndex([v.stake for v in validators]) -return (block_producers, block_producer_sampler) +return (validators, validator_sampler) ``` ### Algorithm for selecting block producers From 550e428cfffafaa28bd84f2e882504a8679d01b6 Mon Sep 17 00:00:00 2001 From: Andrei Kashin Date: Fri, 3 Feb 2023 16:26:28 +0000 Subject: [PATCH 105/150] docs: Improve wording in Refunds (#458) This PR adds a number of wording improvements in the Refunds section. --- specs/RuntimeSpec/Refunds.md | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/specs/RuntimeSpec/Refunds.md b/specs/RuntimeSpec/Refunds.md index 4a796cc25..a88350a41 100644 --- a/specs/RuntimeSpec/Refunds.md +++ b/specs/RuntimeSpec/Refunds.md @@ -1,12 +1,12 @@ # Refunds -When execution of a receipt fails or there are left some unused amount of prepaid gas after a function call, the Runtime generates refund receipts. +When execution of a receipt fails or there is some unused amount of prepaid gas left after a function call, the Runtime generates refund receipts. -The are 2 types of refunds. -- Refunds for the failed receipt for attached deposits. Let's call them deposit refunds. -- Refunds for the unused gas and fees. Let's call them gas refunds. +The are 2 types of refunds: +- Refunds for the failed receipt for attached deposits. Let's call them **deposit refunds**. +- Refunds for the unused gas and fees. Let's call them **gas refunds**. -Refunds receipts are identified by having `predecessor_id == "system"`. They are also special because they don't cost any gas to generate or execute. As a result, they also do not contribute to the block gas limit. +Refund receipts are identified by having `predecessor_id == "system"`. They are also special because they don't cost any gas to generate or execute. As a result, they also do not contribute to the block gas limit. If the execution of a refund fails, the refund amount is burnt. The refund receipt is an `ActionReceipt` that consists of a single action `Transfer` with the `deposit` amount of the refund. @@ -14,9 +14,9 @@ The refund receipt is an `ActionReceipt` that consists of a single action `Trans ## Deposit Refunds Deposit refunds are generated when an action receipt fails to execute. All attached deposit amounts are summed together and -send as a refund to a `predecessor_id`. Because of only the predecessor can attach deposits. +sent as a refund to a `predecessor_id` (because only the predecessor can attach deposits). -Deposit refunds have the following fields in the ActionReceipt: +Deposit refunds have the following fields in the `ActionReceipt`: - `signer_id` is `system` - `signer_public_key` is ED25519 key with data equal to 32 bytes of `0`. @@ -33,7 +33,7 @@ newly generated receipts, e.g. from cross-contract calls in function calls actio Then the gas amount is converted to tokens by multiplying by the gas price at which the original transaction was generated. -Gas refunds have the following fields in the ActionReceipt: +Gas refunds have the following fields in the `ActionReceipt`: - `signer_id` is the actual `signer_id` from the receipt that generates this refund. - `signer_public_key` is the `signer_public_key` from the receipt that generates this refund. From 89b8ce5a565a5bccfe94384f58aa2d82966337d1 Mon Sep 17 00:00:00 2001 From: Bowen Wang Date: Mon, 20 Feb 2023 13:34:52 -0800 Subject: [PATCH 106/150] NEP-448: zero balance account NEP (#448) NEP for #415. Implementation can be found in https://github.com/near/nearcore/pull/8378 --- neps/nep-0448.md | 129 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 129 insertions(+) create mode 100644 neps/nep-0448.md diff --git a/neps/nep-0448.md b/neps/nep-0448.md new file mode 100644 index 000000000..6ecf862b5 --- /dev/null +++ b/neps/nep-0448.md @@ -0,0 +1,129 @@ +--- +NEP: 448 +Title: Zero-balance Accounts +Author: Bowen Wang +DiscussionsTo: https://github.com/nearprotocol/neps/pull/448 +Status: Draft +Type: Protocol Track +Created: 10-Jan-2023 +--- + +## Summary + +A major blocker to a good new user onboarding experience is that users have to acquire NEAR tokens to pay for +their account. With the implementation of [NEP-366](https://github.com/near/NEPs/pull/366), users don't necessarily have +to first acquire NEAR tokens in order to pay transaction fees, but they still have to pay for the storage of their account. +To address this problem, we propose allowing each account to have free storage for the account itself and up to four keys +and account for the cost of storage in the gas cost of create account transaction. + +## Motivation + +Ideally a new user should be able to onboard onto NEAR through any applications built on top of NEAR and do not have to +understand that the application is running on top of blockchain. The ideal flow is as follows: a user hear about an interesting +application from their friends or some forum and they decide to give it a try. The user opens the application in their +browser and directly starts using it without worrying about registration. Under the hood, a keypair is generated for the +user and the application creates an account for the user and pays for transaction fees through meta transactions. Later on, +the user may find other applications that they are also interested in and give them a try as well. At some point, the user +graduates from the onboarding experience by acquiring NEAR tokens either through earning or because they like some experience +so much that they would like to pay for it explicitly. Overall we want to have two full access keys for recovery purposes +and two function call access keys so that users can use two apps before graduating from the onboarding experience. + +## Rationale and alternatives + +There are a few alternative ideas: +* Completely disregard storage staking and do not change the account creation cost. This makes the implementation even +simpler. However, there may be a risk of spamming attack given that the cost of creating an account is around 0.2Tgas. +In addition, with the current design, it is easy to further reduce the cost. Going the other way is more difficult. +* Do not change how storage staking is calculated when converting to gas cost. This means that account creation cost would +be around 60Tgas, which is both high in gas (meaning that the throughput is limited and more likely for some contract to break) +and more costly for users (around 0.006N per account creation). + +## Specification + +There are two main changes to the protocol: +* Account creation cost needs to be increased. For every account, at creation time, 770 bytes of storage are reserved +for the account itself + four full access keys + two function call access keys. For function call access keys, +the "free" ones cannot use `method_names` in order to minimize the storage requirement for an account. +The number of bytes is calculated as follows: + - An account takes 100 bytes due to `storage_usage_config.num_bytes_account` + - A full access key takes 42 bytes and there is an additional 40 bytes required due to `storage_usage_config.num_extra_bytes_record` + - A function call access key takes 131 bytes and there is an additional 40 bytes required due to `storage_usage_config.num_extra_bytes_record` + - Therefore the total the number of bytes is `100 + (131 + 40) * 2 + (42 + 40) * 4 = 770`. + + The cost of these bytes is paid through transaction fee. Note that there is already [discussion](https://github.com/near/NEPs/issues/415) +around the storage cost of NEAR and whether it is reasonable. While this proposal does not attempt to change the entire +storage staking mechanism, the cost of storage is reduced in 10x when converting to gas. A [discussion](https://gov.near.org/t/storage-staking-price/399) +from a while ago mentioned this idea, and the concerns there were proven to be not real concerns. No one is deleting +data from storage in practice and the storage staking mechanism does not really serve its purpose. That conversion means +we increase the account creation cost to 7.7Tgas from 0.2Tgas +* Storage staking check will not be applied if an account has <= 4 full access keys and <= 2 function call access keys +and does not have a contract deployed. If an account accrues more than full access keys or function call access keys, +however, it must pay for the storage of everything including those 6 keys. This makes the implementation simpler and less error-prone. + +## Reference Implementation (Required for Protocol Working Group proposals, optional for other categories) + +Details of the changes described in the section above: +* Change `create_account_cost` to +``` +"create_account_cost": { + "send_sir": 3850000000000, + "send_not_sir": 3850000000000, + "execution": 3850000000000 +}, +``` +* Change the implementation of `get_insufficient_storage_stake` to check whether an account is zero balance account. +Note that even though the intent, as described in the section above, is to limit the number of full access keys to 4 +and the number of function call access keys to 2, for the ease of implementation, it makes sense to limit the size of +`storage_usage` on an account to 770 bytes because `storage_usage` is already stored under `Account` and it does not +require any additional storage reads. More specifically, the check looks roughly as follows: +```rust +/// Returns true if an account is a zero balance account +fn check_for_zero_balance_account(account: &Account) -> bool { + account.storage_usage <= 770 // 4 full access keys and 2 function call access keys +} +``` + +## Drawbacks (Optional) + +- Reduction of storage cost when converting the storage cost of zero balance accounts to gas cost may be a concern. But +I argue that the current storage cost is too high. A calculation shows that the current storage cost is around 36,000 times +higher than S3 storage cost. In addition, when a user accrues any contract data or has more than three keys on their account, +they have to pay for the storage cost of everything combined. In that sense, a user would pay slightly more than what +they pay today when their account is no longer a zero-balance account. + +## Unresolved Issues (Optional) + +## Future possibilities + +- We may change the number of keys allowed for zero-balance accounts in the future. +- A more radical thought: we can separate out zero-balance accounts into its own trie and manage them separately. This +may allow more customization on how we want zero-balance accounts to be treated. + +## Decision Context + +### 1.0.0 - Initial Version + +The initial version of NEP-448 was approved by Protocol Working Group members on February 9, 2023 ([meeting recording](https://youtu.be/ktgWXjNTU_A)). + +#### Benefits + +- Users can now onboard with having to acquire NEAR tokens +- Together with [meta transactions](https://github.com/near/NEPs/pull/366), this allows a user to start interacting with an app on NEAR directly from their device without any additional steps +- Solves the problem of meta transaction for implicit accounts + +#### Concerns + +| # | Concern | Resolution | Status | +| - | - | - | - | +| 1 | The number of full access keys allowed is too small | Could be done in a future iteration. | Resolved | +| 2 | No incentive for people to remove zero balance account. | Very few people actually delete their account anyways. | Resolved | +| 3 | UX of requiring balance after a user graduate from zero balance account to a regular account | The experience of graduating from zero balance account should be handled on the product side | Resolved | +| 4 | Increase of account creation cost may break some existing contracts | A thorough investigation has been done and it turns out that we only need to change the contract that is deployed on `near` slightly | Resolved | +| 5 | Account creation speed is slower due to increased cost | Unlikely to be a concern, especially given that the number of shards is expected to grow in the future | Resolved | +| 6 | Cost of transfers to implicit account increases | Unlikely to break anything at the moment, and could be addressed in the future in a different NEP (see https://github.com/near/NEPs/issues/462 for more details) | Resolved | + +## Copyright + +[copyright]: #copyright + +Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). From b91f1b064df3a89803c41664571ccc63ad0dfdc2 Mon Sep 17 00:00:00 2001 From: Philip Obosi Date: Fri, 24 Feb 2023 18:37:26 +0100 Subject: [PATCH 107/150] NEP-413: Add `signMessage` method to Wallet Standard (#413) ## Summary This is a proposal for a new NEP regarding Wallet Standards. It covers adding a new method 'verifyOwner` which signs a message and verifies wallet ownership. The message is not sent to blockchain. ## References This interface is now supported by Wallet Selector as shown below: > [near/wallet-selector#391](https://github.com/near/wallet-selector/pull/391) More developers within the ecosystem have also begun to add support for this to their Wallets. - [https://github.com/near/wallet-selector/pull/436/files](https://github.com/near/wallet-selector/pull/436/files) --- neps/nep-0413.md | 176 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 176 insertions(+) create mode 100644 neps/nep-0413.md diff --git a/neps/nep-0413.md b/neps/nep-0413.md new file mode 100644 index 000000000..bbac6797e --- /dev/null +++ b/neps/nep-0413.md @@ -0,0 +1,176 @@ +--- +NEP: 413 +Title: Near Wallet API - support for signMessage method +Author: Philip Obosi , Guillermo Gallardo +# DiscussionsTo: +Status: Approved +Type: Standards Track +Category: Wallet +Created: 25-Oct-2022 +--- + +## Summary + +A standardized Wallet API method, namely `signMessage`, that allows users to sign a message for a specific recipient using their NEAR account. + +## Motivation +NEAR users want to create messages destined to a specific recipient using their accounts. This has multiple applications, one of them being authentication in third-party services. + +Currently, there is no standardized way for wallets to sign a message destined to a specific recipient. + +## Rationale and Alternatives +Users want to sign messages for a specific recipient without incurring in GAS fees, nor compromising their account's security. This means that the message being signed: + +1) Must be signed off-chain, with no transactions being involved. +2) Must include the recipient's name and a nonce. +3) Cannot represent a valid transaction. +3) Must be signed using a Full Access Key. +4) Should be simple to produce/verify, and transmitted securely. + +### Why Off-Chain? +So the user would not incur in GAS fees, nor the signed message gets broadcasted into a public network. + +### Why The Message MUST NOT be a Transaction? How To Ensure This? +An attacker could make the user inadvertently sign a valid transaction which, once signed, could be submitted into the network to execute it. + +#### How to Ensure the Message is not a Transaction +In NEAR, transactions are encoded in Borsh before being signed. The first attribute of a transaction is a `signerId: string`, which is encoded as: (1) 4 bytes representing the string's length, (2) N bytes representing the string itself. + +By prepending the prefix tag $2^{31} + 413$ we can both ensure that (1) the whole message is an invalid transaction (since the string would be too long to be a valid signer account id), (2) this NEP is ready for a potential future protocol update, in which non-consensus messages are tagged using $2^{31}$ + NEP-number. + +### Why The Message Needs to Include a Receiver and Nonce? +To stop a malicious app from requesting the user to sign a message for them, only to relay it to a third-party. Including the recipient and making sure the user knows about it should mitigate these kind of attacks. + +Meanwhile, including a nonce helps to mitigate replay attacks, in which an attacker can delay or re-send a signed message. + +### Why using a FullAccess Key? Why Not Simply Creating an [FunctionCall Key](https://docs.near.org/concepts/basics/accounts/access-keys) for Signing? +The most common flow for [NEAR user authentication into a Web3 frontend](https://docs.near.org/develop/integrate/frontend#user-sign-in--sign-out) involves the creation of a [FunctionCall Key](](https://docs.near.org/concepts/basics/accounts/access-keys)). + +One might feel tempted to reproduce such process here, for example, by creating a key that can only be used to call a non-existing method in the user's account. This is a bad idea because: +1. The user would need to expend gas in creating a new key. +2. Any third-party can ask the user to create a `FunctionCall Key`, thus opening an attack vector. + +Using a FullAccess key allows us to be sure that the challenge was signed by the user (since nobody should have access to their `FullAccess Key`), while keeping the constraints of not expending gas in the process (because no new key needs to be created). + +### Why The Input Needs to Include a State? +Including a state helps to mitigate [CSRF attacks](https://auth0.com/docs/secure/attack-protection/state-parameters). This way, if a message needs to be signed for authentication purposes, the auth service can keep a state to make sure the auth request comes from the right author. + +### How to Return the Signed Message in a Safe Way +Sending the signed message in a query string to an arbitrary URL (even within the correct domain) is not secure as the data can be leaked (e.g. through headers, etc). Using URL fragments instead will improve security, since [URL fragments are not included in the `Referer`](https://greenbytes.de/tech/webdav/rfc2616.html#header.referer). + +### NEAR Signatures +NEAR transaction signatures are not plain Ed25519 signatures but Ed25519 signatures of a SHA-256 hash (see [near/nearcore#2835](https://github.com/near/nearcore/issues/2835)). Any protocol that signs anything with NEAR account keys should use the same signature format. + +## Specification +Wallets must implement a `signMessage` method, which takes a `message` destined to a specific `recipient` and transform it into a verifiable signature. + +### Input Interface +`signMessage` must implement the following input interface: + +```jsx +interface SignMessageParams { + message: string ; // The message that wants to be transmitted. + recipient: string; // The recipient to whom the message is destined (e.g. "alice.near" or "myapp.com"). + nonce: [u8; 32] ; // A nonce that uniquely identifies this instance of the message, denoted as a 32 bytes array (a fixed `Buffer` in JS/TS). + callbackUrl?: string; // Optional, applicable to browser wallets (e.g. MyNearWallet). The URL to call after the signing process. Defaults to `window.location.href`. + state?: string; // Optional, applicable to browser wallets (e.g. MyNearWallet). A state for authentication purposes. +} +``` + +### Structure +`signMessage` must embed the input `message`, `recipient` and `nonce` into the following predefined structure: + +```rust +struct Payload { + message: string; // The same message passed in `SignMessageParams.message` + nonce: [u8; 32]; // The same nonce passed in `SignMessageParams.nonce` + recipient: string; // The same recipient passed in `SignMessageParams.recipient` + callbackUrl?: string // The same callbackUrl passed in `SignMessageParams.callbackUrl` +} +``` + +### Signature +In order to create a signature, `signMessage` must: +1. Create a `Payload` object. +2. Convert the `payload` into its [Borsh Representation](https://borsh.io). +3. Prepend the 4-bytes borsh representation of $2^{31}+413$, as the [prefix tag](https://github.com/near/NEPs/pull/461). +4. Compute the `SHA256` hash of the serialized-prefix + serialized-tag. +5. Sign the resulting `SHA256` hash from step 3 using a **full-access** key. + +> If the wallet does not hold any `full-access` keys, then it must return an error. + +### Example +Assuming that the `signMessage` method was invoked, and that: +- The input `message` is `"hi"` +- The input `nonce` is `[0,...,31]` +- The input `recipient` is `"myapp.com"` +- The callbackUrl is `"myapp.com/callback"` +- The wallet stores a full-access private key + +The wallet must construct and sign the following `SHA256` hash: + +```jsx +// 2**31 + 413 == 2147484061 +sha256.hash(Borsh.serialize(2147484061) + Borsh.serialize(Payload{message:"hi", nonce:[0,...,31], recipient:"myapp.com", callbackUrl: "myapp.com/callback"})) +``` + +### Output Interface +`signMessage` must return an object containing the **base64** representation of the `signature`, and all the data necessary to verify such signature. + +```jsx +interface SignedMessage { + accountId: string; // The account name to which the publicKey corresponds as plain text (e.g. "alice.near") + publicKey: string; // The public counterpart of the key used to sign, expressed as a string with format ":" (e.g. "ed25519:6TupyNrcHGTt5XRLmHTc2KGaiSbjhQi1KHtCXTgbcr4Y") + signature: string; // The base64 representation of the signature. + state?: string; // Optional, applicable to browser wallets (e.g. MyNearWallet). The same state passed in SignMessageParams. +} +``` + +### Returning the signature +#### Web Wallets +Web Wallets, such as [MyNearWallet](https://mynearwallet.com), should directly return the `SignedMessage` to the `SignMessageParams.callbackUrl`, passing the `accountId`,`publicKey`, `signature` and the state as URL fragments. This is: `#accountId=&publicKey=&signature=&state=`. + +If the signing process fails, then the wallet must return an error message and the state as string fragments: `#error=&state=`. + +#### Other Wallets +Non-web Wallets, such as [Ledger](https://www.ledger.com) can directly return the `SignedMessage` (in preference as a JSON object) and raise an error on failure. + +## References +A full example on how to implement the `signMessage` method can be [found here](https://github.com/gagdiez/near-login/blob/main/tests/authentication/auth.ava.ts#L27-#L65). + +## Drawbacks +Accounts that do not hold a FullAccess Key will not be able to sign this kind of messages. However, this is a necessary tradeoff for security since any third-party can ask the user to create a FunctionAccess key. + +At the time of writing this NEP, the NEAR ledger app is unable to sign this kind of messages, since currently it can only sign pure transactions. This however can be overcomed by modifying the NEAR ledger app implementation in the near future. + +Non-expert subjects could use this standard to authenticate users in an unsecure way. To anyone implementing an authentication service, we urge them to read about [CSRF attacks](https://auth0.com/docs/secure/attack-protection/state-parameters), and make use of the `state` field. + +## Decision Context + +### 1.0.0 - Initial Version +The Wallet Standards Working Group members approved this NEP on January 17, 2023 ([meeting recording](https://youtu.be/Y6z7lUJSUuA)). + +### 1.1.0 - First Revison +Important Security concerns were raised by a community member, driving us to change the proposed implementation. + + +### Benefits + +- Makes it possible to authenticate users without having to add new access keys. This will improve UX, save money and will not increase the on-chain storage of the users' accounts. +- Makes it possible to authorize through jwt in web2 services using the NEAR account. +- Removes delays in adding transactions to the blockchain and makes the experience of using projects like NEAR Social better. + +### Concerns + +| # | Concern | Resolution | Status | +| - | - | - | - | +| 1 | Implementing the signMessage standard will divide wallets into those that will quickly add support for it and those that will take significantly longer. In this case, some services may not work correctly for some users | (1) Be careful when adding functionality with signMessage with legacy and ensure that alternative authorization methods are possible. For example by adding publicKey. (2) Oblige wallets to implement a standard in specific deadlines to save their support in wallet selector | Resolved | +| 2 | Large number of off-chain transactions will reduce activity in the blockchain and may negatively affect NEAR rate and attractiveness to third-party developers | There seems to be a general agreement that it is a good default | Resolved | +| 3 | `receiver` terminology can be misleading and confusing when existing functionality is taken into consideration (`signTransaction`) | It was recommended for the community to vote for a new name, and the NEP was updated changing `receiver` to `recipient` | Resolved | +| 4 | The NEP should emphasize that `nonce` and `receiver` should be clearly displayed to the user in the signing requests by wallets to achieve the desired security from these params being included | We strongly recommend the wallet to clearly display all the elements that compose the message being signed. However, this pertains to the wallet's UI and UX, and not to the method's specification, thus the NEP was not changed. | Resolved | +| 5 | NEP-408 (Injected Wallet API) should be extended with this new `signMessage` method | It is not a blocker for this NEP, but a follow-up NEP-extension proposal is welcome. | Resolved | + +## Copyright +[copyright]: #copyright + +Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). From 767802fc1b030cbd553ddaf3b5e02d8232d22b56 Mon Sep 17 00:00:00 2001 From: Akhilesh Singhania Date: Thu, 2 Mar 2023 15:10:28 +0100 Subject: [PATCH 108/150] doc: Fix confusing use of the phrase "subject matter experts" (#465) Closes #464 --- neps/nep-0001.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/neps/nep-0001.md b/neps/nep-0001.md index 1bb03de30..2db052b98 100644 --- a/neps/nep-0001.md +++ b/neps/nep-0001.md @@ -24,7 +24,7 @@ The purpose of the NEP process is to ensure seamless protocol upgrades and to em The working groups are responsible for coordinating the public review of NEPs, gauging the viability and community support, and overseeing decisions. Each group will focus on various ecosystem needs, such as the protocol, standards, and tools. -Pagoda has selected a few leading subject matter experts to help bootstrap the first two groups: Protocols and Contract Standards. Putting these groups into practice will require flexibility. The goal is to iterate and eventually introduce more groups and broader participation. Visit [https://near.org/developer-governance](https://near.org/developer-governance) to learn more about these groups, their members, and the upcoming meetings. +Pagoda has selected a few experts to help bootstrap the first two groups: Protocols and Contract Standards. Putting these groups into practice will require flexibility. The goal is to iterate and eventually introduce more groups and broader participation. Visit [https://near.org/developer-governance](https://near.org/developer-governance) to learn more about these groups, their members, and the upcoming meetings. ## Audience The typical primary audience for NEPs are the core developers of the NEAR reference implementations and decentralized applications developers From b452c82aa9016280b85e228a8dd2056491213b6d Mon Sep 17 00:00:00 2001 From: Lachlan Glen <54282009+lachlanglen@users.noreply.github.com> Date: Tue, 7 Mar 2023 10:38:57 -0500 Subject: [PATCH 109/150] add contract_metadata_update event (#423) Added `contract_metadata_update` event to `Standards -> Tokens -> NonFungibleToken` as per the following discussion: https://gov.near.org/t/extending-nep-171-events-standard-to-include-contract-metadata-update-events/30384 Implementation of this new event enables 3rd party applications to listen for updates to NFT contract metadata, e.g. a new dedicated IPFS gateway (`base_uri`) and provide a consistent and higher quality experience for their users. --------- Co-authored-by: Vlad Frolov --- neps/nep-0171.md | 80 ++++++++++++++----- .../Tokens/NonFungibleToken/Event.md | 53 +++++++----- 2 files changed, 96 insertions(+), 37 deletions(-) diff --git a/neps/nep-0171.md b/neps/nep-0171.md index 400df70bc..2d6278007 100644 --- a/neps/nep-0171.md +++ b/neps/nep-0171.md @@ -6,7 +6,9 @@ DiscussionsTo: https://github.com/near/NEPs/discussions/171 Status: Final Type: Standards Track Category: Contract +Version: 1.1.0 Created: 03-Mar-2022 +Updated: 07-Mar-2023 Requires: 297 --- @@ -216,21 +218,21 @@ function nft_on_transfer( ### Events -NEAR and third-party applications need to track `mint`, `transfer`, `burn` events for all NFT-driven apps consistently. +NEAR and third-party applications need to track `mint`, `transfer`, `burn`, and `contract_metadata_update` events for all NFT-driven apps consistently. This extension addresses that. Keep in mind that applications, including NEAR Wallet, could require implementing additional methods to display the NFTs correctly, such as [`nft_metadata`][Metadata] and [`nft_tokens_for_owner`][NFT Enumeration]). -### Events Interface +#### Events Interface -Non-Fungible Token Events MUST have `standard` set to `"nep171"`, standard version set to `"1.0.0"`, `event` value is one of `nft_mint`, `nft_burn`, `nft_transfer`, and `data` must be of one of the following relevant types: `NftMintLog[] | NftTransferLog[] | NftBurnLog[]`: +Non-Fungible Token Events MUST have `standard` set to `"nep171"`, standard version set to `"1.1.0"`, `event` value is one of `nft_mint`, `nft_burn`, `nft_transfer`, or `contract_metadata_update`, and `data` must be of one of the following relevant types: `NftMintLog[] | NftTransferLog[] | NftBurnLog[] | NftContractMetadataUpdateLog[]`: ```ts interface NftEventLogData { standard: "nep171", - version: "1.0.0", - event: "nft_mint" | "nft_burn" | "nft_transfer", - data: NftMintLog[] | NftTransferLog[] | NftBurnLog[], + version: "1.1.0", + event: "nft_mint" | "nft_burn" | "nft_transfer" | "contract_metadata_update", + data: NftMintLog[] | NftTransferLog[] | NftBurnLog[] | NftContractMetadataUpdateLog[], } ``` @@ -273,16 +275,23 @@ interface NftTransferLog { token_ids: string[], memo?: string } + +// An event log to capture contract metadata updates. Note that the updated contract metadata is not included in the log, as it could easily exceed the 16KB log size limit. Listeners can query `nft_metadata` to get the updated contract metadata. +// Arguments +// * `memo`: optional message +interface NftContractMetadataUpdateLog { + memo?: string +} ``` -## Examples +#### Examples Single owner batch minting (pretty-formatted for readability purposes): ```js EVENT_JSON:{ "standard": "nep171", - "version": "1.0.0", + "version": "1.1.0", "event": "nft_mint", "data": [ {"owner_id": "foundation.near", "token_ids": ["aurora", "proximitylabs"]} @@ -295,7 +304,7 @@ Different owners batch minting: ```js EVENT_JSON:{ "standard": "nep171", - "version": "1.0.0", + "version": "1.1.0", "event": "nft_mint", "data": [ {"owner_id": "foundation.near", "token_ids": ["aurora", "proximitylabs"]}, @@ -309,7 +318,7 @@ Different events (separate log entries): ```js EVENT_JSON:{ "standard": "nep171", - "version": "1.0.0", + "version": "1.1.0", "event": "nft_burn", "data": [ {"owner_id": "foundation.near", "token_ids": ["aurora", "proximitylabs"]}, @@ -320,7 +329,7 @@ EVENT_JSON:{ ```js EVENT_JSON:{ "standard": "nep171", - "version": "1.0.0", + "version": "1.1.0", "event": "nft_transfer", "data": [ {"old_owner_id": "user1.near", "new_owner_id": "user2.near", "token_ids": ["meme"], "memo": "have fun!"} @@ -333,7 +342,7 @@ Authorized id: ```js EVENT_JSON:{ "standard": "nep171", - "version": "1.0.0", + "version": "1.1.0", "event": "nft_burn", "data": [ {"owner_id": "owner.near", "token_ids": ["goodbye", "aurevoir"], "authorized_id": "thirdparty.near"} @@ -341,29 +350,62 @@ EVENT_JSON:{ } ``` -## Further Event Methods +Contract metadata update: + +```js +EVENT_JSON:{ + "standard": "nep171", + "version": "1.1.0", + "event": "contract_metadata_update", + "data": [] +} +``` + +#### Events for Other NFT Methods -Note that the example events covered above cover two different kinds of events: -1. Events that are not specified in the NFT Standard (`nft_mint`, `nft_burn`) -2. An event that is covered in the [NFT Core Standard](https://nomicon.io/Standards/NonFungibleToken/Core.html#nft-interface). (`nft_transfer`) +Note that the example events above cover two different kinds of events: +1. Events that do not have a dedicated trigger function in the NFT Standard (`nft_mint`, `nft_burn`, `contract_metadata_update`) +2. An event that has a relevant trigger function [NFT Core Standard](https://nomicon.io/Standards/NonFungibleToken/Core.html#nft-interface) (`nft_transfer`) -This event standard also applies beyond the three events highlighted here, where future events follow the same convention of as the second type. For instance, if an NFT contract uses the [approval management standard](https://nomicon.io/Standards/NonFungibleToken/ApprovalManagement.html), it may emit an event for `nft_approve` if that's deemed as important by the developer community. +This event standard also applies beyond the events highlighted here, where future events follow the same convention of as the second type. For instance, if an NFT contract uses the [approval management standard](https://nomicon.io/Standards/NonFungibleToken/ApprovalManagement.html), it may emit an event for `nft_approve` if that's deemed as important by the developer community. Please feel free to open pull requests for extending the events standard detailed here as needs arise. + ## Reference Implementation [Minimum Viable Interface](https://github.com/near/near-sdk-rs/blob/master/near-contract-standards/src/non_fungible_token/core/mod.rs) [NFT Implementation](https://github.com/near/near-sdk-rs/blob/master/near-contract-standards/src/non_fungible_token/core/core_impl.rs) -## Errata -* **2022-02-03**: updated `Token` struct field names. `id` was changed to `token_id`. This is to be consistent with current implementations of the standard and the rust SDK docs. +## Changelog + +### 1.0.0 - Initial version +This NEP had several pre-1.0.0 iterations that led to the following errata updates to this NEP: + +* **2022-02-03**: updated `Token` struct field names. `id` was changed to `token_id`. This is to be consistent with current implementations of the standard and the rust SDK docs. * **2021-12-20**: updated `nft_resolve_transfer` argument `approved_account_ids` to be type `null|Record` instead of `null|string[]`. This gives contracts a way to restore the original approved accounts and their approval IDs. More information can be found in [this](https://github.com/near/NEPs/issues/301) discussion. * **2021-07-16**: updated `nft_transfer_call` argument `approval_id` to be type `number|null` instead of `string|null`. As stated, approval IDs are not expected to exceed the JSON limit of 2^53. +### 1.1.0 - Add `contract_metadata_update` Event + +The extension NEP-0423 that added Contract Metadata to this NEP-0171 was approved by Contract Standards Working Group members (@frol, @abacabadabacaba, @mfornet) on January 13, 2023 ([meeting recording](https://youtu.be/pBLN9UyE6AA)). + +#### Benefits + +* This new event type will help indexers to invalidate their cached values reliably and efficiently +* This NEP extension only introduces an additional event type, so there is no breaking change to the original NEP + +#### Concerns + +| # | Concern | Resolution | Status | +| - | - | - | - | +| 1 | Old NFT contracts do not emit JSON Events at all; more recent NFT contracts will only emit mint/burn/transfer events, so when it comes to legacy contracts support, we won’t benefit from this new event type and only further fragment the implementations | Legacy contracts usage will die out eventually and new contracts will support new features in a non-breaking way | Resolved | +| 2 | There is a need to have a similar event type for individual NFT updates | It is outside of the scope of this NEP extension. Feel free to create a follow-up proposal | Resolved | + + ## Copyright [copyright]: #copyright diff --git a/specs/Standards/Tokens/NonFungibleToken/Event.md b/specs/Standards/Tokens/NonFungibleToken/Event.md index b9a50d3a7..bd87c2f29 100644 --- a/specs/Standards/Tokens/NonFungibleToken/Event.md +++ b/specs/Standards/Tokens/NonFungibleToken/Event.md @@ -1,29 +1,28 @@ # Events -Version `1.0.0` +Version `1.1.0` ## Summary -Standard interface for NFT contract actions. -Extension of [NEP-297](../../EventsFormat.md) +Standard interface for NFT contract actions based on [NEP-297](../../EventsFormat.md). ## Motivation -NEAR and third-party applications need to track `mint`, `transfer`, `burn` events for all NFT-driven apps consistently. +NEAR and third-party applications need to track `mint`, `transfer`, `burn` and `contract_metadata_update` events for all NFT-driven apps consistently. This extension addresses that. Keep in mind that applications, including NEAR Wallet, could require implementing additional methods to display the NFTs correctly, such as [`nft_metadata`](Metadata.md) and [`nft_tokens_for_owner`](Enumeration.md). ## Interface -Non-Fungible Token Events MUST have `standard` set to `"nep171"`, standard version set to `"1.0.0"`, `event` value is one of `nft_mint`, `nft_burn`, `nft_transfer`, and `data` must be of one of the following relavant types: `NftMintLog[] | NftTransferLog[] | NftBurnLog[]`: +Non-Fungible Token Events MUST have `standard` set to `"nep171"`, standard version set to `"1.1.0"`, `event` value is one of `nft_mint`, `nft_burn`, `nft_transfer`, `contract_metadata_update`, and `data` must be of one of the following relavant types: `NftMintLog[] | NftTransferLog[] | NftBurnLog[] | NftContractMetadataUpdateLog[]`: ```ts interface NftEventLogData { standard: "nep171", - version: "1.0.0", - event: "nft_mint" | "nft_burn" | "nft_transfer", - data: NftMintLog[] | NftTransferLog[] | NftBurnLog[], + version: "1.1.0", + event: "nft_mint" | "nft_burn" | "nft_transfer" | "contract_metadata_update", + data: NftMintLog[] | NftTransferLog[] | NftBurnLog[] | NftContractMetadataUpdateLog[], } ``` @@ -66,6 +65,13 @@ interface NftTransferLog { token_ids: string[], memo?: string } + +// An event log to capture contract metadata updates. Note that the updated contract metadata is not included in the log, as it could easily exceed the 16KB log size limit. Listeners can query `nft_metadata` to get the updated contract metadata. +// Arguments +// * `memo`: optional message +interface NftContractMetadataUpdateLog { + memo?: string +} ``` ## Examples @@ -75,7 +81,7 @@ Single owner batch minting (pretty-formatted for readability purposes): ```js EVENT_JSON:{ "standard": "nep171", - "version": "1.0.0", + "version": "1.1.0", "event": "nft_mint", "data": [ {"owner_id": "foundation.near", "token_ids": ["aurora", "proximitylabs"]} @@ -88,7 +94,7 @@ Different owners batch minting: ```js EVENT_JSON:{ "standard": "nep171", - "version": "1.0.0", + "version": "1.1.0", "event": "nft_mint", "data": [ {"owner_id": "foundation.near", "token_ids": ["aurora", "proximitylabs"]}, @@ -102,7 +108,7 @@ Different events (separate log entries): ```js EVENT_JSON:{ "standard": "nep171", - "version": "1.0.0", + "version": "1.1.0", "event": "nft_burn", "data": [ {"owner_id": "foundation.near", "token_ids": ["aurora", "proximitylabs"]}, @@ -113,7 +119,7 @@ EVENT_JSON:{ ```js EVENT_JSON:{ "standard": "nep171", - "version": "1.0.0", + "version": "1.1.0", "event": "nft_transfer", "data": [ {"old_owner_id": "user1.near", "new_owner_id": "user2.near", "token_ids": ["meme"], "memo": "have fun!"} @@ -126,7 +132,7 @@ Authorized id: ```js EVENT_JSON:{ "standard": "nep171", - "version": "1.0.0", + "version": "1.1.0", "event": "nft_burn", "data": [ {"owner_id": "owner.near", "token_ids": ["goodbye", "aurevoir"], "authorized_id": "thirdparty.near"} @@ -134,12 +140,23 @@ EVENT_JSON:{ } ``` -## Further methods +Contract metadata update: + +```js +EVENT_JSON:{ + "standard": "nep171", + "version": "1.1.0", + "event": "contract_metadata_update", + "data": [] +} +``` + +## Events for Other NFT Methods -Note that the example events covered above cover two different kinds of events: -1. Events that are not specified in the NFT Standard (`nft_mint`, `nft_burn`) -2. An event that is covered in the [NFT Core Standard](Core.md). (`nft_transfer`) +Note that the example events above cover two different kinds of events: +1. Events that do not have a dedicated trigger function in the NFT Standard (`nft_mint`, `nft_burn`, `contract_metadata_update`) +2. An event that has a relevant trigger function [NFT Core Standard](Core.md#nft-interface) (`nft_transfer`) -This event standard also applies beyond the three events highlighted here, where future events follow the same convention of as the second type. For instance, if an NFT contract uses the [approval management standard](ApprovalManagement.md), it may emit an event for `nft_approve` if that's deemed as important by the developer community. +This event standard also applies beyond the events highlighted here, where future events follow the same convention of as the second type. For instance, if an NFT contract uses the [approval management standard](ApprovalManagement.md), it may emit an event for `nft_approve` if that's deemed as important by the developer community. Please feel free to open pull requests for extending the events standard detailed here as needs arise. From ad53776f4be26463b30480003a32d993b59c0389 Mon Sep 17 00:00:00 2001 From: Vlad Frolov Date: Wed, 8 Mar 2023 18:36:39 +0100 Subject: [PATCH 110/150] fix: Fixed the link to the NEAR Economics paper (#468) --- specs/Proposals/0033-economics.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/specs/Proposals/0033-economics.md b/specs/Proposals/0033-economics.md index b8e890274..349628f85 100644 --- a/specs/Proposals/0033-economics.md +++ b/specs/Proposals/0033-economics.md @@ -6,12 +6,12 @@ # Summary [summary]: #summary -Adding economics specification for NEAR Protocol based on the economics paper - https://nearprotocol.com/papers/economics-in-sharded-blockchain/ +Adding economics specification for NEAR Protocol based on the economics paper - https://near.org/papers/economics-in-sharded-blockchain/ # Motivation [motivation]: #motivation -Currently, the specification is defined by the implementation in https://github.com/nearprotocol/nearcore. This codifies all the parameters and formulas and defines main concepts. +Currently, the specification is defined by the implementation in https://github.com/near/nearcore. This codifies all the parameters and formulas and defines main concepts. # Guide-level explanation [guide-level-explanation]: #guide-level-explanation From 4498ac9e14f2bc1cb56acf5b1c8091f3a7434ce3 Mon Sep 17 00:00:00 2001 From: ori-near <110252255+ori-near@users.noreply.github.com> Date: Wed, 8 Mar 2023 09:54:23 -0800 Subject: [PATCH 111/150] Update template to reflect NEP-0001 (#467) We've recently proposed some improvements to NEP-0001 (#466). This template reflects those changes. --- nep-0000-template.md | 127 +++++++++++++++++++++++++++---------------- 1 file changed, 81 insertions(+), 46 deletions(-) diff --git a/nep-0000-template.md b/nep-0000-template.md index 5769a8bb7..57bf3bb98 100644 --- a/nep-0000-template.md +++ b/nep-0000-template.md @@ -1,83 +1,118 @@ --- NEP: 0 -Title: NEP Purpose and Guidelines -Author: Todd Codrington III +Title: NEP Template +Authors: Todd Codrington III +Status: Approved DiscussionsTo: https://github.com/nearprotocol/neps/pull/0000 -Status: Draft -Type: Standards Track -Category: Contract -Created: 03-Mar-2022 +Type: Developer Tools +Version: 1.1.0 +Created: 2022-03-03 +LastUpdated: 2023-03-07 --- +[This is a NEP (NEAR Enhancement Proposal) template, as described in [NEP-0001](https://github.com/near/NEPs/blob/master/neps/nep-0001.md). Use this when creating a new NEP. The author should delete or replace all the comments or commented brackets when merging their NEP.] + + + + + ## Summary -One paragraph explanation of the proposal. +[Provide a short human-readable (~200 words) description of the proposal. A reader should get from this section a high-level understanding about the issue this NEP is addressing.] ## Motivation -Why are we doing this? What use cases does it support? What is the expected outcome? +[Explain why this proposal is necessary, how it will benefit the NEAR protocol or community, and what problems it solves. Also describe why the existing protocol specification is inadequate to address the problem that this NEP solves, and what potential use cases or outcomes.] ## Rationale and alternatives -- Why is this design the best in the space of possible designs? -- What other designs have been considered and what is the rationale for not choosing them? -- What is the impact of not doing this? +[Justify the design decision for the proposed solution. And explain any alternative designs that were considered and the rationale for not choosing them.] ## Specification -Explain the proposal as if it was already implemented and you were teaching it to another developer. That generally means: - -- Introducing new named concepts. -- Explaining the feature largely in terms of examples. -- If the feature introduces new abstractions, explaining how users and/or developers should _think_ about it; -- If applicable, describe the differences between the existing functionality. - -For user-facing NEPs, this section should focus on user stories. +[Explain the proposal as if you were teaching it to another developer. This generally means describing the syntax and semantics, naming new concepts, and providing clear examples. The specification needs to include sufficient detail to allow interoperable implementations getting built by following only the provided specification. In cases where it is infeasible to specify all implementation details upfront, broadly describe what they are.] -## Reference Implementation (Required for Protocol Working Group proposals, optional for other categories) +## Reference Implementation -This is the technical portion of the NEP. Explain the design in sufficient detail that: +[This technical section is required for Protocol proposals but optional for other categories. A draft implementation should demonstrate a minimal implementation that assists in understanding or implementing this proposal. Explain the design in sufficient detail that: -- Its interaction with other features is clear. -- Where possible, include a `Minimum Viable Interface` subsection expressing the required behavior and types in a target Near Contract language. (ie. traits and structs for rust, interfaces and classes for javascript, function signatures and structs for c, etc.) -- It is reasonably clear how the feature would be implemented. -- Corner cases are dissected by example. +* Its interaction with other features is clear. +* Where possible, include a Minimum Viable Interface subsection expressing the required behavior and types in a target programming language. (ie. traits and structs for rust, interfaces and classes for javascript, function signatures and structs for c, etc.) +* It is reasonably clear how the feature would be implemented. +* Corner cases are dissected by example. +* For protocol changes: A link to a draft PR on nearcore that shows how it can be integrated in the current code. It should at least solve the key technical challenges. -The section should return to the examples given in the previous section, and explain more fully how the detailed proposal makes those examples work. +The section should return to the examples given in the previous section, and explain more fully how the detailed proposal makes those examples work.] -## Security Implications (Optional) +## Security Implications -If there are security concerns concerning the NEP, those concerns should be explicitly written out to make sure reviewers of the NEP are aware of them. +[Explicitly outline any security concerns in relation to the NEP, and potential ways to resolve or mitigate them. At the very least, well-known relevant threats must be covered, e.g. person-in-the-middle, double-spend, XSS, CSRF, etc.] ## Drawbacks (Optional) -Why should we **not** do this? +[Explain why we should not implement this NEP and any limitations. It is helpful to record any concerns raised throughout the NEP discussion.] ## Unresolved Issues (Optional) -- What parts of the design do you expect to resolve through the NEP process before this gets merged? -- What parts of the design do you expect to resolve through the implementation of this feature before stabilization? -- What related issues do you consider out of scope for this NEP that could be addressed in the future independently of the solution that comes out of this NEP? +[Explain any issues that warrant further discussion. Considerations: + +* What parts of the design do you expect to resolve through the NEP process before this gets merged? +* What parts of the design do you expect to resolve through the implementation of this feature before stabilization? +* What related issues do you consider out of scope for this NEP that could be addressed in the future independently of the solution that comes out of this NEP?] ## Future possibilities -Think about what the natural extension and evolution of your proposal would -be and how it would affect the project as a whole in a holistic -way. Try to use this section as a tool to more fully consider all possible -interactions with the project in your proposal. -Also, consider how all fits into the roadmap for the project -and of the relevant sub-team. +[Describe any natural extensions and evolutions to the NEP proposal, and how they would impact the project. Use this section as a tool to help fully consider all possible interactions with the project in your proposal. This is also a good place to "dump ideas"; if they are out of scope for the NEP but otherwise related. Note that having something written down in the future-possibilities section is not a reason to accept the current or a future NEP. Such notes should be in the section on motivation or rationale in this or subsequent NEPs. The section merely provides additional information.] + +## Changelog + +[The changelog section provides historical context for how the NEP developed over time. Initial NEP submission should start with version 1.0.0, and all subsequent NEP extensions must follow [Semantic Versioning](https://semver.org/). Every version should have the benefits and concerns raised during the review. The author does not need to fill out this section for the initial draft. Instead, the assigned reviewers (Subject Matter Experts) should create the first version during the first technical review. After the final public call, the author should then finalize the last version of the decision context.] + +### 1.0.0 - Initial Version + +[Placeholder for the context about when and who approved this NEP version.] + +#### Benefits -This is also a good place to "dump ideas"; if they are out of scope for the -NEP you are writing but otherwise related. +[Placeholder for Subject Matter Experts review for this version:] +* Benefit 1 +* Benefit 2 -If you have tried and cannot think of any future possibilities, -you may simply state that you cannot think of anything. +#### Concerns -Note that having something written down in the future-possibilities section -is not a reason to accept the current or a future NEP. Such notes should be -in the section on motivation or rationale in this or subsequent NEPs. -The section merely provides additional information. +[Template for Subject Matter Experts review for this version:] +| # | Concern | Resolution | Status | +| - | - | - | - | +| 1 | | | | +| 2 | | | | ## Copyright From d36f696df9315b76d2b6ca71053f9ecb2aa6a6a8 Mon Sep 17 00:00:00 2001 From: ori-near <110252255+ori-near@users.noreply.github.com> Date: Wed, 8 Mar 2023 11:33:07 -0800 Subject: [PATCH 112/150] Updates to NEP-0001 (#466) We have made several changes to NEP-0001 (and the corresponding NEP-0000 template #467) to improve the clarity and effectiveness of the process. These changes include clarifying the roles and responsibilities and adding additional guidance for each step. We also reordered various sections to make it easier to read and navigate. --- neps/nep-0001.md | 267 +++++++++++++++++++---------------------------- 1 file changed, 108 insertions(+), 159 deletions(-) diff --git a/neps/nep-0001.md b/neps/nep-0001.md index 2db052b98..3df1f3662 100644 --- a/neps/nep-0001.md +++ b/neps/nep-0001.md @@ -1,228 +1,177 @@ --- NEP: 1 -Title: NEP Purpose and Guideline -Authors: Bowen W. ; Austin Baggio ; Ori A. ; +Title: NEP Purpose and Guidelines +Authors: Bowen W. , Austin Baggio , Ori A. , Vlad F. ; +Status: Approved DiscussionsTo: https://github.com/near/NEPs/pull/333 -Status: Living -Type: Process -Created: 03-Mar-2022 +Type: Developer Tools +Version: 1.1.0 +Created: 2022-03-03 +Last Updated: 2023-03-05 --- +## Summary +A NEAR Enhancement Proposal (NEP) is a design document that specifies reusable and interoperable components integrated across the NEAR ecosystem. -## What is a NEAR Enhancement Proposal (NEP)? -A NEP is a design document for providing information to the NEAR community or describing a new feature for the NEAR protocol or Smart Contract standards. The NEP should provide a concise technical specification and a rationale for the feature. +NEPs are the primary mechanism for evolving NEAR’s runtime, Smart Contract Standards, and Wallets ecosystem in a community-driven way. NEPs provide a concise technical specification and a rationale for the feature. The NEP author is responsible for building consensus within the community and documenting dissenting opinions. The typical primary audience for NEPs are the developers of the NEAR reference implementations and decentralized application developers. -NEPs are intended to be the primary mechanism for proposing new features, coordinating formal feedback, and documenting design decisions that were integrated into NEAR’s runtime or Smart Contract ecosystem. +NEPs are stored as text files in a versioned repository, allowing for easy historical tracking. A list of NEPs is available on [GitHub](https://github.com/near/NEPs). -As such, the NEP’s author is responsible for building consensus within the community and documenting dissenting opinions. +## Motivation -Because NEPs are maintained as text files in a versioned repository, their revision history is the historical record of the feature proposal. A list of NEPs is available on [GitHub](https://github.com/near/NEPs/). +The purpose of the NEP process is to ensure the seamless evolution of the NEAR platform and to empower the community to contribute to its development. Given the complexity and number of participants involved across the ecosystem, a well-defined process helps ensure transparency, security, and stability. -## Motivation +## NEP Types +There are four kinds of NEPs: -The purpose of the NEP process is to ensure seamless protocol upgrades and to empower the community to contribute to the development of the NEAR platform. Given the complexity of the protocol and the large number of participants across the ecosystem, the process introduces working groups as a way to operationalize the review of NEPs that builds legitimacy and community support. +1. A **Protocol** NEP describes a new feature of the NEAR protocol. +2. A **Contract Standards** NEP specifies NEAR Smart Contract interfaces for a reusable concept in the NEAR ecosystem. +3. A **Wallet Standards** NEP specifies ecosystem-wide APIs for Wallet implementations. +4. A **Developer Tools** NEP defines norms and guidelines for developer tooling in the NEAR ecosystem. -The working groups are responsible for coordinating the public review of NEPs, gauging the viability and community support, and overseeing decisions. Each group will focus on various ecosystem needs, such as the protocol, standards, and tools. +Currently, all types of NEPs follow the same process, but for Protocol NEPs a draft implementation is required. -Pagoda has selected a few experts to help bootstrap the first two groups: Protocols and Contract Standards. Putting these groups into practice will require flexibility. The goal is to iterate and eventually introduce more groups and broader participation. Visit [https://near.org/developer-governance](https://near.org/developer-governance) to learn more about these groups, their members, and the upcoming meetings. +## Submit a NEP -## Audience -The typical primary audience for NEPs are the core developers of the NEAR reference implementations and decentralized applications developers +### Start with ideation +Everyone in the community is welcome to propose, discuss, and review ideas to improve the NEAR protocol and standards. The NEP process begins with a [new idea](https://www.neardevgov.org/blog/how-to-ideate-in-the-near-developer-governance) for the NEAR ecosystem. A single NEP should contain a single key proposal or new idea. -## NEP Types -There are two kinds of NEPs: - -1. A **Standards** NEP describes a new NEAR Smart Contract implementation standard. -2. A **Protocol** NEP describes a new feature for the NEAR protocol. - -Currently, both types of NEPs follow the same process. - -## NEP Workflow -### Start with an idea for NEAR -Everyone in the community is welcome to propose, discuss, and review ideas to improve the NEAR protocol and standards. The NEP process begins with a new idea for the NEAR ecosystem. A single NEP should contain a single key proposal or new idea. - -Each NEP must have an author: someone who writes the NEP using the style and format described below. The author, or another champion, shepherds the discussions in the appropriate forums and attempts to build community consensus around the idea to help it progress toward completion. - -Before submitting a NEP, the author should first attempt to ascertain whether the idea is NEP-able. Vetting an idea publicly before writing a NEP saves the potential author time. Asking the NEAR community first if an idea is original helps prevent effort on something that is guaranteed to be rejected based on prior discussions. It also helps ensure the idea is applicable to the entire community. Just because an idea sounds good to the author does not mean it will work for most people in most use cases. - -In general, the process to socialize an idea is: - -- **Check prior proposals:** Many ideas for changing NEAR come up frequently. Please search the [governance](https://gov.near.org/)[ ](https://gov.near.org/)[site](https://gov.near.org/) forums and NEPs in this repo before proposing something new. -- **Share the idea:** Join the [governance](https://gov.near.org/)[ ](https://gov.near.org/)[site](https://gov.near.org/) and make a post to the appropriate section. For instance, during the ideation phase of a standard, one might start a new conversation in the [Development](https://gov.near.org/c/dev/standards/29)[ » ](https://gov.near.org/c/dev/standards/29)[Standards](https://gov.near.org/c/dev/standards/29)[ ](https://gov.near.org/c/dev/standards/29)[section](https://gov.near.org/c/dev/standards/29). Similarly, during the ideation phase of a proposal to change the protocol, one might start a new conversation in the [Development](https://gov.near.org/c/dev/proposals/68)[ » ](https://gov.near.org/c/dev/proposals/68)[Proposals](https://gov.near.org/c/dev/proposals/68)[ ](https://gov.near.org/c/dev/proposals/68)[section](https://gov.near.org/c/dev/proposals/68). -- **Get feedback:** The forum has comment threading which allows the community and NEAR Collective to ideate, ask questions, wrestle with approaches, etc. If more immediate responses are desired, consider bringing the conversation [to](https://near.chat/)[ ](https://near.chat/)[Discord](https://near.chat/). - -### Submit a NEP -Following the above initial discussions, the author should submit a draft NEP via a GitHub pull request. The draft must follow the NEP style as described below, else it will fail review immediately (although the moderators may correct minor errors). - -The NEP workflow is: - -- You, the NEP author, fork the NEPs repository, and create a file named neps/nep-9999.md that contains your new NEP. Use “9999” as your draft NEP number. -- Your first update is to change the nep filename to match the Pull Request number. For example, if the PR is 305, the NEP should be neps/nep-0305.md. -- In the “Type:” header field, enter “Standards” or “Protocol” as appropriate, and for the “Status:” field enter “Draft”. For full details, see NEP Header Preamble. -- Push this to your GitHub fork and submit a pull request. -- The NEP moderators review your PR for structure, formatting, and other errors. For a markdown-formatted NEP, nep-template.md is provided as a template. - Approval criteria are: - - The content is sound and complete. The ideas must make technical sense. The moderators do not consider whether they seem likely for acceptance. - - The title accurately describes the content. - - The language (spelling, grammar, sentence structure, etc.) and code style are correct and conformant. -- If the NEP is not ready for approval, the moderators will send it back to the author for revision, with specific instructions in the pull request. The review by the moderators is expected to finish within one week. -- Once the moderators agree that the PR is ready for review, the moderators will notify the approvers (working group members) to assign a team of at least two reviewers (subject matter experts) to review the NEP. The reviewers will review the technical details of the proposal and assess its merits. They may ask clarification questions, request changes, or reject the proposal. If the assigned reviewers feel that they do not have the relevant expertise to fully review the NEP, they can request the working group to re-assign subject matter experts for the NEP. -- The review by the reviewers is expected to finish within one week. After completing the review, the reviewer must add an explicit comment to indicate the next step and tag the appropriate member: - - To request revisions from the author: "As the assigned Reviewer, I request from the author @author-username to address [provide concerns or suggestions]." - - To move to the next stage: "As the assigned Reviewer, I do not have any feedback for the author. I recommend moving this NEP forward and for the working group to [accept or reject] it based on [provide reasoning, including a sense of importance or urgency of this NEP]." -- The author of the proposal is free to revise the proposal and re-request reviews from reviewers. If a proposal is in the review stage for more than two months, the moderator will automatically reject it. To re-open the proposal, the author must start over with the NEP process again. -- Once the two reviewers agree that the proposal is close to the voting stage, the moderators will assign the approvers (working group) to review the NEP. The approvers will review the proposal and add their voting indication. -- The final review period by the approvers is expected to finish within one week. After completing the review, the approvers must add an explicit comment with their voting indication: - - To reject: "As a working group member, I lean towards rejecting this proposal based on [provide reasoning]." - - To approve: "As a working group member, I lean towards approving this NEP based on [provide reasoning]." -- Once all the approvers add their voting indication, the moderator will review the voting indication for a 2/3 majority vote: - - If the votes lean toward rejection: The moderator will summarize the feedback and close the NEP. - - If the votes lean toward approval: The moderator will schedule a public call (see [NEP Communication](#nep-communication)) for the author to present the NEP and for the working group members to formalize the voting decision. If the working group members agree that the NEP is overall beneficial for the NEAR ecosystem and vote to approve it, then the proposal is considered accepted. After the call, the moderator will summarize the decision on the NEP. +Each NEP must have an author: Someone who writes the NEP using the style and format described below. The author, or another champion, shepherds the discussions in the appropriate forums and attempts to build community consensus around the idea to help it progress toward completion. -### NEP Communication +Before submitting a NEP, the author should first attempt to ascertain whether the idea is NEP-able. Vetting an idea publicly before writing a NEP saves the potential author time. Asking the NEAR community first if the idea is original helps prevent effort on something guaranteed to be rejected based on prior discussions. It also helps ensure the idea applies to the entire community. Just because an idea sounds good to the author does not mean it will work for most people in most use cases. -NEP discussions should happen asynchronously within the NEP’s public thread. +In general, the process for socializing an idea is: -However, if a discussion becomes circular and could benefit from a synchronous conversation, any participants on a given NEP can suggest for the moderator to schedule an ad hoc meeting. For example, if a reviewer and author have multiple rounds of comments, they may request a call. The moderator can help coordinate the call and post the registration link on the NEP. The person who requested the call should designate a note taker to post a summary on the NEP after the call. +- **Check prior proposals:** Many ideas for changing NEAR come up frequently. Please search the [Dev Gov Gigs Board](https://devgovgigs.near.social), the [NEAR Forums](https://gov.near.org), and NEPs in this repo before proposing something new. +- **Share the idea:** Submit your [idea](https://www.neardevgov.org/blog/how-to-ideate-in-the-near-developer-governance) on the [Dev Gov Gigs Board](https://devgovgigs.near.social). +- **Get feedback:** The [Dev Gov Gigs Board](https://devgovgigs.near.social) has comment threading which allows the community to ideate, ask questions, wrestle with approaches, etc. If more immediate responses are desired, consider bringing the conversation to the appropriate [Community Group](https://gov.near.org/c/dev/community-groups/103). -When a NEP gets to the final voting stage, the moderator will schedule a public working group meeting to discuss the NEP with the author and formalize the decision. The moderator will first coordinate a time with the author and working group members, and then post the meeting time and registration link on the NEP at least one week in advance. +### Submit a NEP Draft +Following the above initial discussions, the author should submit a NEP draft into the GitHub NEP repository. The draft NEP must follow the [NEP-0000 template](https://github.com/near/NEPs/blob/master/nep-0000-template.md), or else it will fail the review immediately. -### NEP Maintenance -In general, NEPs are no longer modified after they have reached the Final state. +To submit a NEP draft as a pull request, the NEP author should: -## NEP Life Cycle +1. Fork the [NEPs repository](https://github.com/near/NEPs). +2. Copy `nep-0000-template.md` to `neps/nep-0000-my-feature.md` (where “my-feature” is descriptive; don’t assign a NEP number yet). +3. Fill in the NEP following the NEP template guidelines. For the Header Preamble, make sure to set the status as “Draft.” +4. Push this to your GitHub fork and submit a pull request. +5. Now that your NEP has an open pull request, use the pull request number to update your `0000` prefix. For example, if the PR is 305, the NEP should be `neps/nep-0305-my-feature.md`. +6. Push this to your GitHub fork and submit a pull request. Mention the @near/nep-moderators in the comment and turn the PR into a "Ready for Review" state once you believe the NEP is ready for review. + +## NEP Lifecycle +The NEP process begins when an author submits a [NEP draft](#submit-a-nep-draft). The NEP lifecycle consists of three stages: draft, review, and voting, with two possible outcomes: approval or rejection. Throughout the process, various roles play a critical part in moving the proposal forward. Most of the activity happens asynchronously on the NEP within GitHub, where all the roles can communicate and collaborate on revisions and improvements to the proposal. ![NEP Process](https://user-images.githubusercontent.com/110252255/201413632-f72743d6-593e-4747-9409-f56bc38de17b.png) -A given NEP can have one of the following states: -- **Draft**: The first formally tracked stage of a NEP in development. A NEP is merged by a NEP Moderator into the NEP repository when properly formatted. -- **Review**: A NEP moderator marks a NEP as ready for Subject Matter Experts Review. - - If the NEP is not approved within two months, it is automatically rejected. -- **Voting**: This is the final voting period for a NEP. The working group will vote on whether to accept or reject the NEP. This period is limited to two weeks. If during this period necessary normative changes are required, the NEP will revert back to Review. -- **Approved:** If the working group votes to approve, they will move the NEP to Approved. Once approved, Standards NEPs exist in a state of finality and should only be updated to correct errata and add non-normative clarifications. -- **Rejected:** If the working group votes to reject, they will move the NEP to Rejected. -- **Living** - A special status for NEPs that are designed to be continually updated and not reach a state of finality. This includes most notably NEP-0001. +### NEP Stages + +* **Draft:** The first formally tracked stage of a new NEP. This process begins once an author submits a draft proposal and the NEP moderator merges it into the NEP repo when properly formatted. +* **Review:** A NEP moderator marks a NEP as ready for Subject Matter Experts Review. If the NEP is not approved within two months, it is automatically rejected. +* **Voting:** This is the final voting period for a NEP. The working group will vote on whether to accept or reject the NEP. This period is limited to two weeks. If during this period necessary normative changes are required, the NEP will revert to Review. + +### NEP Outcomes -## NEP Roles and Responsibilities -The NEP process has various roles and responsibilities. +* **Approved:** If the working group votes to approve, they will move the NEP to Approved. Once approved, Standards NEPs exist in a state of finality and should only be updated to correct errata and add non-normative clarifications. +* **Rejected:** If the working group votes to reject, they will move the NEP to Rejected. +### NEP Roles and Responsibilities ![author](https://user-images.githubusercontent.com/110252255/181816534-2f92b073-79e2-4e8d-b5b9-b10824958acd.png) **Author**
*Anyone can participate* -- Writes proposal following the standards -- Submits proposal with prototype when ready for review and changes the status to “Draft” -- Addresses comments -- Presents to working group and incorporates necessary changes -- Provides final implementation with sufficient testing and documentation once approved +The NEP author (or champion) is responsible for creating a NEP draft that follows the guidelines. They drive the NEP forward by actively participating in discussions and incorporating feedback. During the voting stage, they may present the NEP to the working group and community, and provide a final implementation with thorough testing and documentation once approved. ![Moderator](https://user-images.githubusercontent.com/110252255/181816650-b1610c0e-6d32-4d2a-a34e-877c702139bd.png) **Moderator**
-*Assigned by working group* +*Assigned by the working group* -- Ensures proposal meets standards - - If proposal needs revisions, provides comments on improvements and keeps status as “Draft” - - If proposal does not meet standards, changes status to “Rejected” - - If proposal is ready for review, changes status to “Review” -- Coordinates working group to assign reviewers and review proposals -- Does not assess the technical feasibility or writes any parts of the proposal +The moderator is responsible for facilitating the process and validating that the NEP follows the guidelines. They do not assess the technical feasibility or write any part of the proposal. They provide comments if revisions are necessary and ensure that all roles are working together to progress the NEP forward. They also schedule and facilitate public voting calls. ![Reviewer](https://user-images.githubusercontent.com/110252255/181816664-a9485ea6-e774-4999-b11d-dc8be6b08f87.png) -**Reviewer** (Subject Matter Experts)
-*Assigned by working group* +**NEP Reviewer** (Subject Matter Experts)
+*Assigned by the working group* -- Gives feedback on proposals -- Assesses technical feasibility of proposals -- Does not have the ability to approve proposal +The reviewer is responsible for reviewing the technical feasibility of a NEP and giving feedback to the author. While they do not have voting power, they play a critical role in providing their voting recommendations along with a summary of the benefits and concerns that were raised in the discussion. Their inputs help everyone involved make a transparent and informed decision. ![Approver](https://user-images.githubusercontent.com/110252255/181816752-521dd147-f56f-4c5c-84de-567b109f21d6.png) -**Approver** (Community Working Groups)
-*Appointed by Pagoda in the bootstrapping phase* +**Approver** (Working Groups)
+*Selected by the Dev Gov DAO in the bootstrapping phase* -- Assigns reviewers to proposals -- Attends working group meetings to review proposals -- Votes to approve or reject proposals - -## What does a successful NEP look like? -Each NEP should have the following parts/sections: +The working group is a selected committee of 3-7 recognized experts who are responsible for coordinating the public review and making decisions on a NEP in a fair and timely manner. There are multiple working groups, each one focusing on a specific ecosystem area, such as the Protocol or Wallet Standards. They assign reviewers to proposals, provide feedback to the author, and attend public calls to vote to approve or reject the NEP. Learn more about the various working groups at [neardevgov.org](http://neardevgov.org/). -1. Preamble - [RFC](https://www.ietf.org/rfc/rfc822.txt)[ 822](https://www.ietf.org/rfc/rfc822.txt) style headers containing meta-data about the NEP, including the NEP number, a short descriptive title, the names, and optionally the contact info for each author, etc. -1. Summary - a short (~200 word) description of the technical issue being addressed. -1. Motivation - The motivation section should clearly explain why the existing contract ecosystem is inadequate to address the problem that the NEP solves. This can include collecting documented support for the NEP from important projects in the NEAR ecosystem. NEP submissions without sufficient motivation may be rejected. -1. Rationale and alternatives - The rationale fleshes out the specification by describing why particular design decisions were made. It should describe alternate designs that were considered and related work, e.g. how the feature is supported in other platforms. -1. Specification - The technical specification should describe the syntax and semantics of the contract or protocol feature. The specification should be detailed enough to allow competing, interoperable implementations for at least the current major NEAR version. -1. Draft Implementation - A draft implementation showing the viability of the proposal must be completed before any NEP is given the “Approved” status. - While there is merit to the approach of reaching consensus on the specification and rationale before writing code, the principle of “rough consensus and running code” is still useful when it comes to resolving many discussions of API details. Once approved, the final implementation must include test code and documentation. -1. Security Implications - If there are security concerns in relation to the NEP, those concerns should be explicitly written out to make sure reviewers of the NEP are aware of them. -1. Drawbacks - Throughout the discussion of a NEP, various ideas will be proposed which are not accepted. Those rejected ideas should be recorded along with the reasoning as to why they were rejected. This both helps record the thought process behind the final version of the NEP as well as preventing people from bringing up the same rejected idea again in subsequent discussions. - In a way this section can be thought of as a breakout section of the Rationale section that is focused specifically on why certain ideas were not ultimately pursued. -1. Unresolved Issues - While a NEP is in draft, ideas can come up which warrant further discussion. Those ideas should be recorded so people know that they are being thought about but do not have a concrete resolution. This helps make sure all issues required for the NEP to be ready for consideration are complete and reduces people duplicating prior discussion. -1. Future possibilities - Future possibilities describes any natural extensions and evolutions to the NEP proposal and how it would affect the project. Try to use this section as a tool to more fully consider all possible interactions with the project in your proposal. Also consider how this all fits into the roadmap for the project and of the relevant sub-teams. -1. Copyright Waiver - All NEPs must be in the public domain. See the bottom of this NEP for an example copyright waiver. - -## NEP Header Preamble -Each NEP must begin with an [RFC](https://www.ietf.org/rfc/rfc822.txt)[ 822](https://www.ietf.org/rfc/rfc822.txt) style header preamble. The headers must appear in the following order. +### NEP Communication -``` - NEP: - Title: - Author: - Status: - DiscussionsTo (Optional): - Type: - Requires (Optional): - Replaces (Optional): - SupersededBy (Optional): - Created: -``` - - -`Title`: The NEP title header should not be more than 4-5 words, describing +NEP discussions should happen asynchronously within the NEP’s public thread. This allows for broad participation and ensures transparency. -`Author`: The Author header lists the names, and optionally the email addresses of all the authors/owners of the NEP. The format of the Author header value must be +However, if a discussion becomes circular and could benefit from a synchronous conversation, any participants on a given NEP can suggest that the moderator schedules an ad hoc meeting. For example, if a reviewer and author have multiple rounds of comments, they may request a call. The moderator can help coordinate the call and post the registration link on the NEP. The person who requested the call should designate a note-taker to post a summary on the NEP after the call. - Random J. User ; - Other I. User +When a NEP gets to the final voting stage, the moderator will schedule a public working group meeting to discuss the NEP with the author and formalize the decision. The moderator will first coordinate a time with the author and working group members, and then post the meeting time and registration link on the NEP at least one week in advance. -if the email address is included, and just +All participants in the NEP process should maintain a professional and respectful code of conduct in all interactions. This includes communicating clearly and promptly and refraining from disrespectful or offensive language. - Random J. User -`DiscussionsTo`: The DiscussionsTo header provides the URL to the current canonical discussion thread for the NEP. +### NEP Playbook -`Type`: The Type header specifies the type of NEP: Standards or Protocol +1. Once an author [submits a NEP draft](#submit-a-nep-draft), the NEP moderators will review their pull request (PR) for structure, formatting, and other errors. Approval criteria are: + * The content is complete and technically sound. The moderators do not consider whether the NEP is likely or not to get accepted. + * The title accurately reflects the content. + * The language, spelling, grammar, sentence structure, and code style are correct and conformant. +2. If the NEP is not ready for approval, the moderators will send it back to the author with specific instructions in the PR. The moderators must complete the review within one week. +3. Once the moderators agree that the PR is ready for review, they will ask the approvers (working group members) to nominate a team of at least two reviewers (subject matter experts) to review the NEP. At least one working group member must explicitly tag the reviewers and comment: `"As a working group member, I'd like to nominate @SME-username and @SME-username as the Subject Matter Experts to review this NEP."` If the assigned reviewers feel that they lack the relevant expertise to fully review the NEP, they can ask the working group to re-assign the reviewers for the NEP. +4. The reviewers must finish the technical review within one week. Technical Review Guidelines: + * First, review the technical details of the proposals and assess their merit. If you have feedback, explicitly tag the author and comment: `"As the assigned Reviewer, I request from @author-username to [ask clarifying questions, request changes, or provide suggestions that are actionable.]."` It may take a couple of iterations to resolve any open comments. + * Second, once the reviewer believes that the NEP is close to the voting stage, explicitly tag the @near/nep-moderators and comment with your technical summary. The Technical Summary must include: + * A recommendation for the working group: `"As the assigned reviewer, I do not have any feedback for the author. I recommend moving this NEP forward and for the working group to [accept or reject] it based on [provide reasoning, including a sense of importance or urgency of this NEP]."` Please note that this is the reviewer's personal recommendation. + * A summary of benefits that surfaced in previous discussions. This should include a concise list of all the benefits that others raised, not just the ones that the reviewer personally agrees with. + * A summary of concerns or blockers, along with their current status and resolution. Again, this should reflect the collective view of all commenters, not just the reviewer's perspective. +5. The NEP author can make revisions and request further reviews from the reviewers. However, if a proposal is in the review stage for more than two months, the moderator will automatically reject it. To reopen the proposal, the author must restart the NEP process again. +6. Once both reviewers complete their technical summary, the moderators will notify the approvers (working group members) that the NEP is in the final comment period. The approvers must fully review the NEP within one week. Approver guidelines: + * First, read the NEP thoroughly. If you have feedback, explicitly tag the author and comment: `"As a working group member, I request from @author-username to [ask clarifying questions, request changes, or provide actionable suggestions.]."` + * Second, once the approver believes the NEP is close to the voting stage, explicitly comment with your voting indication: `"As a working group member, I lean towards [approving OR rejecting] this NEP based on [provide reasoning]."` +7. Once all the approvers indicate their voting indication, the moderator will review the voting indication for a 2/3 majority: + * If the votes lean toward rejection: The moderator will summarize the feedback and close the NEP. + * If the votes lean toward approval: The moderator will schedule a public call (see [NEP Communication](#nep-communication)) for the author to present the NEP and for the working group members to formalize the voting decision. If the working group members agree that the NEP is overall beneficial for the NEAR ecosystem and vote to approve it, then the proposal is considered accepted. After the call, the moderator will summarize the decision on the NEP. +8. The NEP author or other assignees will complete action items from the call. For example, the author will finalize the "Changelog" section on the NEP, which summarizes the benefits and concerns for future reference. -`Created`: The Created header records the date that the NEP was assigned a number, should be in dd-mmm-yyyy format, e.g. 03-Mar-2022. +### Transferring NEP Ownership -`Requires`: NEPs may have a Requires header, indicating the NEP numbers that this NEP depends on. +While a NEP is worked on, it occasionally becomes necessary to transfer ownership of NEPs to a new author. In general, it is preferable to retain the original author as a co-author of the transferred NEP, but that is up to the original author. A good reason to transfer ownership is that the original author no longer has the time or interest in updating it or following through with the NEP process. A bad reason to transfer ownership is that the author does not agree with the direction of the NEP. One aim of the NEP process is to try to build consensus around a NEP, but if that is not possible, an author can submit a competing NEP. -`SupersededBy`: NEPs may also have a SupersededBy header indicating that a NEP has been rendered obsolete by a later document; the value is the number of the NEP that replaces the current document. +If you are interested in assuming ownership of a NEP, you can also do this via pull request. Fork the NEP repository, modify the owner, and submit a pull request. In the PR description, tag the original author and provide a summary of the work that was previously done. Also clearly state the intent of the fork and the relationship of the new PR to the old one. For example: "Forked to address the remaining review comments in NEP \# since the original author does not have time to address them. -`Replaces`: A newer NEP marked with a SupercededBy header must have a Replaces header containing the number of the NEP that it rendered obsolete. +## What does a successful NEP look like? -## Auxiliary Files -Images, diagrams and auxiliary files should be included in a subdirectory of the assets folder for that NEP as follows: assets/nep-N (where N is to be replaced with the NEP number). When linking to an image in the NEP, use relative links such as …/assets/nep-1/image.png +Each NEP should be written in markdown format and follow the [NEP-0000 template](https://github.com/near/NEPs/blob/master/nep-0000-template.md) and include all the appropriate sections, which will make it easier for the NEP reviewers and community members to understand and provide feedback. The most successful NEPs are those that go through collective iteration, with authors who actively seek feedback and support from the community. Ultimately, a successful NEP is one that addresses a specific problem or needs within the NEAR ecosystem, is well-researched, and has the support of the community and ecosystem experts. -## Transferring NEP Ownership -It occasionally becomes necessary to transfer ownership of NEPs to a new author. In general, it is preferable to retain the original author as a co-author of the transferred NEP, but that is up to the original author. A good reason to transfer ownership is because the original author no longer has the time or interest in updating it or following through with the NEP process. A bad reason to transfer ownership is because the author does not agree with the direction of the NEP. One aim of the NEP process is to try to build consensus around a NEP, but if that is not possible, an author can submit a competing NEP. +### Auxiliary Files -If you are interested in assuming ownership of a NEP, you can also do this via pull request. Fork the NEP repository, make your ownership modification, and submit a pull request. In the PR description, tag the original author and provide a summary of the work that was previously done. Also clearly state the intent of the fork and the relationship of the new PR to the old one. For example: "Forked to address the remaining review comments in NEP # since the original author does not have time to address them." +Images, diagrams, and auxiliary files should be included in a subdirectory of the assets folder for that NEP as follows: assets/nep-N (where N is to be replaced with the NEP number). When linking to an image in the NEP, use relative links such as .../assets/nep-1/image.png -## Style Guide +### Style Guide #### NEP numbers -When referring to a NEP by number, it should be written in the hyphenated form NEP-X where Xis the NEP’s assigned number. + +When referring to a NEP by number, it should be written in the hyphenated form NEP-X where X is the NEP's assigned number. #### RFC 2119 -NEPs are encouraged to follow [RFC](https://www.ietf.org/rfc/rfc2119.txt)[ 2119](https://www.ietf.org/rfc/rfc2119.txt) for terminology and to insert the following at the beginning of the Specification section: -The key words “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “MAY”, and “OPTIONAL” in this document are to be interpreted as described in RFC 2119. +NEPs are encouraged to follow [RFC 2119](https://www.ietf.org/rfc/rfc2119.txt) for terminology and to insert the following at the beginning of the Specification section: + +The keywords "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in [RFC 2119](https://www.ietf.org/rfc/rfc2119.txt). + +## NEP Maintenance + +Generally, NEPs are not modifiable after reaching their final state. However, there are occasions when updating a NEP is necessary, such as when discovering a security vulnerability or identifying misalignment with a widely-used implementation. In such cases, an author may submit a NEP extension in a pull request with the proposed changes to an existing NEP document. + +A NEP extension has a higher chance of approval if it introduces clear benefits to existing implementors and does not introduce breaking changes. + +If an author believes that a new extension meets the criteria for its own separate NEP, it is better to submit a new NEP than to modify an existing one. Just make sure to specify any dependencies on certain NEPs. ## References -The content of this document was derived heavily from the PEP, BIP, Rust RFC and EIP standards bootstrap documents: +The content of this document was derived heavily from the PEP, BIP, Rust RFC, and EIP standards bootstrap documents: * Klock, F et al. Rust: RFC-0002: RFC Process. https://github.com/rust-lang/rfcs/blob/master/text/0002-rfc-process.md * Taaki, A. et al. Bitcoin Improvement Proposal: BIP:1, BIP Purpose and Guidelines. https://github.com/bitcoin/bips/blob/master/bip-0001.mediawiki From 3046258d74bf3526f5910c65e80ac540ccf35455 Mon Sep 17 00:00:00 2001 From: mzhangmzz <34969888+mzhangmzz@users.noreply.github.com> Date: Tue, 21 Mar 2023 01:57:26 -0600 Subject: [PATCH 113/150] NEP-399: Flat Storage (#399) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Proposal of Flat Storage to improve state storage reads, which aims to make state storage more stable and make fees more predictable, and sketch the plan for future improvements. --------- Co-authored-by: Damián Parrino Co-authored-by: Marcelo Fornet Co-authored-by: Aleksandr Logunov Co-authored-by: Akhilesh Singhania --- README.md | 33 ++-- neps/nep-0399.md | 482 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 499 insertions(+), 16 deletions(-) create mode 100644 neps/nep-0399.md diff --git a/README.md b/README.md index 33494d582..2b259cecc 100644 --- a/README.md +++ b/README.md @@ -10,22 +10,23 @@ Changes to the protocol specification and standards are called NEAR Enhancement ## NEPs -|NEP # | Title | Author | Status | -|---|---|---|---| -|[0001](https://github.com/near/NEPs/blob/master/neps/nep-0001.md) | NEP Purpose and Guidelines | @jlogelin | Living | -|[0021](https://github.com/near/NEPs/blob/master/neps/nep-0021.md) | Fungible Token Standard (Deprecated) | @evgenykuzyakov | Final | -|[0141](https://github.com/near/NEPs/blob/master/neps/nep-0141.md) | Fungible Token Standard | @evgenykuzyakov @oysterpack | Final | -|[0145](https://github.com/near/NEPs/blob/master/neps/nep-0145.md) | Storage Management | @evgenykuzyakov | Final | -|[0148](https://github.com/near/NEPs/blob/master/neps/nep-0148.md) | Fungible Token Metadata | @robert-zaremba @evgenykuzyakov @oysterpack | Final | -|[0171](https://github.com/near/NEPs/blob/master/neps/nep-0171.md) | Non Fungible Token Standard | @mikedotexe @evgenykuzyakov @oysterpack | Final | -|[0177](https://github.com/near/NEPs/blob/master/neps/nep-0177.md) | Non Fungible Token Metadata | @chadoh @mikedotexe | Final | -|[0178](https://github.com/near/NEPs/blob/master/neps/nep-0178.md) | Non Fungible Token Approval Management | @chadoh @thor314 | Final | -|[0181](https://github.com/near/NEPs/blob/master/neps/nep-0181.md) | Non Fungible Token Enumeration | @chadoh @thor314 | Final | -|[0199](https://github.com/near/NEPs/blob/master/neps/nep-0199.md) | Non Fungible Token Royalties and Payouts | @thor314 @mattlockyer | Final | -|[0245](https://github.com/near/NEPs/blob/master/neps/nep-0245.md) | Multi Token Standard | @zcstarr @riqi @jriemann @marcos.sun | Review | -|[0297](https://github.com/near/NEPs/blob/master/neps/nep-0297.md) | Events Standard | @telezhnaya | Final | -|[0330](https://github.com/near/NEPs/blob/master/neps/nep-0330.md) | Source Metadata | @BenKurrek | Review | -|[0366](https://github.com/near/NEPs/blob/master/neps/nep-0366.md) | Meta Transactions | @ilblackdragon @e-uleyskiy @fadeevab | Draft | +|NEP # | Title | Author | Status | +|---|---|---------------------------------------------|--------| +|[0001](https://github.com/near/NEPs/blob/master/neps/nep-0001.md) | NEP Purpose and Guidelines | @jlogelin | Living | +|[0021](https://github.com/near/NEPs/blob/master/neps/nep-0021.md) | Fungible Token Standard (Deprecated) | @evgenykuzyakov | Final | +|[0141](https://github.com/near/NEPs/blob/master/neps/nep-0141.md) | Fungible Token Standard | @evgenykuzyakov @oysterpack | Final | +|[0145](https://github.com/near/NEPs/blob/master/neps/nep-0145.md) | Storage Management | @evgenykuzyakov | Final | +|[0148](https://github.com/near/NEPs/blob/master/neps/nep-0148.md) | Fungible Token Metadata | @robert-zaremba @evgenykuzyakov @oysterpack | Final | +|[0171](https://github.com/near/NEPs/blob/master/neps/nep-0171.md) | Non Fungible Token Standard | @mikedotexe @evgenykuzyakov @oysterpack | Final | +|[0177](https://github.com/near/NEPs/blob/master/neps/nep-0177.md) | Non Fungible Token Metadata | @chadoh @mikedotexe | Final | +|[0178](https://github.com/near/NEPs/blob/master/neps/nep-0178.md) | Non Fungible Token Approval Management | @chadoh @thor314 | Final | +|[0181](https://github.com/near/NEPs/blob/master/neps/nep-0181.md) | Non Fungible Token Enumeration | @chadoh @thor314 | Final | +|[0199](https://github.com/near/NEPs/blob/master/neps/nep-0199.md) | Non Fungible Token Royalties and Payouts | @thor314 @mattlockyer | Final | +|[0245](https://github.com/near/NEPs/blob/master/neps/nep-0245.md) | Multi Token Standard | @zcstarr @riqi @jriemann @marcos.sun | Review | +|[0297](https://github.com/near/NEPs/blob/master/neps/nep-0297.md) | Events Standard | @telezhnaya | Final | +|[0330](https://github.com/near/NEPs/blob/master/neps/nep-0330.md) | Source Metadata | @BenKurrek | Review | +|[0366](https://github.com/near/NEPs/blob/master/neps/nep-0366.md) | Meta Transactions | @ilblackdragon @e-uleyskiy @fadeevab | Draft | +|[0399](https://github.com/near/NEPs/blob/master/neps/nep-0399.md) | Flat Storage | @Longarithm @mzhangmzz | Review | diff --git a/neps/nep-0399.md b/neps/nep-0399.md new file mode 100644 index 000000000..725be4a50 --- /dev/null +++ b/neps/nep-0399.md @@ -0,0 +1,482 @@ +--- +NEP: 0399 +Title: Flat Storage +Author: Aleksandr Logunov Min Zhang +DiscussionsTo: https://github.com/nearprotocol/neps/pull/0399 +Status: Draft +Type: Protocol Track +Category: Storage +Created: 30-Sep-2022 +--- + +## Summary + +This NEP proposes the idea of Flat Storage, which stores a flattened map of key/value pairs of the current +blockchain state on disk. Note that original Trie (persistent merkelized trie) is not removed, but Flat Storage +allows to make storage reads faster, make storage fees more predictable and potentially decrease them. + +## Motivation + +Currently, the blockchain state is stored in our storage only in the format of persistent merkelized tries. +Although it is needed to compute state roots and prove the validity of states, reading from it requires a +traversal from the trie root to the leaf node that contains the key value pair, which could mean up to +2 * key_length disk accesses in the worst case. + +In addition, we charge receipts by the number of trie nodes they touched (TTN cost). Note that the number +of touched trie node does not always equal to the key length, it depends on the internal trie structure. +Based on some feedback from contract developers collected in the past, they are interested in predictable fees, +but TTN costs are annoying to predict and can lead to unexpected excess of the gas limit. They are also a burden +for NEAR Protocol client implementations, i.e. nearcore, as exact TTN number must be computed deterministically +by all clients. This prevents storage optimizations that use other strategies than nearcore uses today. + +With Flat Storage, number of disk reads is reduced from worst-case 2 * key_length to exactly 2, storage read gas +fees are simplified by getting rid of TTN cost, and potentially can be further reduced because fewer disk reads +are needed. + +## Rationale and alternatives + +Q: Why is this design the best in the space of possible designs? + +A: Space of possible designs is quite big here, let's show some meaningful examples. + +The most straightforward one is just to increase TTN, or align it with biggest possible value, or alternatively increase +the base fees for storage reads and writes. However, technically the biggest TTN could be 4096 as of today. And we tend +to strongly avoid increasing fees, because it may break existing contract calls, not even mentioning that it would greatly +reduce capacity of NEAR blocks, because for current mainnet usecases depth is usually below 20. + +We also consider changing tree type from Trie to AVL, B-tree, etc. to make number of traversed nodes more stable and +predictable. But we approached AVL idea, and implementation turned out to be tricky, so we didn't go +much further than POC here: https://github.com/near/nearcore/discussions/4815. Also for most key-value pairs +tree depth will actually increase - for example, if you have 1M keys, depth is always 20, and it would cause increasing +fees as well. Size of intermediate node also increases, because we have to need to store a key there to decide whether +we should go to the left or right child. + +Separate idea is to get rid of global state root completely: https://github.com/near/NEPs/discussions/425. Instead, +we could track the latest account state in the block where it was changed. But after closer look, it brings us to +similar questions - if some key was untouched for a long time, it becomes harder to find exact block to find latest +value for it, and we need some tree-shaped structure again. Because ideas like that could be also extremely invasive, +we stopped considering them at this point. + +Other ideas around storage include exploring databases other than RocksDB, or moving State to a separate database. +We can tweak State representation, i.e. start trie key from account id to achieve data locality within +the same account. However, Flat Storage main goal is speed up reads and make their costs predictable, and these ideas +are orthogonal to that, although they still can improve storage in other ways. + +Q: What other designs have been considered and what is the rationale for not choosing them? + +A: There were several ideas on Flat Storage implementation. One of questions is whether we need global flat storage +for all shards or separate flat storages. Due to how sharding works, we have make flat storages separate, because in +the future node may have to catchup new shard while already tracking old shards, and flat storage heads (see +Specification) must be different for these shards. + +Flat storage deltas are another tricky part of design, but we cannot avoid them, because at certain points of time +different nodes can disagree what is the current chain head, and they have to support reads for some subset of latest +blocks with decent speed. We can't really fallback to Trie in such cases because storage reads for it are much slower. + +Another implementation detail is where to put flat storage head. The planned implementation doesn't rely on that +significantly and can be changed, but for MVP we assume flat storage head = chain final head as a simplest solution. + +Q: What is the impact of not doing this? + +A: Storage reads will remain inefficiently implemented and cost more than they should, and the gas fees will remain +difficult for the contract developers to predict. + +## Specification + +The key idea of Flat Storage is to store a direct mapping from trie keys to values in the DB. +Here the values of this mapping can be either the value corresponding to the trie key itself, +or the value ref, a hash that points to the address of the value. If the value itself is stored, +only one disk read is needed to look up a value from flat storage, otherwise two disk reads are needed if the value +ref is stored. We will discuss more in the following section for whether we use values or value refs. +For the purpose of high level discussion, it suffices to say that with Flat Storage, +at most two disk reads are needed to perform a storage read. + +The simple design above won't work because there could be forks in the chain. In the following case, FlatStorage +must support key value lookups for states of the blocks on both forks. +``` + / Block B1 - Block B2 - ... +block A + \ Block C1 - Block C2 - ... +``` + +The handling of forks will be the main consideration of the following design. More specifically, +the design should satisfy the following requirements, +1) It should support concurrent block processing. Blocks on different forks are processed + concurrently in the nearcore Client code, the struct which responsibility includes receiving blocks from network, + scheduling applying chunks and writing results of that to disk. Flat storage API must be aligned with that. +2) In case of long forks, block processing time should not be too much longer than the average case. + We don’t want this case to be exploitable. It is acceptable that block processing time is 200ms longer, + which may slow down block production, but probably won’t cause missing blocks and chunks. + 10s delays are not acceptable and may lead to more forks and instability in the network. +3) The design must be able to decrease storage access cost in all cases, + since we are going to change the storage read fees based on flat storage. + We can't conditionally enable Flat Storage for some blocks and disable it for other, because + the fees we charge must be consistent. + +The mapping of key value pairs FlatStorage stored on disk matches the state at some block. +We call this block the head of flat storage, or the flat head. During block processing, +the flat head is set to the last final block. The Doomslug consensus algorithm +guarantees that if a block is final, all future final blocks must be descendants of this block. +In other words, any block that is not built on top of the last final block can be discarded because they +will never be finalized. As a result, if we use the last final block as the flat head, any block +FlatStorage needs to process is a descendant of the flat head. + +To support key value lookups for other blocks that are not the flat head, FlatStorage will +store key value changes(deltas) per block for these blocks. +We call these deltas FlatStorageDelta (FSD). Let’s say the flat storage head is at block h, +and we are applying transactions based on block h’. Since h is the last final block, +h is an ancestor of h'. To access the state at block h', we need FSDs of all blocks between h and h'. +Note that all these FSDs must be stored in memory, otherwise, the access of FSDs will trigger +more disk reads and we will have to set storage key read fee higher. + +### FSD size estimation + +We prefer to store deltas in memory, because memory read is much faster than disk read, and even a single extra RocksDB +access requires increasing storage fees, which is not desirable. To reduce delta size, we will store hashes of trie keys +instead of keys, because deltas are read-only. Now let's carefully estimate FSD size. + +We can do so using protocol fees as of today. Assume that flat state stores a mapping from keys to value refs. +Maximal key length is ~2 KiB which is the limit of contract data key size. During wasm execution, we pay +`wasm_storage_write_base` = 64 Ggas per call. Entry size is 68 B for key hash and value ref. +Then the total size of keys changed in a block is at most +`chunk_gas_limit / gas_per_entry * entry_size * num_shards = (1300 Tgas / 64 Ggas) * 68 B * 4 ~= 5.5 MiB`. + +Assuming that we can increase RAM requirements by 1 GiB, we can afford to store deltas for 100-200 blocks +simultaneously. + +Note that if we store a value instead of value ref, size of FSDs can potentially be much larger. +Because value limit is 4 MiB, we can’t apply previous argument about base cost. +Since `wasm_storage_write_value_byte` = 31 Mgas, values contribution to FSD size can be estimated as +`(1300 Tgas / storage_write_value_byte * num_shards)`, or ~167 MiB. Same estimation for trie keys gives 54 MiB. +The advantage of storing values instead of value refs is that it saves one disk read if the key has been +modified in the recent blocks. It may be beneficial if we get many transactions or receipts touching the same +trie keys in consecutive blocks, but it is hard to estimate the value of such benefits without more data. +We may store only short values ("inlining"), but this idea is orthogonal and can be applied separately. + +### Protocol changes + +Flat Storage itself doesn't change protocol. We only change impacted storage costs to reflect changes in performance. Below we describe reads and writes separately. + +#### Storage Reads + +Latest proposal for shipping storage reads is [here](https://github.com/near/nearcore/issues/8006#issuecomment-1473718509). +It solves several issues with costs, but the major impact of flat storage is that essentially for reads +`wasm_touching_trie_node` and `wasm_read_cached_trie_node` are reduced to 0. Reason is that before we had to cover costs +of reading nodes from memory or disk, and with flat storage we make only 2 DB reads. + +Latest up-to-date gas and compute costs can be found in nearcore repo. + +#### Storage Writes + +Storage writes are charged similarly to reads and include TTN as well, because updating the leaf trie +node which stores the value to the trie key requires updating all trie nodes on the path leading to the leaf node. +All writes are committed at once in one db transaction at the end of block processing, outside of runtime after +all receipts in a block are executed. However, at the time of execution, runtime needs to calculate the cost, +which means it needs to know how many trie nodes the write affects, so runtime will issue a read for every write +to calculate the TTN cost for the write. Such reads cannot be replaced by a read in FlatStorage because FlatStorage does +not provide the path to the trie node. + +There are multiple proposals on how storage writes can work with FlatStorage. +- Keep it the same. The cost of writes remain the same. Note that this can increase the cost for writes in + some cases, for example, if a contract first read from a key and then writes to the same key in the same chunk. + Without FlatStorage, the key will be cached in the chunk cache after the read, so the write will cost less. + With FlatStorage, the read will go through FlatStorage, the write will not find the key in the chunk cache and + it will cost more. +- Remove the TTN cost from storage write fees. Currently, there are two ideas in this direction. + - Charge based on maximum depth of a contract’s state, instead of per-touch-trie node. + - Charge based on key length only. + + Both of the above ideas would allow us to get rid of trie traversal ("reads-for-writes") from the critical path of + block execution. However, + it is unclear at this point what the new cost would look like and whether further optimizations are needed + to bring down the cost for writes in the new cost model. + +See https://gov.near.org/t/storage-write-optimizations/30083 for more details. + +While storage writes are not fully implemented yet, we may increase parameter compute cost for storage writes implemented +in https://github.com/near/NEPs/pull/455 as an intermediate solution. + +### Migration Plan +There are two main questions regarding to how to enable FlatStorage. +1) Whether there should be database migration. The main challenge of enabling FlatStorage will be to build the flat state + column, which requires iterating the entire state. Estimations showed that it takes 10 hours to build + flat state for archival nodes and 5 hours for rpc and validator nodes in 8 threads. The main concern is that if + it takes too long for archival node to migrate, + they may have a hard time catching up later since the block processing speed of archival nodes is not very fast. + + Alternatively, we can build the flat state in a background process while the node is running. This provides a better + experience for both archival and validator nodes since the migration process is transient to them. It would require + more implementation effort from our side. + + We currently proceed with background migration using 8 threads. +2) Whether there should be a protocol upgrade. The enabling of FlatStorage itself does not require a protocol upgrade, since +it is an internal storage implementation that doesn't change protocol level. However, a protocol upgrade is needed + if we want to adjust fees based on the storage performance with FlatStorage. These two changes can happen in one release, + or we can be release them separately. We propose that the enabling of FlatStorage and the protocol upgrade + to adjust fees should happen in separate release to reduce the risk. The period between the two releases can be + used to test the stability and performance of FlatStorage. Because it is not a protocol change, it is easy to roll back + the change in case any issue arises. + +## Reference Implementation +FlatStorage will implement the following structs. + +`FlatStorageChunkView`: interface for getting value or value reference from flat storage for +specific shard, block hash and trie key. In current logic we plan to make it part of `Trie`, +and all trie reads will be directed to this object. Though we could work with chunk hashes, we don't, +because block hashes are easier to navigate. + +`FlatStorage`: API for interacting with flat storage for fixed shard, including updating head, + adding new delta and creating `FlatStorageChunkView`s. + for example, all block deltas that are stored in flat storage and the flat + storage head. `FlatStorageChunkView` can access `FlatStorage` to get the list of + deltas it needs to apply on top of state of current flat head in order to + compute state of a target block. + +`FlatStorageManager`: owns flat storages for all shards, being stored in `NightshadeRuntime`, accepts + updates from `Chain` side, caused by successful processing of chunk or block. + +`FlatStorageCreator`: handles flat storage structs creation or initiates background creation (aka migration +process) if flat storage data is not presend on DB yet. + +`FlatStateDelta`: a HashMap that contains state changes introduced in a chunk. They can be applied +on top the state at flat storage head to compute state at another block. + +The reason for having separate flat storages that there are two modes of block processing, +normal block processing and block catchups. +Since they are performed on different ranges of blocks, flat storage need to be able to support +different range of blocks on different shards. Therefore, we separate the flat storage objects +used for different shards. + +### DB columns +`DBCol::FlatState` stores a mapping from trie keys to the value corresponding to the trie keys, +based on the state of the block at flat storage head. +- *Rows*: trie key (`Vec`) +- *Column type*: `ValueRef` + +`DBCol::FlatStateDeltas` stores all existing FSDs as mapping from `(shard_id, block_hash, trie_key)` to the `ValueRef`. +To read the whole delta, we read all values for given key prefix. This delta stores all state changes introduced in the +given shard of the given block. +- *Rows*: `{ shard_id, block_hash, trie_key }` +- *Column type*: `ValueRef` + +Note that `FlatStateDelta`s needed are stored in memory, so during block processing this column won't be used + at all. This column is only used to load deltas into memory at `FlatStorage` initialization time when node starts. + +`DBCol::FlatStateMetadata` stores miscellaneous data about flat storage layout, including current flat storage +head, current creation status and info about deltas existence. We don't specify exact format here because it is under +discussion and can be tweaked until release. + +Similarly, flat head is also stored in `FlatStorage` in memory, so this column is only used to initialize + `FlatStorage` when node starts. + +### `FlatStateDelta` +`FlatStateDelta` stores a mapping from trie keys to value refs. If the value is `None`, it means the key is deleted +in the block. +```rust +pub struct FlatStateDelta(HashMap, Option>); +``` + +```rust +pub fn from_state_changes(changes: &[RawStateChangesWithTrieKey]) -> FlatStateDelta +``` +Converts raw state changes to flat state delta. The raw state changes will be returned as part of the result of +`Runtime::apply_transactions`. They will be converted to `FlatStateDelta` to be added +to `FlatStorage` during `Chain::postprocess_block` or `Chain::catch_up_postprocess`. + +### `FlatStorageChunkView` +`FlatStorageChunkView` will be created for a shard `shard_id` and a block `block_hash`, and it can perform +key value lookup for the state of shard `shard_id` after block `block_hash` is applied. +```rust +pub struct FlatStorageChunkView { +/// Used to access flat state stored at the head of flat storage. +store: Store, +/// The block for which key-value pairs of its state will be retrieved. The flat state +/// will reflect the state AFTER the block is applied. +block_hash: CryptoHash, +/// Stores the state of the flat storage +flat_storage: FlatStorage, +} +``` + +`FlatStorageChunkView` will provide the following interface. +```rust +pub fn get_ref( + &self, + key: &[u8], +) -> Result, StorageError> +``` +Returns the value or value reference corresponding to the given `key` +for the state that this `FlatStorageChunkView` object represents, i.e., the state that after +block `self.block_hash` is applied. + +### `FlatStorageManager` + +`FlatStorageManager` will be stored as part of `ShardTries` and `NightshadeRuntime`. Similar to how `ShardTries` is used to +construct new `Trie` objects given a state root and a shard id, `FlatStorageManager` is used to construct +a new `FlatStorageChunkView` object given a block hash and a shard id. + +```rust +pub fn new_flat_storage_chunk_view( + &self, + shard_id: ShardId, + block_hash: Option, +) -> FlatStorageChunkView +``` +Creates a new `FlatStorageChunkView` to be used for performing key value lookups on the state of shard `shard_id` +after block `block_hash` is applied. + +```rust +pub fn get_flat_storage( + &self, + shard_id: ShardId, +) -> Result +``` +Returns the `FlatStorage` for the shard `shard_id`. This function is needed because even though +`FlatStorage` is part of `NightshadeRuntime`, `Chain` also needs access to `FlatStorage` to update flat head. +We will also create a function with the same in `NightshadeRuntime` that calls this function to provide `Chain` to access +to `FlatStorage`. + +```rust +pub fn remove_flat_storage( + &self, + shard_id: ShardId, +) -> Result +``` + +Removes flat storage for shard if we stopped tracking it. + +###`FlatStorage` +`FlatStorage` is created per shard. It provides information to which blocks the flat storage +on the given shard currently supports and what block deltas need to be applied on top the stored +flat state on disk to get the state of the target block. + +```rust +fn get_blocks_to_head( + &self, + target_block_hash: &CryptoHash, +) -> Result, FlatStorageError> +``` +Returns the list of deltas between blocks `target_block_hash` (inclusive) and flat head (exclusive), +Returns an error if `target_block_hash` is not a direct descendent of the current flat head. +This function will be used in `FlatStorageChunkView::get_ref`. Note that we can't call it once and store during applying +chunk, because in parallel to that some block can be processed and flat head can be updated. + +```rust +fn update_flat_head(&self, new_head: &CryptoHash) -> Result<(), FlatStorageError> +``` +Updates the head of the flat storage, including updating the flat head in memory and on disk, +update the flat state on disk to reflect the state at the new head, and gc the `FlatStateDelta`s that +are no longer needed from memory and from disk. + +```rust +fn add_block( + &self, + block_hash: &CryptoHash, + delta: FlatStateDelta, +) -> Result +``` + +Adds `delta` to `FlatStorage`, returns a `StoreUpdate` object that includes DB transaction to be committed to persist +that change. + +```rust +fn get_ref( + &self, + block_hash: &CryptoHash, + key: &[u8], +) -> Result, FlatStorageError> +``` + +Returns `ValueRef` from flat storage state on top of `block_hash`. Returns `None` if key is not present, or an error if +block is not supported. + +### Thread Safety +We should note that the implementation of `FlatStorage` must be thread safe because it can +be concurrently accessed by multiple threads. A node can process multiple blocks at the same time +if they are on different forks, and chunks from these blocks can trigger storage reads in parallel. +Therefore, `FlatStorage` will be guarded by a `RwLock` so its access can be shared safely: + +```rust +pub struct FlatStorage(Arc>); +``` + +## Drawbacks + +The main drawback is that we need to control total size of state updates in blocks after current final head. +current testnet/mainnet load amount of blocks under final head doesn't exceed 5 in 99.99% cases, we still have to +consider extreme cases, because Doomslug consensus doesn't give guarantees / upper limit on that. If we don't consider +this at all and there is no finality for a long time, validator nodes can crash because of too many FSDs of memory, and +chain slows down and stalls, which can have a negative impact on user/validator experience and reputation. For now, we +claim that we support enough deltas in memory for chain to be finalized, and the proper discussions are likely to happen +in NEPs like https://github.com/near/NEPs/pull/460. + +Risk of DB corruption slightly increases, and it becomes harder to replay blocks on chain. While `Trie` entries are +essentially immutable (in fact, value for each key is +unique, because key is a value hash), `FlatStorage` is read-modify-write, because values for the same `TrieKey` can be +completely different. We believe that such flat mapping is reasonable to maintain anyway, as for newly discovered state +sync idea. But if some change was applied incorrectly, we may have to recompute the whole flat storage, and for block +hashes before flat head we can't access flat storage at all. + +Though Flat Storage significantly reduces amount of storage reads, we have to keep it up-to-date, which results in 1 +extra disk write for changed key, and 1 auxiliary disk write + removal for each FSD. Disk requirements also slightly +increase. We think it is acceptable, because actual disk writes are executed in background and are not a bottleneck +for block processing. For storage write in general Flat Storage is even a net improvement, because it removes +necessity to traverse changed nodes during write execution ("reads-for-writes"), and we can apply optimizations +there (see "Storage Writes" section). + +Implementing FlatStorage will require a lot of engineering effort and introduce code that will make the codebase more +complicated. In particular, we had to extend `RuntimeAdapter` API with flat storage-related method after thorough +considerations. We are confident that FlatStorage will bring a lot of performance benefit, but we can only measure the exact +improvement after the implementation. We may find that the benefit FlatStorage brings is not +worth the effort, but it is very unlikely. + +It will make the state rollback harder in the future when we enable challenges in phase 2 of sharding. +When a challenge is accepted and the state needs to be rolled back to a previous block, the entire flat state needs to +be rebuilt, which could take a long time. Alternatively, we could postpone garbage collection of deltas and add support +of applying them backwards. + +Speaking of new sharding phases, once nodes are no longer tracking all shards, Flat Storage must have support for adding +or removing state for some specific shard. Adding new shard is a tricky but natural extension of catchup process. Our +current approach for removal is to iterate over all entries in `DBCol::FlatState` and find out for each trie key to +which shard it belongs to. We would be happy to assume that each shard is represented by set of +contiguous ranges in `DBCol::FlatState` and make removals simpler, but this is still under discussion. + +Last but not least, resharding is not supported by current implementation yet. + +## Future possibilities + +Flat Storage maintains all state keys in sorted order, which seems beneficial. We currently investigate opportunity to +speed up state sync: instead of traversing state part in Trie, we can extract range of keys and values from Flat Storage +and build range of Trie nodes based on it. It is well known that reading Trie nodes is a bottleneck for state sync as +well. + +## Changelog + +### 1.0.0 - Initial Version + +The NEP was approved by Protocol Working Group members on March 16, 2023 ([meeting recording](https://www.youtube.com/watch?v=4VxRoKwLXIs)): + +- [Bowen's vote](https://github.com/near/NEPs/pull/399#issuecomment-1467010125) +- [Marcelo's vote](https://github.com/near/NEPs/pull/399#pullrequestreview-1341069564) +- [Marcin's vote](https://github.com/near/NEPs/pull/399#issuecomment-1465977749) + +#### Benefits + +* The proposal makes serving reads more efficient; making the NEAR protocol cheaper to use and increasing the capacity of the network; +* The proposal makes estimating gas costs for a transaction easier as the fees for reading are no longer a function of the trie structure whose shape the smart contract developer does not know ahead of time and can continuously change. +* The proposal should open doors to enabling future efficiency gains in the protocol and further simplifying gas fee estimations. +* 'Secondary' index over the state data - which would allow further optimisations in the future. + +#### Concerns + +| # | Concern | Resolution | Status | +| - | - | - | - | +| 1 | The cache requires additional database storage | There is an upper bound on how much additional storage is needed. The costs for the additional disk storage should be negligible | Not an issue | +| 2 | Additional implementation complexity | Given the benefits of the proposal, I believe the complexity is justified | not an issue | +| 3 | Additional memory requirement | Most node operators are already operating over-provisioned machines which can handle the additional memory requirement. The minimum requirements should be raised but it appears that minimum requirements are already not enough to operate a node | This is a concern but it is not specific to this project | +| 4 | Slowing down the read-update-write workload | This is common pattern in smart contracts so indeed a concern. However, there are future plans on how to address this by serving writes from the flat storage as well which will also reduce the fees of serving writes and make further improvements to the NEAR protocol | This is a concern but hopefully will be addressed in future iterations of the project | + +## Copyright +[copyright]: #copyright + +Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). From b788cbd312be6e293e346bb12e50a4cd675ea0f7 Mon Sep 17 00:00:00 2001 From: Andrei Kashin Date: Tue, 21 Mar 2023 14:51:32 +0100 Subject: [PATCH 114/150] NEP-455: Parameter Compute Costs (#455) NEP for Parameter Compute Costs (formerly known as Parameter Weights). For the context, this NEP was previously named "Parameter Weights" and the idea was originally proposed in https://gov.near.org/t/proposal-gas-weights-to-fight-instability-to-due-to-undercharging/30919. Now it's renamed into "Parameter Compute Cost" to more accurately represent the fact that it is about accounting how much compute time the parameters cost and using it to limit the chunk processing time. --- README.md | 1 + neps/nep-0455.md | 237 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 238 insertions(+) create mode 100644 neps/nep-0455.md diff --git a/README.md b/README.md index 2b259cecc..124a8d2a1 100644 --- a/README.md +++ b/README.md @@ -27,6 +27,7 @@ Changes to the protocol specification and standards are called NEAR Enhancement |[0330](https://github.com/near/NEPs/blob/master/neps/nep-0330.md) | Source Metadata | @BenKurrek | Review | |[0366](https://github.com/near/NEPs/blob/master/neps/nep-0366.md) | Meta Transactions | @ilblackdragon @e-uleyskiy @fadeevab | Draft | |[0399](https://github.com/near/NEPs/blob/master/neps/nep-0399.md) | Flat Storage | @Longarithm @mzhangmzz | Review | +|[0455](https://github.com/near/NEPs/blob/master/neps/nep-0455.md) | Parameter Compute Costs | @akashin @jakmeier | Final | diff --git a/neps/nep-0455.md b/neps/nep-0455.md new file mode 100644 index 000000000..070523388 --- /dev/null +++ b/neps/nep-0455.md @@ -0,0 +1,237 @@ +--- +NEP: 455 +Title: Parameter Compute Costs +Author: Andrei Kashin , Jakob Meier +DiscussionsTo: https://github.com/nearprotocol/neps/pull/455 +Status: Draft +Type: Protocol Track +Category: Runtime +Created: 26-Jan-2023 +--- + +## Summary + +Introduce compute costs decoupled from gas costs for individual parameters to safely limit the compute time it takes to process the chunk while avoiding adding breaking changes for contracts. + +## Motivation + +For NEAR blockchain stability, we need to ensure that blocks are produced regularly and in a timely manner. + +The chunk gas limit is used to ensure that the time it takes to validate a chunk is strictly bounded by limiting the total gas cost of operations included in the chunk. +This process relies on accurate estimates of gas costs for individual operations. + +Underestimating these costs leads to *undercharging* which can increase the chunk validation time and slow down the chunk production. + +As a concrete example, in the past we undercharged contract deployment. +The responsible team has implemented a number of optimizations but a gas increase was still necessary. +[Meta-pool](https://github.com/Narwallets/meta-pool/issues/21) and [Sputnik-DAO](https://github.com/near-daos/sputnik-dao-contract/issues/135) were affected by this change, among others. +Finding all affected parties and reaching out to them before implementing the change took a lot of effort, prolonging the period where the network was exposed to the attack. + +Another motivating example is the upcoming incremental deployment of Flat Storage, where during one of the intermediate stages we expect the storage operations to be undercharged. +See the explanation in the next section for more details. + +## Rationale + +Separating compute costs from gas costs will allow us to safely limit the compute usage for processing the chunk while still keeping the gas prices the same and thus not breaking existing contracts. + +An important challenge with undercharging is that it is not possible to disclose them widely because it could be used to increase the chunk production time thereby impacting the stability of the network. +Adjusting the compute cost for undercharged parameter eliminates the security concern and allows us to publicly discuss the ways to solve the undercharging (optimize implementation, smart contract or increasing the gas cost). + +This design is easy to implement and simple to reason about and provides a clear way to address existing undercharging issues. +If we don't address the undercharging problems, we increase the risks that they will be exploited. + +Specifically for Flat Storage deployment, we [plan](https://github.com/near/nearcore/issues/8006) to stop charging TTN (touching trie node) gas costs, however the intermediate implementation (read-only Flat Storage) will still incur these costs during writes introducing undercharging. +Setting temporary high compute costs for writes will ensure that this undercharging does not lead to long chunk processing times. + +## Alternatives + +### Increase the gas costs for undercharged operations +We could increase the gas costs for the operations that are undercharged to match the computational time it takes to process them according to the rule 1ms = 1TGas. + +Pros: +- Does not require any new code or design work (but still requires a protocol version bump) +- Security implications are well-understood + +Cons: +- Can break contracts that rely on current gas costs, in particular steeply increasing operating costs for the most active users of the blockchain (aurora and sweat) +- Doing this safely and responsibly requires prior consent by the affected parties which is hard to do without disclosing security-sensitive information about undercharging in public + +In case of flat storage specifically, using this approach will result in a large increase in storage write costs (breaking many contracts) to enable safe deployment of read-only flat storage and later a correction of storage write costs when flat storage for writes is rolled out. +With compute costs, we will be able to roll out the read-only flat storage with minimal impact on deployed contracts. + +### Adjust the gas chunk limit +We could continuously measure the chunk production time in nearcore clients and compare it to the gas burnt. +If the chunk producer observes undercharging, it decreases the limit. +If there is overcharging, the limit can be increased up to a limit of at most 1000 Tgas. +To make such adjustment more predictable under spiky load, we also [limit](https://nomicon.io/Economics/Economic#transaction-fees) the magnitude of change of gas limit by 0.1% per block. + +Pros: +- Prevents moderate undercharging from stalling the network +- No protocol change necessary (as this feature is already [a part of the protocol](https://nomicon.io/Economics/Economic#transaction-fees)), we could easily experiment and revert if it does not work well + +Cons: +- Very broad granularity --- undercharging in one parameter affects all users, even those that never use the undercharged parts +- Dependence on validator hardware --- someone running overspecced hardware will continuously want to increase the limit, others might run with underspecced hardware and continuously want to decrease the limit +- Malicious undercharging attacks are unlikely to be prevented by this --- a single 10x undercharged receipt still needs to be processed using the old limit. +Adjusting 0.1% per block means 100 chunks can only change by a maximum of 1.1x and 1000 chunks could change up to x2.7 +- Conflicts with transaction and receipt limit --- A transaction or receipt can (today) use up to 300Tgas. +The effective limit per chunk is `gas_limit` + 300Tgas since receipts are added to a chunk until one exceeds the limit and the last receipt is not removed. +Thus a gas limit of 0gas only reduces the effective limit from 1300Tgas to 300Tgas, which means a single 10x undercharged receipt can still result in a chunk with compute usage of 3 seconds (equivalent to 3000TGas) + +### Allow skipping chunks in the chain +Slow chunk production in one shard can introduce additional user-visible latency in all shards as the nodes expect a regular and timely chunk production during normal operation. +If processing the chunk takes much longer than 1.3s, it can cause the corresponding block and possibly more consecutive blocks to be skipped. + +We could extend the protocol to produce empty chunks for some of the shards within the block (effectively skipping them) when processing the chunk takes longer than expected. +This way will still ensure a regular block production, at a cost of lower throughput of the network in that shard. +The chunk should still be included in a later block to avoid stalling the affected shard. + +Pros: +- Fast and automatic adaptation to the blockchain workload + +Cons: +- For the purpose of slashing, it is hard to distinguish situations when the honest block producer skips chunk due to slowness from the situations when the block producer is offline or is maliciously stalling the block production. We need some mechanism (e.g. on-chain voting) for nodes to agree that the chunk was skipped legitimately due to slowness as otherwise we introduce new attack vectors to stall the network + +## Specification + +- **Chunk Compute Usage** -- total compute time spent on processing the chunk + +- **Chunk Compute Limit** -- upper-bound for compute time spent on processing the chunk + +- **Parameter Compute Cost** -- the numeric value in seconds corresponding to compute time that it takes to include an operation into the chunk + +Today, gas has two somewhat orthogonal roles: + +1. Gas is money. It is used to avoid spam by charging users +2. Gas is CPU time. It defines how many transactions fit in a chunk so that validators can apply it within a second + +The idea is to decouple these two by introducing parameter compute costs. +Each gas parameter still has a gas cost that determines what users have to pay. +But when filling a chunk with transactions, parameter compute cost is used to estimate CPU time. + +Ideally, all compute costs should match corresponding gas costs. +But when we discover undercharging issues, we can set a higher compute cost (this would require a protocol upgrade). +The stability concern is then resolved when the compute cost becomes active. + +The ratio between compute cost and gas cost can be thought of as an undercharging factor. +If a gas cost is 2 times too low to guarantee stability, compute cost will be twice the gas cost. +A chunk will be full 2 times faster when gas for this parameter is burned. +This deterministically throttles the throughput to match what validators can actually handle. + +Compute costs influence the gas price adjustment logic described in https://nomicon.io/Economics/Economic#transaction-fees. +Specifically, we're now using compute usage instead of gas usage in the formula to make sure that the gas price increases if chunk processing time is close to the limit. + +Compute costs **do not** count towards the transaction/receipt gas limit of 300TGas, as that might break existing contracts by pushing their method calls over this limit. + +Compute costs are static for each protocol version. + +### Using Compute Costs +Compute costs different from gas costs are only a temporary solution. +Whenever we introduce a compute cost, we as the community can discuss this publicly and find a solution to the specific problem together. + +For any active compute cost, a tracking GitHub issue in [`nearcore`](https://github.com/near/nearcore) should be created, tracking work towards resolving the undercharging. The reference to this issue should be added to this NEP. + +In the best case, we find technical optimizations that allow us to decrease the compute cost to match the existing gas cost. + +In other cases, the only solution is to increase the gas cost. +But the dApp developers who are affected by this change should have a chance to voice their opinion, suggest alternatives, and implement necessary changes before the gas cost is increased. + +## Reference Implementation + +The compute cost is a numeric value represented as `u64` in time units. +Value 1 corresponds to `10^-15` seconds or 1fs (femtosecond) to match the gas costs scale. + +By default, the parameter compute cost matches the corresponding gas cost. + +Compute costs should be applicable to all gas parameters, specifically including: +- [`ExtCosts`](https://cs.github.com/near/nearcore/blob/6e08a41084c632010b1d4c42132ad58ecf1398a2/core/primitives-core/src/config.rs#L377) +- [`ActionCosts`](https://cs.github.com/near/nearcore/blob/6e08a41084c632010b1d4c42132ad58ecf1398a2/core/primitives-core/src/config.rs#L456) + +Changes necessary to support `ExtCosts`: +1. Track compute usage in [`GasCounter`](https://cs.github.com/near/nearcore/blob/51670e593a3741342a1abc40bb65e29ba0e1b026/runtime/near-vm-logic/src/gas_counter.rs#L47) struct +2. Track compute usage in [`VMOutcome`](https://cs.github.com/near/nearcore/blob/056c62183e31e64cd6cacfc923a357775bc2b5c9/runtime/near-vm-logic/src/logic.rs#L2868) struct (alongside `burnt_gas` and `used_gas`) +3. Store compute usage in [`ActionResult`](https://cs.github.com/near/nearcore/blob/6d2f3fcdd8512e0071847b9d2ca10fb0268f469e/runtime/runtime/src/lib.rs#L129) and aggregate it across multiple actions by modifying [`ActionResult::merge`](https://cs.github.com/near/nearcore/blob/6d2f3fcdd8512e0071847b9d2ca10fb0268f469e/runtime/runtime/src/lib.rs#L141) +4. Store compute costs in [`ExecutionOutcome`](https://cs.github.com/near/nearcore/blob/578983c8df9cc36508da2fb4a205c852e92b211a/runtime/runtime/src/lib.rs#L266) and [aggregate them across all transactions](https://cs.github.com/near/nearcore/blob/578983c8df9cc36508da2fb4a205c852e92b211a/runtime/runtime/src/lib.rs#L1279) +5. Enforce the chunk compute limit when the chunk is [applied](https://cs.github.com/near/nearcore/blob/6d2f3fcdd8512e0071847b9d2ca10fb0268f469e/runtime/runtime/src/lib.rs#L1325) + +Additional changes necessary to support `ActionCosts`: +1. Return compute costs from [`total_send_fees`](https://cs.github.com/near/nearcore/blob/578983c8df9cc36508da2fb4a205c852e92b211a/runtime/runtime/src/config.rs#L71) +2. Store aggregate compute cost in [`TransactionCost`](https://cs.github.com/near/nearcore/blob/578983c8df9cc36508da2fb4a205c852e92b211a/runtime/runtime/src/config.rs#L22) struct +3. Propagate compute costs to [`VerificationResult`](https://cs.github.com/near/nearcore/blob/578983c8df9cc36508da2fb4a205c852e92b211a/runtime/runtime/src/verifier.rs#L330) + +Additionaly, the gas price computation will need to be adjusted in [`compute_new_gas_price`](https://cs.github.com/near/nearcore/blob/578983c8df9cc36508da2fb4a205c852e92b211a/core/primitives/src/block.rs#L328) to use compute cost instead of gas cost. + +## Security Implications + +Changes in compute costs will be publicly known and might reveal an undercharging that can be used as a target for the attack. +In practice, it is not trivial to exploit the undercharging unless you know the exact shape of the workload that realizes it. +Also, after the compute cost is deployed, the undercharging should no longer be a threat for the network stability. + +## Drawbacks + +- Changing compute costs requires a protocol version bump (and a new binary release), limiting their use to undercharging problems that we're aware of + +- Updating compute costs is a manual process and requires deliberately looking for potential underchargings + +- The compute cost would not have a full effect on the last receipt in the chunk, decreasing its effectiveness to deal with undercharging. +This is because 1) a transaction or receipt today can use up to 300TGas and 2) receipts are added to a chunk until one exceeds the limit and the last receipt is not removed. +Therefore, a single receipt with 300TGas filled with undercharged operations with a factor of K can lead to overshooting the chunk compute limit by (K - 1) * 300TGas + +- Underchargings can still be exploited to lower the throughput of the network at unfair price and increase the waiting times for other users. +This is inevitable for any proposal that doesn't change the gas costs and must be resolved by improving the performance or increasing the gas costs + +- Even without malicious intent, the effective peak throughput of the network will decrease when the chunks include undercharged operations (as the stopping condition based on compute costs for filling the chunk becomes stricter). +Most of the time, this is not the problem as the network is operating below the capacity. +The effects will also be softened by the fact that undercharged operations comprise only a fraction of the workload. +For example, the planned increase for TTN compute cost alongside the Flat Storage MVP is less critical because you cannot fill a receipt with only TTN costs, you will always have other storage costs and ~5Tgas overhead to even start a function call. +So even with 10x difference between gas and compute costs, the DoS only becomes 5x cheaper instead of 10x + +## Unresolved Issues + +## Future possibilities +We can also think about compute costs smaller than gas costs. +For example, we charge gas instead of token balance for extra storage bytes in [NEP-448](https://github.com/near/NEPs/pull/448), it would make sense to set the compute cost to 0 for the part that covers on-chain storage if the throttling due to increased gas cost becomes problematic. +Otherwise, the throughput would be throttled unnecessarily. + +A further option would be to change compute costs dynamically without a protocol upgrade when block production has become too slow. +This would be a catch-all, self-healing solution that requires zero intervention from anyone. +The network would simply throttle throughput when block time remains too high for long enough. +Pursuing this approach would require additional design work: +- On-chain voting to agree on new values of costs, given that inputs to the adjustment process are not deterministic (measurements of wall clock time it takes to process receipt on particular validator) +- Ensuring that dynamic adjustment is done in a safe way that does not lead to erratic behavior of costs (and as a result unpredictable network throughput). +Having some experience manually operating this mechanism would be valuable before introducing automation + +and addressing challenges described in https://github.com/near/nearcore/issues/8032#issuecomment-1362564330. + +The idea of introducing a chunk limit for compute resource usage naturally extends to other resource types, for example RAM usage, Disk IOPS, [Background CPU Usage](https://github.com/near/nearcore/issues/7625). +This would allow us to align the pricing model with cloud offerings familiar to many users, while still using gas as a common denominator to simplify UX. + +## Changelog + +### 1.0.0 - Initial Version + +This NEP was approved by Protocol Working Group members on March 16, 2023 ([meeting recording](https://www.youtube.com/watch?v=4VxRoKwLXIs)): + +- [Bowen's vote](https://github.com/near/NEPs/pull/455#issuecomment-1467023424) +- [Marcelo's vote](https://github.com/near/NEPs/pull/455#pullrequestreview-1340887413) +- [Marcin's vote](https://github.com/near/NEPs/pull/455#issuecomment-1471882639) + +#### Benefits + +- Among the alternatives, this is the easiest to implement. +- It allows us to able to publicly discuss undercharging issues before they are fixed. + +#### Concerns + +No concerns that need to be addressed. The drawbacks listed in this NEP are minor compared to the benefits that it will bring. And implementing this NEP is strictly better than what we have today. + +## Copyright + +[copyright]: #copyright + +Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). + + +## References +- https://gov.near.org/t/proposal-gas-weights-to-fight-instability-to-due-to-undercharging/30919 +- https://github.com/near/nearcore/issues/8032 From ef2e2072dbc67b2ce650b1694b8a760dc43747bf Mon Sep 17 00:00:00 2001 From: Andrei Kashin Date: Wed, 22 Mar 2023 17:28:01 +0100 Subject: [PATCH 115/150] chore: Update status of NEP-455 to Final (#470) As it's been voted on and accepted --- neps/nep-0455.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/neps/nep-0455.md b/neps/nep-0455.md index 070523388..6ad46950d 100644 --- a/neps/nep-0455.md +++ b/neps/nep-0455.md @@ -3,7 +3,7 @@ NEP: 455 Title: Parameter Compute Costs Author: Andrei Kashin , Jakob Meier DiscussionsTo: https://github.com/nearprotocol/neps/pull/455 -Status: Draft +Status: Final Type: Protocol Track Category: Runtime Created: 26-Jan-2023 From 748654112cc5001d54531fc1202c1c65e5c31881 Mon Sep 17 00:00:00 2001 From: Robert Zaremba Date: Fri, 24 Mar 2023 15:02:05 +0100 Subject: [PATCH 116/150] ci: add Markdown linter (#472) --- .github/workflows/links.yml | 15 -------------- .github/workflows/lint.yml | 41 +++++++++++++++++++++++++++++++++++++ .markdownlint.json | 10 +++++++++ 3 files changed, 51 insertions(+), 15 deletions(-) delete mode 100644 .github/workflows/links.yml create mode 100644 .github/workflows/lint.yml create mode 100644 .markdownlint.json diff --git a/.github/workflows/links.yml b/.github/workflows/links.yml deleted file mode 100644 index f53d968b7..000000000 --- a/.github/workflows/links.yml +++ /dev/null @@ -1,15 +0,0 @@ -name: Check Markdown links - -on: push - -jobs: - markdown-link-check: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@master - - uses: gaurav-nelson/github-action-markdown-link-check@v1 - with: - use-quiet-mode: 'yes' -# use-verbose-mode: 'yes' - config-file: 'website/mlc_config.json' - folder-path: 'specs' diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml new file mode 100644 index 000000000..2b0e02afb --- /dev/null +++ b/.github/workflows/lint.yml @@ -0,0 +1,41 @@ +name: Lint + +on: + pull_request: + branches: [master, main] + merge_group: + +concurrency: + group: ci-${{ github.ref }}-${{ github.workflow }} + cancel-in-progress: true + +jobs: + markdown-lint: + name: markdown-lint + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + with: + fetch-depth: 0 + # lint only changed files + - uses: tj-actions/changed-files@v35 + id: changed-files + with: + files: "**/*.md" + separator: "," + - uses: DavidAnson/markdownlint-cli2-action@v9 + if: steps.changed-files.outputs.any_changed == 'true' + with: + globs: ${{ steps.changed-files.outputs.all_changed_files }} + separator: "," + + markdown-link-check: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@master + - uses: gaurav-nelson/github-action-markdown-link-check@v1 + with: + use-quiet-mode: "yes" + # use-verbose-mode: 'yes' + config-file: "website/mlc_config.json" + folder-path: "specs" diff --git a/.markdownlint.json b/.markdownlint.json new file mode 100644 index 000000000..e7026f1ee --- /dev/null +++ b/.markdownlint.json @@ -0,0 +1,10 @@ +{ + "default": true, + "MD007": { "indent": 4 }, + "MD013": false, + "MD024": { "siblings_only": true }, + "MD025": false, + "MD033": false, + "MD034": false, + "whitespace": false +} From ea9393fdadf182de32bbae1da7a892f0814d108c Mon Sep 17 00:00:00 2001 From: Robert Zaremba Date: Fri, 24 Mar 2023 17:13:04 +0100 Subject: [PATCH 117/150] docs(template): move alternatives down (#471) When reading a NEP, it's usually hard to start with _alternatives_ before we read the specification and the main design. It would be more logical (and more clear) if we push the _alternatives_ section down. Also, we don't need to call it "Rationale and Altenratives", because rationale should be clearly covered in the "Motivation" section. --- nep-0000-template.md | 39 +++++++++++++++++++-------------------- 1 file changed, 19 insertions(+), 20 deletions(-) diff --git a/nep-0000-template.md b/nep-0000-template.md index 57bf3bb98..a4223851a 100644 --- a/nep-0000-template.md +++ b/nep-0000-template.md @@ -22,7 +22,7 @@ Title: NEP title Author: List of author name(s) and optional contact info. Examples FirstName LastName , FirstName LastName (@GitHubUserName)> -Status: The NEP status -- New | Approved | Deprecated. +Status: The NEP status -- New | Approved | Deprecated. DiscussionsTo (Optional): URL of current canonical discussion thread, e.g. GitHub Pull Request link. @@ -42,8 +42,6 @@ LastUpdated: The Created header records the date that the NEP was assigned a num See example above --> - - ## Summary [Provide a short human-readable (~200 words) description of the proposal. A reader should get from this section a high-level understanding about the issue this NEP is addressing.] @@ -52,10 +50,6 @@ See example above --> [Explain why this proposal is necessary, how it will benefit the NEAR protocol or community, and what problems it solves. Also describe why the existing protocol specification is inadequate to address the problem that this NEP solves, and what potential use cases or outcomes.] -## Rationale and alternatives - -[Justify the design decision for the proposed solution. And explain any alternative designs that were considered and the rationale for not choosing them.] - ## Specification [Explain the proposal as if you were teaching it to another developer. This generally means describing the syntax and semantics, naming new concepts, and providing clear examples. The specification needs to include sufficient detail to allow interoperable implementations getting built by following only the provided specification. In cases where it is infeasible to specify all implementation details upfront, broadly describe what they are.] @@ -64,11 +58,11 @@ See example above --> [This technical section is required for Protocol proposals but optional for other categories. A draft implementation should demonstrate a minimal implementation that assists in understanding or implementing this proposal. Explain the design in sufficient detail that: -* Its interaction with other features is clear. -* Where possible, include a Minimum Viable Interface subsection expressing the required behavior and types in a target programming language. (ie. traits and structs for rust, interfaces and classes for javascript, function signatures and structs for c, etc.) -* It is reasonably clear how the feature would be implemented. -* Corner cases are dissected by example. -* For protocol changes: A link to a draft PR on nearcore that shows how it can be integrated in the current code. It should at least solve the key technical challenges. +- Its interaction with other features is clear. +- Where possible, include a Minimum Viable Interface subsection expressing the required behavior and types in a target programming language. (ie. traits and structs for rust, interfaces and classes for javascript, function signatures and structs for c, etc.) +- It is reasonably clear how the feature would be implemented. +- Corner cases are dissected by example. +- For protocol changes: A link to a draft PR on nearcore that shows how it can be integrated in the current code. It should at least solve the key technical challenges. The section should return to the examples given in the previous section, and explain more fully how the detailed proposal makes those examples work.] @@ -84,9 +78,13 @@ The section should return to the examples given in the previous section, and exp [Explain any issues that warrant further discussion. Considerations: -* What parts of the design do you expect to resolve through the NEP process before this gets merged? -* What parts of the design do you expect to resolve through the implementation of this feature before stabilization? -* What related issues do you consider out of scope for this NEP that could be addressed in the future independently of the solution that comes out of this NEP?] +- What parts of the design do you expect to resolve through the NEP process before this gets merged? +- What parts of the design do you expect to resolve through the implementation of this feature before stabilization? +- What related issues do you consider out of scope for this NEP that could be addressed in the future independently of the solution that comes out of this NEP?] + +## Alternatives + +[Explain any alternative designs that were considered and the rationale for not choosing them. Why your design is superior?] ## Future possibilities @@ -103,16 +101,17 @@ The section should return to the examples given in the previous section, and exp #### Benefits [Placeholder for Subject Matter Experts review for this version:] -* Benefit 1 -* Benefit 2 + +- Benefit 1 +- Benefit 2 #### Concerns [Template for Subject Matter Experts review for this version:] | # | Concern | Resolution | Status | -| - | - | - | - | -| 1 | | | | -| 2 | | | | +| - | - | - | - | +| 1 | | | | +| 2 | | | | ## Copyright From 3657715aa30ca472bdc78399e4cfd3ec3805bf86 Mon Sep 17 00:00:00 2001 From: Robert Zaremba Date: Sat, 25 Mar 2023 13:08:32 +0100 Subject: [PATCH 118/150] chore: linting neps (#473) In https://github.com/near/NEPs/pull/472 we integrated a popular linter. Here we update the existing markdown files to clean up linting issues. - [x] root dir - [x] neps - `specs` -- let's do it in other PR, will be easier to review. --- .markdownlint.json | 2 +- README.md | 92 ++++++++-------- neps/nep-0001.md | 47 ++++---- neps/nep-0021.md | 41 +++---- neps/nep-0141.md | 206 ++++++++++++++++++----------------- neps/nep-0145.md | 255 ++++++++++++++++++++++++------------------- neps/nep-0148.md | 60 +++++----- neps/nep-0171.md | 20 ++-- neps/nep-0177.md | 11 +- neps/nep-0178.md | 238 ++++++++++++++++++++++------------------ neps/nep-0181.md | 1 - neps/nep-0199.md | 9 +- neps/nep-0245.md | 4 +- neps/nep-0297.md | 29 +++-- neps/nep-0330.md | 2 +- neps/nep-0364.md | 17 ++- neps/nep-0366.md | 94 +++++++++------- neps/nep-0399.md | 265 ++++++++++++++++++++++++--------------------- neps/nep-0413.md | 60 +++++++--- neps/nep-0418.md | 2 +- neps/nep-0448.md | 95 ++++++++-------- neps/nep-0455.md | 17 ++- 22 files changed, 861 insertions(+), 706 deletions(-) diff --git a/.markdownlint.json b/.markdownlint.json index e7026f1ee..605a1716d 100644 --- a/.markdownlint.json +++ b/.markdownlint.json @@ -1,6 +1,6 @@ { "default": true, - "MD007": { "indent": 4 }, + "MD001": false, "MD013": false, "MD024": { "siblings_only": true }, "MD025": false, diff --git a/README.md b/README.md index 124a8d2a1..f22c101b5 100644 --- a/README.md +++ b/README.md @@ -10,26 +10,24 @@ Changes to the protocol specification and standards are called NEAR Enhancement ## NEPs -|NEP # | Title | Author | Status | -|---|---|---------------------------------------------|--------| -|[0001](https://github.com/near/NEPs/blob/master/neps/nep-0001.md) | NEP Purpose and Guidelines | @jlogelin | Living | -|[0021](https://github.com/near/NEPs/blob/master/neps/nep-0021.md) | Fungible Token Standard (Deprecated) | @evgenykuzyakov | Final | -|[0141](https://github.com/near/NEPs/blob/master/neps/nep-0141.md) | Fungible Token Standard | @evgenykuzyakov @oysterpack | Final | -|[0145](https://github.com/near/NEPs/blob/master/neps/nep-0145.md) | Storage Management | @evgenykuzyakov | Final | -|[0148](https://github.com/near/NEPs/blob/master/neps/nep-0148.md) | Fungible Token Metadata | @robert-zaremba @evgenykuzyakov @oysterpack | Final | -|[0171](https://github.com/near/NEPs/blob/master/neps/nep-0171.md) | Non Fungible Token Standard | @mikedotexe @evgenykuzyakov @oysterpack | Final | -|[0177](https://github.com/near/NEPs/blob/master/neps/nep-0177.md) | Non Fungible Token Metadata | @chadoh @mikedotexe | Final | -|[0178](https://github.com/near/NEPs/blob/master/neps/nep-0178.md) | Non Fungible Token Approval Management | @chadoh @thor314 | Final | -|[0181](https://github.com/near/NEPs/blob/master/neps/nep-0181.md) | Non Fungible Token Enumeration | @chadoh @thor314 | Final | -|[0199](https://github.com/near/NEPs/blob/master/neps/nep-0199.md) | Non Fungible Token Royalties and Payouts | @thor314 @mattlockyer | Final | -|[0245](https://github.com/near/NEPs/blob/master/neps/nep-0245.md) | Multi Token Standard | @zcstarr @riqi @jriemann @marcos.sun | Review | -|[0297](https://github.com/near/NEPs/blob/master/neps/nep-0297.md) | Events Standard | @telezhnaya | Final | -|[0330](https://github.com/near/NEPs/blob/master/neps/nep-0330.md) | Source Metadata | @BenKurrek | Review | -|[0366](https://github.com/near/NEPs/blob/master/neps/nep-0366.md) | Meta Transactions | @ilblackdragon @e-uleyskiy @fadeevab | Draft | -|[0399](https://github.com/near/NEPs/blob/master/neps/nep-0399.md) | Flat Storage | @Longarithm @mzhangmzz | Review | -|[0455](https://github.com/near/NEPs/blob/master/neps/nep-0455.md) | Parameter Compute Costs | @akashin @jakmeier | Final | - - +| NEP # | Title | Author | Status | +| ----------------------------------------------------------------- | ---------------------------------------- | ------------------------------------------- | ------ | +| [0001](https://github.com/near/NEPs/blob/master/neps/nep-0001.md) | NEP Purpose and Guidelines | @jlogelin | Living | +| [0021](https://github.com/near/NEPs/blob/master/neps/nep-0021.md) | Fungible Token Standard (Deprecated) | @evgenykuzyakov | Final | +| [0141](https://github.com/near/NEPs/blob/master/neps/nep-0141.md) | Fungible Token Standard | @evgenykuzyakov @oysterpack | Final | +| [0145](https://github.com/near/NEPs/blob/master/neps/nep-0145.md) | Storage Management | @evgenykuzyakov | Final | +| [0148](https://github.com/near/NEPs/blob/master/neps/nep-0148.md) | Fungible Token Metadata | @robert-zaremba @evgenykuzyakov @oysterpack | Final | +| [0171](https://github.com/near/NEPs/blob/master/neps/nep-0171.md) | Non Fungible Token Standard | @mikedotexe @evgenykuzyakov @oysterpack | Final | +| [0177](https://github.com/near/NEPs/blob/master/neps/nep-0177.md) | Non Fungible Token Metadata | @chadoh @mikedotexe | Final | +| [0178](https://github.com/near/NEPs/blob/master/neps/nep-0178.md) | Non Fungible Token Approval Management | @chadoh @thor314 | Final | +| [0181](https://github.com/near/NEPs/blob/master/neps/nep-0181.md) | Non Fungible Token Enumeration | @chadoh @thor314 | Final | +| [0199](https://github.com/near/NEPs/blob/master/neps/nep-0199.md) | Non Fungible Token Royalties and Payouts | @thor314 @mattlockyer | Final | +| [0245](https://github.com/near/NEPs/blob/master/neps/nep-0245.md) | Multi Token Standard | @zcstarr @riqi @jriemann @marcos.sun | Review | +| [0297](https://github.com/near/NEPs/blob/master/neps/nep-0297.md) | Events Standard | @telezhnaya | Final | +| [0330](https://github.com/near/NEPs/blob/master/neps/nep-0330.md) | Source Metadata | @BenKurrek | Review | +| [0366](https://github.com/near/NEPs/blob/master/neps/nep-0366.md) | Meta Transactions | @ilblackdragon @e-uleyskiy @fadeevab | Draft | +| [0399](https://github.com/near/NEPs/blob/master/neps/nep-0399.md) | Flat Storage | @Longarithm @mzhangmzz | Review | +| [0455](https://github.com/near/NEPs/blob/master/neps/nep-0455.md) | Parameter Compute Costs | @akashin @jakmeier | Final | ## Specification @@ -57,26 +55,26 @@ Spec changes are ultimately done via pull requests to this repository (formalize 2. The forum has comment threading which allows the community and NEAR Collective to ideate, ask questions, wrestle with approaches, etc. If more immediate responses are desired, consider bringing the conversation to [Zulip](https://near.zulipchat.com/#narrow/stream/320497-nep-standards). 3. When the governance conversations have reached a point where a clear plan is evident, create a pull request, using the instructions below. - * Clone this repository and create a branch with "my-feature". - * Update relevant content in the current specification that are affected by the proposal. - * Create a Pull request, using [nep-0000-template.md](nep-0000-template.md) to describe motivation and details of the new Contract or Protocol specification. In the document header, ensure the `Status` is marked as `Draft`, and any relevant discussion links are added to the `DiscussionsTo` section. - Use the pull request number padded with zeroes. For instance, the pull request `219` should be created as `neps/nep-0219.md`. - * Add your Draft standard to the `NEPs` section of this README.md. This helps advertise your standard via github. - * Update Docusaurus documentation under the `specs/Standards` to describe the contract standard at a high level, how to integrate it into a Dapp, and a link to the standard document (ie. `neps/nep-0123.md`). This helps advertise your standard via [nomicon](https://nomicon.io/). Any related nomicon sections should be prefixed and styled using the following snippet: + - Clone this repository and create a branch with "my-feature". + - Update relevant content in the current specification that are affected by the proposal. + - Create a Pull request, using [nep-0000-template.md](nep-0000-template.md) to describe motivation and details of the new Contract or Protocol specification. In the document header, ensure the `Status` is marked as `Draft`, and any relevant discussion links are added to the `DiscussionsTo` section. + Use the pull request number padded with zeroes. For instance, the pull request `219` should be created as `neps/nep-0219.md`. + - Add your Draft standard to the `NEPs` section of this README.md. This helps advertise your standard via github. + - Update Docusaurus documentation under the `specs/Standards` to describe the contract standard at a high level, how to integrate it into a Dapp, and a link to the standard document (ie. `neps/nep-0123.md`). This helps advertise your standard via [nomicon](https://nomicon.io/). Any related nomicon sections should be prefixed and styled using the following snippet: - ``` - :::caution - This is part of proposed spec [NEP-123](https://github.com/near/NEPs/blob/master/neps/nep-0123.md) and subject to change. - ::: - ``` + ```text + :::caution + This is part of proposed spec [NEP-123](https://github.com/near/NEPs/blob/master/neps/nep-0123.md) and subject to change. + ::: + ``` - * Once complete, submit the pull request for editor review. + - Once complete, submit the pull request for editor review. - * The formalization dance begins: - * NEP Editors, who are unopinionated shepherds of the process, check document formatting, completeness and adherence to [NEP-0001](neps/nep-0001.md) and approve the pull request. - * Once ready, the author updates the NEP status to `Review` allowing further community participation, to address any gaps or clarifications, normally part of the Review PR. - * NEP Editors mark the NEP as `Last Call`, allowing a 14 day grace period for any final community feedback. Any unresolved show stoppers roll the state back to `Review`. - * NEP Editors mark the NEP as `Final`, marking the standard as complete. The standard should only be updated to correct errata and add non-normative clarifications. + - The formalization dance begins: + - NEP Editors, who are unopinionated shepherds of the process, check document formatting, completeness and adherence to [NEP-0001](neps/nep-0001.md) and approve the pull request. + - Once ready, the author updates the NEP status to `Review` allowing further community participation, to address any gaps or clarifications, normally part of the Review PR. + - NEP Editors mark the NEP as `Last Call`, allowing a 14 day grace period for any final community feedback. Any unresolved show stoppers roll the state back to `Review`. + - NEP Editors mark the NEP as `Final`, marking the standard as complete. The standard should only be updated to correct errata and add non-normative clarifications. Tip: build consensus and integrate feedback. NEPs that have broad support are much more likely to make progress than those that don't receive any comments. Feel free to reach out to the NEP assignee in particular to get help identify stakeholders and obstacles. @@ -95,19 +93,19 @@ This repository uses [Docusaurus](https://docusaurus.io/) for the [Nomicon websi - Run the local docs development server - ```sh - # Start the site - yarn start - ``` + ```sh + # Start the site + yarn start + ``` - _Expected Output_ + _Expected Output_ - ```sh - # Website with live reload is started - Docusaurus server started on port 3000 - ``` + ```sh + # Website with live reload is started + Docusaurus server started on port 3000 + ``` - The website for docs will open your browser locally to port `3000` + The website for docs will open your browser locally to port `3000` 2. Make changes to the docs diff --git a/neps/nep-0001.md b/neps/nep-0001.md index 3df1f3662..ba343ab3e 100644 --- a/neps/nep-0001.md +++ b/neps/nep-0001.md @@ -11,6 +11,7 @@ Last Updated: 2023-03-05 --- ## Summary + A NEAR Enhancement Proposal (NEP) is a design document that specifies reusable and interoperable components integrated across the NEAR ecosystem. NEPs are the primary mechanism for evolving NEAR’s runtime, Smart Contract Standards, and Wallets ecosystem in a community-driven way. NEPs provide a concise technical specification and a rationale for the feature. The NEP author is responsible for building consensus within the community and documenting dissenting opinions. The typical primary audience for NEPs are the developers of the NEAR reference implementations and decentralized application developers. @@ -22,6 +23,7 @@ NEPs are stored as text files in a versioned repository, allowing for easy histo The purpose of the NEP process is to ensure the seamless evolution of the NEAR platform and to empower the community to contribute to its development. Given the complexity and number of participants involved across the ecosystem, a well-defined process helps ensure transparency, security, and stability. ## NEP Types + There are four kinds of NEPs: 1. A **Protocol** NEP describes a new feature of the NEAR protocol. @@ -34,6 +36,7 @@ Currently, all types of NEPs follow the same process, but for Protocol NEPs a dr ## Submit a NEP ### Start with ideation + Everyone in the community is welcome to propose, discuss, and review ideas to improve the NEAR protocol and standards. The NEP process begins with a [new idea](https://www.neardevgov.org/blog/how-to-ideate-in-the-near-developer-governance) for the NEAR ecosystem. A single NEP should contain a single key proposal or new idea. Each NEP must have an author: Someone who writes the NEP using the style and format described below. The author, or another champion, shepherds the discussions in the appropriate forums and attempts to build community consensus around the idea to help it progress toward completion. @@ -47,6 +50,7 @@ In general, the process for socializing an idea is: - **Get feedback:** The [Dev Gov Gigs Board](https://devgovgigs.near.social) has comment threading which allows the community to ideate, ask questions, wrestle with approaches, etc. If more immediate responses are desired, consider bringing the conversation to the appropriate [Community Group](https://gov.near.org/c/dev/community-groups/103). ### Submit a NEP Draft + Following the above initial discussions, the author should submit a NEP draft into the GitHub NEP repository. The draft NEP must follow the [NEP-0000 template](https://github.com/near/NEPs/blob/master/nep-0000-template.md), or else it will fail the review immediately. To submit a NEP draft as a pull request, the NEP author should: @@ -59,6 +63,7 @@ To submit a NEP draft as a pull request, the NEP author should: 6. Push this to your GitHub fork and submit a pull request. Mention the @near/nep-moderators in the comment and turn the PR into a "Ready for Review" state once you believe the NEP is ready for review. ## NEP Lifecycle + The NEP process begins when an author submits a [NEP draft](#submit-a-nep-draft). The NEP lifecycle consists of three stages: draft, review, and voting, with two possible outcomes: approval or rejection. Throughout the process, various roles play a critical part in moving the proposal forward. Most of the activity happens asynchronously on the NEP within GitHub, where all the roles can communicate and collaborate on revisions and improvements to the proposal. ![NEP Process](https://user-images.githubusercontent.com/110252255/201413632-f72743d6-593e-4747-9409-f56bc38de17b.png) @@ -66,14 +71,14 @@ The NEP process begins when an author submits a [NEP draft](#submit-a-nep-draft) ### NEP Stages -* **Draft:** The first formally tracked stage of a new NEP. This process begins once an author submits a draft proposal and the NEP moderator merges it into the NEP repo when properly formatted. -* **Review:** A NEP moderator marks a NEP as ready for Subject Matter Experts Review. If the NEP is not approved within two months, it is automatically rejected. -* **Voting:** This is the final voting period for a NEP. The working group will vote on whether to accept or reject the NEP. This period is limited to two weeks. If during this period necessary normative changes are required, the NEP will revert to Review. +- **Draft:** The first formally tracked stage of a new NEP. This process begins once an author submits a draft proposal and the NEP moderator merges it into the NEP repo when properly formatted. +- **Review:** A NEP moderator marks a NEP as ready for Subject Matter Experts Review. If the NEP is not approved within two months, it is automatically rejected. +- **Voting:** This is the final voting period for a NEP. The working group will vote on whether to accept or reject the NEP. This period is limited to two weeks. If during this period necessary normative changes are required, the NEP will revert to Review. ### NEP Outcomes -* **Approved:** If the working group votes to approve, they will move the NEP to Approved. Once approved, Standards NEPs exist in a state of finality and should only be updated to correct errata and add non-normative clarifications. -* **Rejected:** If the working group votes to reject, they will move the NEP to Rejected. +- **Approved:** If the working group votes to approve, they will move the NEP to Approved. Once approved, Standards NEPs exist in a state of finality and should only be updated to correct errata and add non-normative clarifications. +- **Rejected:** If the working group votes to reject, they will move the NEP to Rejected. ### NEP Roles and Responsibilities @@ -115,24 +120,24 @@ All participants in the NEP process should maintain a professional and respectfu ### NEP Playbook 1. Once an author [submits a NEP draft](#submit-a-nep-draft), the NEP moderators will review their pull request (PR) for structure, formatting, and other errors. Approval criteria are: - * The content is complete and technically sound. The moderators do not consider whether the NEP is likely or not to get accepted. - * The title accurately reflects the content. - * The language, spelling, grammar, sentence structure, and code style are correct and conformant. + - The content is complete and technically sound. The moderators do not consider whether the NEP is likely or not to get accepted. + - The title accurately reflects the content. + - The language, spelling, grammar, sentence structure, and code style are correct and conformant. 2. If the NEP is not ready for approval, the moderators will send it back to the author with specific instructions in the PR. The moderators must complete the review within one week. 3. Once the moderators agree that the PR is ready for review, they will ask the approvers (working group members) to nominate a team of at least two reviewers (subject matter experts) to review the NEP. At least one working group member must explicitly tag the reviewers and comment: `"As a working group member, I'd like to nominate @SME-username and @SME-username as the Subject Matter Experts to review this NEP."` If the assigned reviewers feel that they lack the relevant expertise to fully review the NEP, they can ask the working group to re-assign the reviewers for the NEP. 4. The reviewers must finish the technical review within one week. Technical Review Guidelines: - * First, review the technical details of the proposals and assess their merit. If you have feedback, explicitly tag the author and comment: `"As the assigned Reviewer, I request from @author-username to [ask clarifying questions, request changes, or provide suggestions that are actionable.]."` It may take a couple of iterations to resolve any open comments. - * Second, once the reviewer believes that the NEP is close to the voting stage, explicitly tag the @near/nep-moderators and comment with your technical summary. The Technical Summary must include: - * A recommendation for the working group: `"As the assigned reviewer, I do not have any feedback for the author. I recommend moving this NEP forward and for the working group to [accept or reject] it based on [provide reasoning, including a sense of importance or urgency of this NEP]."` Please note that this is the reviewer's personal recommendation. - * A summary of benefits that surfaced in previous discussions. This should include a concise list of all the benefits that others raised, not just the ones that the reviewer personally agrees with. - * A summary of concerns or blockers, along with their current status and resolution. Again, this should reflect the collective view of all commenters, not just the reviewer's perspective. + - First, review the technical details of the proposals and assess their merit. If you have feedback, explicitly tag the author and comment: `"As the assigned Reviewer, I request from @author-username to [ask clarifying questions, request changes, or provide suggestions that are actionable.]."` It may take a couple of iterations to resolve any open comments. + - Second, once the reviewer believes that the NEP is close to the voting stage, explicitly tag the @near/nep-moderators and comment with your technical summary. The Technical Summary must include: + - A recommendation for the working group: `"As the assigned reviewer, I do not have any feedback for the author. I recommend moving this NEP forward and for the working group to [accept or reject] it based on [provide reasoning, including a sense of importance or urgency of this NEP]."` Please note that this is the reviewer's personal recommendation. + - A summary of benefits that surfaced in previous discussions. This should include a concise list of all the benefits that others raised, not just the ones that the reviewer personally agrees with. + - A summary of concerns or blockers, along with their current status and resolution. Again, this should reflect the collective view of all commenters, not just the reviewer's perspective. 5. The NEP author can make revisions and request further reviews from the reviewers. However, if a proposal is in the review stage for more than two months, the moderator will automatically reject it. To reopen the proposal, the author must restart the NEP process again. 6. Once both reviewers complete their technical summary, the moderators will notify the approvers (working group members) that the NEP is in the final comment period. The approvers must fully review the NEP within one week. Approver guidelines: - * First, read the NEP thoroughly. If you have feedback, explicitly tag the author and comment: `"As a working group member, I request from @author-username to [ask clarifying questions, request changes, or provide actionable suggestions.]."` - * Second, once the approver believes the NEP is close to the voting stage, explicitly comment with your voting indication: `"As a working group member, I lean towards [approving OR rejecting] this NEP based on [provide reasoning]."` + - First, read the NEP thoroughly. If you have feedback, explicitly tag the author and comment: `"As a working group member, I request from @author-username to [ask clarifying questions, request changes, or provide actionable suggestions.]."` + - Second, once the approver believes the NEP is close to the voting stage, explicitly comment with your voting indication: `"As a working group member, I lean towards [approving OR rejecting] this NEP based on [provide reasoning]."` 7. Once all the approvers indicate their voting indication, the moderator will review the voting indication for a 2/3 majority: - * If the votes lean toward rejection: The moderator will summarize the feedback and close the NEP. - * If the votes lean toward approval: The moderator will schedule a public call (see [NEP Communication](#nep-communication)) for the author to present the NEP and for the working group members to formalize the voting decision. If the working group members agree that the NEP is overall beneficial for the NEAR ecosystem and vote to approve it, then the proposal is considered accepted. After the call, the moderator will summarize the decision on the NEP. + - If the votes lean toward rejection: The moderator will summarize the feedback and close the NEP. + - If the votes lean toward approval: The moderator will schedule a public call (see [NEP Communication](#nep-communication)) for the author to present the NEP and for the working group members to formalize the voting decision. If the working group members agree that the NEP is overall beneficial for the NEAR ecosystem and vote to approve it, then the proposal is considered accepted. After the call, the moderator will summarize the decision on the NEP. 8. The NEP author or other assignees will complete action items from the call. For example, the author will finalize the "Changelog" section on the NEP, which summarizes the benefits and concerns for future reference. ### Transferring NEP Ownership @@ -173,10 +178,10 @@ If an author believes that a new extension meets the criteria for its own separa The content of this document was derived heavily from the PEP, BIP, Rust RFC, and EIP standards bootstrap documents: -* Klock, F et al. Rust: RFC-0002: RFC Process. https://github.com/rust-lang/rfcs/blob/master/text/0002-rfc-process.md -* Taaki, A. et al. Bitcoin Improvement Proposal: BIP:1, BIP Purpose and Guidelines. https://github.com/bitcoin/bips/blob/master/bip-0001.mediawiki -* Warsaw, B. et al. Python Enhancement Proposal: PEP Purpose and Guidelines. https://github.com/python/peps/blob/main/pep-0001.txt -* Becze, M. et al. Ethereum Improvement Proposal EIP1: EIP Purpose and Guidelines. https://github.com/ethereum/EIPs/blob/master/EIPS/eip-1.md +- Klock, F et al. Rust: RFC-0002: RFC Process. https://github.com/rust-lang/rfcs/blob/master/text/0002-rfc-process.md +- Taaki, A. et al. Bitcoin Improvement Proposal: BIP:1, BIP Purpose and Guidelines. https://github.com/bitcoin/bips/blob/master/bip-0001.mediawiki +- Warsaw, B. et al. Python Enhancement Proposal: PEP Purpose and Guidelines. https://github.com/python/peps/blob/main/pep-0001.txt +- Becze, M. et al. Ethereum Improvement Proposal EIP1: EIP Purpose and Guidelines. https://github.com/ethereum/EIPs/blob/master/EIPS/eip-1.md ## Copyright diff --git a/neps/nep-0021.md b/neps/nep-0021.md index 45dc7bc13..ab45c49c4 100644 --- a/neps/nep-0021.md +++ b/neps/nep-0021.md @@ -39,6 +39,7 @@ For latest lock proposals see Safes (#26) ## Specification We should be able to do the following: + - Initialize contract once. The given total supply will be owned by the given account ID. - Get the total supply. - Transfer tokens to a new user. @@ -49,6 +50,7 @@ We should be able to do the following: - Get the current allowance for an escrow account on behalf of the balance owner. This should only be used in the UI, since a contract shouldn't rely on this temporary information. There are a few concepts in the scenarios above: + - **Total supply**. It's the total number of tokens in circulation. - **Balance owner**. An account ID that owns some amount of tokens. - **Balance**. Some amount of tokens. @@ -62,8 +64,7 @@ value is always 1 token. ### Simple transfer Alice wants to send 5 wBTC tokens to Bob. - -**Assumptions** +Assumptions: - The wBTC token contract is `wbtc`. - Alice's account is `alice`. @@ -71,19 +72,18 @@ Alice wants to send 5 wBTC tokens to Bob. - The precision on wBTC contract is `10^8`. - The 5 tokens is `5 * 10^8` or as a number is `500000000`. -**High-level explanation** +#### High-level explanation Alice needs to issue one transaction to wBTC contract to transfer 5 tokens (multiplied by precision) to Bob. -**Technical calls** +#### Technical calls 1. `alice` calls `wbtc::transfer({"new_owner_id": "bob", "amount": "500000000"})`. ### Token deposit to a contract Alice wants to deposit 1000 DAI tokens to a compound interest contract to earn extra tokens. - -**Assumptions** +Assumptions: - The DAI token contract is `dai`. - Alice's account is `alice`. @@ -92,14 +92,15 @@ Alice wants to deposit 1000 DAI tokens to a compound interest contract to earn e - The 1000 tokens is `1000 * 10^18` or as a number is `1000000000000000000000`. - The compound contract can work with multiple token types. -**High-level explanation** +#### High-level explanation Alice needs to issue 2 transactions. The first one to `dai` to set an allowance for `compound` to be able to withdraw tokens from `alice`. The second transaction is to the `compound` to start the deposit process. Compound will check that the DAI tokens are supported and will try to withdraw the desired amount of DAI from `alice`. + - If transfer succeeded, `compound` can increase local ownership for `alice` to 1000 DAI - If transfer fails, `compound` doesn't need to do anything in current example, but maybe can notify `alice` of unsuccessful transfer. -**Technical calls** +#### Technical calls 1. `alice` calls `dai::set_allowance({"escrow_account_id": "compound", "allowance": "1000000000000000000000"})`. 1. `alice` calls `compound::deposit({"token_contract": "dai", "amount": "1000000000000000000000"})`. During the `deposit` call, `compound` does the following: @@ -109,8 +110,7 @@ The second transaction is to the `compound` to start the deposit process. Compou ### Multi-token swap on DEX Charlie wants to exchange his wLTC to wBTC on decentralized exchange contract. Alex wants to buy wLTC and has 80 wBTC. - -**Assumptions** +Assumptions - The wLTC token contract is `wltc`. - The wBTC token contract is `wbtc`. @@ -124,24 +124,27 @@ Charlie wants to exchange his wLTC to wBTC on decentralized exchange contract. A - Dex contract already has an open order to sell 80 wBTC tokens by `alex` towards 9001 wLTC. - Without Safes implementation, DEX has to act as an escrow and hold funds of both users before it can do an exchange. -**High-level explanation** +#### High-level explanation Let's first setup open order by Alex on DEX. It's similar to `Token deposit to a contract` example above. + - Alex sets an allowance on wBTC to DEX - Alex calls deposit on Dex for wBTC. - Alex calls DEX to make an new sell order. Then Charlie comes and decides to fulfill the order by selling his wLTC to Alex on DEX. Charlie calls the DEX + - Charlie sets the allowance on wLTC to DEX - Alex calls deposit on Dex for wLTC. - Then calls DEX to take the order from Alex. When called, DEX makes 2 async transfers calls to exchange corresponding tokens. + - DEX calls wLTC to transfer tokens DEX to Alex. - DEX calls wBTC to transfer tokens DEX to Charlie. -**Technical calls** +#### Technical calls 1. `alex` calls `wbtc::set_allowance({"escrow_account_id": "dex", "allowance": "8000000000"})`. 1. `alex` calls `dex::deposit({"token": "wbtc", "amount": "8000000000"})`. @@ -158,11 +161,12 @@ When called, DEX makes 2 async transfers calls to exchange corresponding tokens. The full implementation in Rust can be found there: https://github.com/nearprotocol/near-sdk-rs/blob/master/examples/fungible-token/src/lib.rs -**NOTES:** +NOTES: + - All amounts, balances and allowance are limited by U128 (max value `2**128 - 1`). - Token standard uses JSON for serialization of arguments and results. - Amounts in arguments and results have are serialized as Base-10 strings, e.g. `"100"`. This is done to avoid -JSON limitation of max integer value of `2**53`. + JSON limitation of max integer value of `2**53`. Interface: @@ -208,23 +212,20 @@ pub fn get_balance(&self, owner_id: AccountId) -> U128; /// So this method should only be used on the front-end to see the current allowance. pub fn get_allowance(&self, owner_id: AccountId, escrow_account_id: AccountId) -> U128; ``` + ## Drawbacks -[drawbacks]: #drawbacks - Current interface doesn't have minting, precision (decimals), naming. But it should be done as extensions, e.g. a Precision extension. - It's not possible to exchange tokens without transferring them to escrow first. - It's not possible to transfer tokens to a contract with a single transaction without setting the allowance first. -It should be possible if we introduce `transfer_with` function that transfers tokens and calls escrow contract. It needs to handle result of the execution and contracts have to be aware of this API. + It should be possible if we introduce `transfer_with` function that transfers tokens and calls escrow contract. It needs to handle result of the execution and contracts have to be aware of this API. ## Future possibilities -[future-possibilities]: #future-possibilities - Support for multiple token types - Minting and burning - Precision, naming and short token name. - ## Copyright -[copyright]: #copyright -Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). \ No newline at end of file +Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). diff --git a/neps/nep-0141.md b/neps/nep-0141.md index 4c7f0ea26..2cec6e96c 100644 --- a/neps/nep-0141.md +++ b/neps/nep-0141.md @@ -19,8 +19,9 @@ The [fungible token metadata standard][FT Metadata] provides the fields needed f ## Motivation NEAR Protocol uses an asynchronous, sharded runtime. This means the following: - - Storage for different contracts and accounts can be located on the different shards. - - Two contracts can be executed at the same time in different shards. + +- Storage for different contracts and accounts can be located on the different shards. +- Two contracts can be executed at the same time in different shards. While this increases the transaction throughput linearly with the number of shards, it also creates some challenges for cross-contract development. For example, if one contract wants to query some information from the state of another contract (e.g. current balance), by the time the first contract receives the balance the real balance can change. In such an async system, a contract can't rely on the state of another contract and assume it's not going to change. @@ -44,6 +45,7 @@ Learn about NEP-141: ### Guide-level explanation We should be able to do the following: + - Initialize contract once. The given total supply will be owned by the given account ID. - Get the total supply. - Transfer tokens to a new user. @@ -52,6 +54,7 @@ We should be able to do the following: - Remove state for the key/value pair corresponding with a user's account, withdrawing a nominal balance of Ⓝ that was used for storage. There are a few concepts in the scenarios above: + - **Total supply**: the total number of tokens in circulation. - **Balance owner**: an account ID that owns some amount of tokens. - **Balance**: an amount of tokens. @@ -63,13 +66,12 @@ Note that precision (the number of decimal places supported by a given token) is Given that multiple users will use a Fungible Token contract, and their activity will result in an increased [storage staking](https://docs.near.org/docs/concepts/storage-staking) burden for the contract's account, this standard is designed to interoperate nicely with [the Account Storage standard][Storage Management] for storage deposits and refunds. -#### Example scenarios +### Example scenarios -##### Simple transfer +#### Simple transfer Alice wants to send 5 wBTC tokens to Bob. - -**Assumptions** +Assumptions - The wBTC token contract is `wbtc`. - Alice's account is `alice`. @@ -77,19 +79,19 @@ Alice wants to send 5 wBTC tokens to Bob. - The precision ("decimals" in the metadata standard) on wBTC contract is `10^8`. - The 5 tokens is `5 * 10^8` or as a number is `500000000`. -**High-level explanation** +##### High-level explanation Alice needs to issue one transaction to wBTC contract to transfer 5 tokens (multiplied by precision) to Bob. -**Technical calls** +##### Technical calls 1. `alice` calls `wbtc::ft_transfer({"receiver_id": "bob", "amount": "500000000"})`. -##### Token deposit to a contract +#### Token deposit to a contract Alice wants to deposit 1000 DAI tokens to a compound interest contract to earn extra tokens. -**Assumptions** +##### Assumptions - The DAI token contract is `dai`. - Alice's account is `alice`. @@ -101,14 +103,15 @@ Alice wants to deposit 1000 DAI tokens to a compound interest contract to earn e
For this example, you may expand this section to see how a previous fungible token standard using escrows would deal with the scenario. -**High-level explanation** (NEP-21 standard) +##### High-level explanation (NEP-21 standard) Alice needs to issue 2 transactions. The first one to `dai` to set an allowance for `compound` to be able to withdraw tokens from `alice`. The second transaction is to the `compound` to start the deposit process. Compound will check that the DAI tokens are supported and will try to withdraw the desired amount of DAI from `alice`. + - If transfer succeeded, `compound` can increase local ownership for `alice` to 1000 DAI - If transfer fails, `compound` doesn't need to do anything in current example, but maybe can notify `alice` of unsuccessful transfer. -**Technical calls** (NEP-21 standard) +##### Technical calls (NEP-21 standard) 1. `alice` calls `dai::set_allowance({"escrow_account_id": "compound", "allowance": "1000000000000000000000"})`. 2. `alice` calls `compound::deposit({"token_contract": "dai", "amount": "1000000000000000000000"})`. During the `deposit` call, `compound` does the following: @@ -117,11 +120,11 @@ The second transaction is to the `compound` to start the deposit process. Compou
-**High-level explanation** +##### High-level explanation Alice needs to issue 1 transaction, as opposed to 2 with a typical escrow workflow. -**Technical calls** +##### Technical calls 1. `alice` calls `dai::ft_transfer_call({"receiver_id": "compound", "amount": "1000000000000000000000", "msg": "invest"})`. During the `ft_transfer_call` call, `dai` does the following: 1. makes async call `compound::ft_on_transfer({"sender_id": "alice", "amount": "1000000000000000000000", "msg": "invest"})`. @@ -133,7 +136,7 @@ Alice needs to issue 1 transaction, as opposed to 2 with a typical escrow workfl Alice wants to swap 5 wrapped NEAR (wNEAR) for BNNA tokens at current market rate, with less than 2% slippage. -**Assumptions** +##### Assumptions - The wNEAR token contract is `wnear`. - Alice's account is `alice`. @@ -142,7 +145,7 @@ Alice wants to swap 5 wrapped NEAR (wNEAR) for BNNA tokens at current market rat - The precision ("decimals" in the metadata standard) on wNEAR contract is `10^24`. - The 5 tokens is `5 * 10^24` or as a number is `5000000000000000000000000`. -**High-level explanation** +##### High-level explanation Alice needs to issue one transaction to wNEAR contract to transfer 5 tokens (multiplied by precision) to `amm`, specifying her desired action (swap), her destination token (BNNA) & minimum slippage (<2%) in `msg`. @@ -152,24 +155,24 @@ Alice needs to attach one yoctoNEAR. This will result in her seeing a confirmati Altogether then, Alice may take two steps, though the first may be a background detail of the app she uses. -**Technical calls** +##### Technical calls 1. View `amm::ft_data_to_msg({ action: "swap", destination_token: "bnna", min_slip: 2 })`. Using [NEAR CLI](https://docs.near.org/docs/tools/near-cli): - near view amm ft_data_to_msg '{ - "action": "swap", - "destination_token": "bnna", - "min_slip": 2 - }' + ```shell + near view amm ft_data_to_msg \ + '{"action": "swap", "destination_token": "bnna", "min_slip": 2}' + ``` Then Alice (or the app she uses) will hold onto the result and use it in the next step. Let's say this result is `"swap:bnna,2"`. 2. Call `wnear::ft_on_transfer`. Using NEAR CLI: - near call wnear ft_transfer_call '{ - "receiver_id": "amm", - "amount": "5000000000000000000000000", - "msg": "swap:bnna,2" - }' --accountId alice --depositYocto 1 + + ```shell + near call wnear ft_transfer_call \ + '{"receiver_id": "amm", "amount": "5000000000000000000000000", "msg": "swap:bnna,2"}' \ + --accountId alice --depositYocto 1 + ``` During the `ft_transfer_call` call, `wnear` does the following: @@ -179,40 +182,42 @@ Altogether then, Alice may take two steps, though the first may be a background 4. `amm` finishes the swap, either successfully swapping all 5 wNEAR within the desired slippage, or failing. 5. The `wnear::ft_resolve_transfer` function receives success/failure of the promise. Assuming `amm` implements all-or-nothing transfers (as in, it will not transfer less-than-the-specified amount in order to fulfill the slippage requirements), `wnear` will do nothing at this point if the swap succeeded, or it will decrease the balance of `amm` and increase the balance of `alice` by 5000000000000000000000000. - ### Reference-level explanation -**NOTES**: +NOTES: + - All amounts, balances and allowance are limited by `U128` (max value `2**128 - 1`). - Token standard uses JSON for serialization of arguments and results. - Amounts in arguments and results have are serialized as Base-10 strings, e.g. `"100"`. This is done to avoid JSON limitation of max integer value of `2**53`. - The contract must track the change in storage when adding to and removing from collections. This is not included in this core fungible token standard but instead in the [Storage Standard][Storage Management]. - To prevent the deployed contract from being modified or deleted, it should not have any access keys on its account. -#### Interface: +#### Interface ##### ft_transfer Simple transfer to a receiver. Requirements: -* Caller of the method must attach a deposit of 1 yoctoⓃ for security purposes -* Caller must have greater than or equal to the `amount` being requested + +- Caller of the method must attach a deposit of 1 yoctoⓃ for security purposes +- Caller must have greater than or equal to the `amount` being requested Arguments: -* `receiver_id`: the valid NEAR account receiving the fungible tokens. -* `amount`: the number of tokens to transfer, wrapped in quotes and treated + +- `receiver_id`: the valid NEAR account receiving the fungible tokens. +- `amount`: the number of tokens to transfer, wrapped in quotes and treated like a string, although the number will be stored as an unsigned integer with 128 bits. -* `memo` (optional): for use cases that may benefit from indexing or -providing information for a transfer. +- `memo` (optional): for use cases that may benefit from indexing or + providing information for a transfer. ```ts function ft_transfer( - receiver_id: string, - amount: string, - memo: string|null -): void + receiver_id: string, + amount: string, + memo: string | null +): void; ``` ##### ft_transfer_call @@ -225,46 +230,45 @@ function call. It allows you to attach any Fungible Token in a call to a receiver contract. Requirements: -* Caller of the method must attach a deposit of 1 yoctoⓃ for security + +- Caller of the method must attach a deposit of 1 yoctoⓃ for security purposes -* Caller must have greater than or equal to the `amount` being requested -* The receiving contract must implement `ft_on_transfer` according to the - standard. If it does not, FT contract's `ft_resolve_transfer` MUST deal +- Caller must have greater than or equal to the `amount` being requested +- The receiving contract must implement `ft_on_transfer` according to the + standard. If it does not, FT contract's `ft_resolve_transfer` MUST deal with the resulting failed cross-contract call and roll back the transfer. -* Contract MUST implement the behavior described in `ft_resolve_transfer` +- Contract MUST implement the behavior described in `ft_resolve_transfer` Arguments: -* `receiver_id`: the valid NEAR account receiving the fungible tokens. -* `amount`: the number of tokens to transfer, wrapped in quotes and treated + +- `receiver_id`: the valid NEAR account receiving the fungible tokens. +- `amount`: the number of tokens to transfer, wrapped in quotes and treated like a string, although the number will be stored as an unsigned integer with 128 bits. -* `memo` (optional): for use cases that may benefit from indexing or +- `memo` (optional): for use cases that may benefit from indexing or providing information for a transfer. -* `msg`: specifies information needed by the receiving contract in +- `msg`: specifies information needed by the receiving contract in order to properly handle the transfer. Can indicate both a function to call and the parameters to pass to that function. ```ts function ft_transfer_call( - receiver_id: string, - amount: string, - memo: string|null, - msg: string -): Promise + receiver_id: string, + amount: string, + memo: string | null, + msg: string +): Promise; ``` ##### ft_on_transfer This function is implemented on the receiving contract. -As mentioned, the `msg` argument contains information necessary for the receiving contract to know how to process the request. This may include method names and/or arguments. +As mentioned, the `msg` argument contains information necessary for the receiving contract to know how to process the request. This may include method names and/or arguments. Returns a value, or a promise which resolves with a value. The value is the number of unused tokens in string form. For instance, if `amount` is 10 but only 9 are needed, it will return "1". + ```ts -function ft_on_transfer( - sender_id: string, - amount: string, - msg: string -): string +function ft_on_transfer(sender_id: string, amount: string, msg: string): string; ``` ### View Methods @@ -272,17 +276,17 @@ function ft_on_transfer( ##### ft_total_supply Returns the total supply of fungible tokens as a string representing the value as an unsigned 128-bit integer. + ```js -function ft_total_supply(): string +function ft_total_supply(): string ``` ##### ft_balance_of Returns the balance of an account in string form representing a value as an unsigned 128-bit integer. If the account doesn't exist must returns `"0"`. + ```ts -function ft_balance_of( - account_id: string -): string +function ft_balance_of(account_id: string): string; ``` ##### ft_resolve_transfer @@ -293,35 +297,37 @@ Finalize an `ft_transfer_call` chain of cross-contract calls. The `ft_transfer_call` process: - 1. Sender calls `ft_transfer_call` on FT contract - 2. FT contract transfers `amount` tokens from sender to receiver - 3. FT contract calls `ft_on_transfer` on receiver contract - 4+. [receiver contract may make other cross-contract calls] - N. FT contract resolves promise chain with `ft_resolve_transfer`, and may - refund sender some or all of original `amount` +1. Sender calls `ft_transfer_call` on FT contract +2. FT contract transfers `amount` tokens from sender to receiver +3. FT contract calls `ft_on_transfer` on receiver contract +4. [receiver contract may make other cross-contract calls] +5. FT contract resolves promise chain with `ft_resolve_transfer`, and may refund sender some or all of original `amount` Requirements: - * Contract MUST forbid calls to this function by any account except self - * If promise chain failed, contract MUST revert token transfer - * If promise chain resolves with a non-zero amount given as a string, - contract MUST return this amount of tokens to `sender_id` + +- Contract MUST forbid calls to this function by any account except self +- If promise chain failed, contract MUST revert token transfer +- If promise chain resolves with a non-zero amount given as a string, + contract MUST return this amount of tokens to `sender_id` Arguments: - * `sender_id`: the sender of `ft_transfer_call` - * `receiver_id`: the `receiver_id` argument given to `ft_transfer_call` - * `amount`: the `amount` argument given to `ft_transfer_call` + +- `sender_id`: the sender of `ft_transfer_call` +- `receiver_id`: the `receiver_id` argument given to `ft_transfer_call` +- `amount`: the `amount` argument given to `ft_transfer_call` Returns a string representing a string version of an unsigned 128-bit integer of how many total tokens were spent by sender_id. Example: if sender calls `ft_transfer_call({ "amount": "100" })`, but `receiver_id` only uses 80, `ft_on_transfer` will resolve with `"20"`, and `ft_resolve_transfer` will return `"80"`. + ```ts function ft_resolve_transfer( - sender_id: string, - receiver_id: string, - amount: string -): string + sender_id: string, + receiver_id: string, + amount: string +): string; ``` ### Events @@ -339,10 +345,10 @@ Fungible Token Events MUST have `standard` set to `"nep141"`, standard version s ```ts interface FtEventLogData { - standard: "nep141", - version: "1.0.0", - event: "ft_mint" | "ft_burn" | "ft_transfer", - data: FtMintLog[] | FtTransferLog[] | FtBurnLog[], + standard: "nep141"; + version: "1.0.0"; + event: "ft_mint" | "ft_burn" | "ft_transfer"; + data: FtMintLog[] | FtTransferLog[] | FtBurnLog[]; } ``` @@ -355,9 +361,9 @@ interface FtEventLogData { // with 128 bits. // * `memo`: optional message interface FtMintLog { - owner_id: string, - amount: string, - memo?: string + owner_id: string; + amount: string; + memo?: string; } // An event log to capture tokens burning @@ -368,9 +374,9 @@ interface FtMintLog { // with 128 bits. // * `memo`: optional message interface FtBurnLog { - owner_id: string, - amount: string, - memo?: string + owner_id: string; + amount: string; + memo?: string; } // An event log to capture tokens transfer @@ -382,10 +388,10 @@ interface FtBurnLog { // with 128 bits. // * `memo`: optional message interface FtTransferLog { - old_owner_id: string, - new_owner_id: string, - amount: string, - memo?: string + old_owner_id: string; + new_owner_id: string; + amount: string; + memo?: string; } ``` @@ -434,6 +440,7 @@ EVENT_JSON:{ ### Further Event Methods Note that the example events covered above cover two different kinds of events: + 1. Events that are not specified in the FT Standard (`ft_mint`, `ft_burn`) 2. An event that is covered in the [FT Core Standard][FT Core]. (`ft_transfer`) @@ -443,10 +450,10 @@ Please feel free to open pull requests for extending the events standard detaile The `near-contract-standards` cargo package of the [Near Rust SDK](https://github.com/near/near-sdk-rs) contain the following implementations of NEP-141: -* [Minimum Viable Interface](https://github.com/near/near-sdk-rs/blob/master/near-contract-standards/src/fungible_token/core.rs) -* The [Core Fungible Token Implementation](https://github.com/near/near-sdk-rs/blob/master/near-contract-standards/src/fungible_token/core_impl.rs) -* [Optional Fungible Token Events](https://github.com/near/near-sdk-rs/blob/master/near-contract-standards/src/fungible_token/events.rs) -* [Core Fungible Token tests](https://github.com/near/near-sdk-rs/blob/master/examples/fungible-token/tests/workspaces.rs) +- [Minimum Viable Interface](https://github.com/near/near-sdk-rs/blob/master/near-contract-standards/src/fungible_token/core.rs) +- The [Core Fungible Token Implementation](https://github.com/near/near-sdk-rs/blob/master/near-contract-standards/src/fungible_token/core_impl.rs) +- [Optional Fungible Token Events](https://github.com/near/near-sdk-rs/blob/master/near-contract-standards/src/fungible_token/events.rs) +- [Core Fungible Token tests](https://github.com/near/near-sdk-rs/blob/master/examples/fungible-token/tests/workspaces.rs) ## Drawbacks @@ -461,6 +468,7 @@ The `near-contract-standards` cargo package of the [Near Rust SDK](https://githu ## History See also the discussions: + - [Fungible token core](https://github.com/near/NEPs/discussions/146#discussioncomment-298943) - [Fungible token metadata](https://github.com/near/NEPs/discussions/148) - [Storage standard](https://github.com/near/NEPs/discussions/145) diff --git a/neps/nep-0145.md b/neps/nep-0145.md index 478d18338..88b77ef32 100644 --- a/neps/nep-0145.md +++ b/neps/nep-0145.md @@ -23,7 +23,7 @@ It allows accounts and contracts to: 4. Withdraw some storage deposit by removing associated account data from the contract and then making a call to remove unused deposit. 5. Unregister an account to recover full storage balance. - [storage staking]: https://docs.near.org/concepts/storage/storage-staking +[storage staking]: https://docs.near.org/concepts/storage/storage-staking ## Rationale and alternatives @@ -72,76 +72,90 @@ Let's follow two users, Alice with account `alice` and Bob with account `bob`, a #### 1. Account pays own registration fee -**High-level explanation** +##### High-level explanation 1. Alice checks if she is registered with the `ft` contract. 2. Alice determines the needed registration fee to register with the `ft` contract. 3. Alice issues a transaction to deposit Ⓝ for her account. -**Technical calls** +##### Technical calls -1. Alice queries a view-only method to determine if she already has storage on this contract with `ft::storage_balance_of({"account_id": "alice"})`. Using [NEAR CLI](https://docs.near.org/tools/near-cli) to make this view call, the command would be: +1. Alice queries a view-only method to determine if she already has storage on this contract with `ft::storage_balance_of({"account_id": "alice"})`. Using [NEAR CLI](https://docs.near.org/tools/near-cli) to make this view call, the command would be: - near view ft storage_balance_of '{"account_id": "alice"}' + ```shell + near view ft storage_balance_of '{"account_id": "alice"}' + ``` - The response: + The response: - null + ```shell + null + ``` -2. Alice uses [NEAR CLI](https://docs.near.org/docs/tools/near-cli) to make a view call. +2. Alice uses [NEAR CLI](https://docs.near.org/docs/tools/near-cli) to make a view call. - near view ft storage_balance_bounds + ```shell + near view ft storage_balance_bounds + ``` - As mentioned above, this will show that both `min` and `max` are both 2350000000000000000000 yoctoⓃ. + As mentioned above, this will show that both `min` and `max` are both 2350000000000000000000 yoctoⓃ. -3. Alice converts this yoctoⓃ amount to 0.00235 Ⓝ, then calls `ft::storage_deposit` with this attached deposit. Using NEAR CLI: +3. Alice converts this yoctoⓃ amount to 0.00235 Ⓝ, then calls `ft::storage_deposit` with this attached deposit. Using NEAR CLI: - near call ft storage_deposit '' \ - --accountId alice --amount 0.00235 + ```shell + near call ft storage_deposit '' --accountId alice --amount 0.00235 + ``` - The result: - - { - total: "2350000000000000000000", - available: "0" - } + The result: + ```json + { + "total": "2350000000000000000000", + "available": "0" + } + ``` #### 2. Account pays for another account's storage Alice wishes to eventually send `ft` tokens to Bob who is not registered. She decides to pay for Bob's storage. -**High-level explanation** +##### High-level explanation Alice issues a transaction to deposit Ⓝ for Bob's account. -**Technical calls** +##### Technical calls Alice calls `ft::storage_deposit({"account_id": "bob"})` with the attached deposit of '0.00235'. Using NEAR CLI the command would be: - near call ft storage_deposit '{"account_id": "bob"}' \ - --accountId alice --amount 0.00235 +```shell +near call ft storage_deposit '{"account_id": "bob"}' --accountId alice --amount 0.00235 +``` The result: - { - total: "2350000000000000000000", - available: "0" - } +```json +{ + "total": "2350000000000000000000", + "available": "0" +} +``` #### 3. Unnecessary attempt to register already-registered account Alice accidentally makes the same call again, and even misses a leading zero in her deposit amount. - near call ft storage_deposit '{"account_id": "bob"}' \ - --accountId alice --amount 0.0235 +```shell +near call ft storage_deposit '{"account_id": "bob"}' --accountId alice --amount 0.0235 +``` The result: - { - total: "2350000000000000000000", - available: "0" - } +```json +{ + "total": "2350000000000000000000", + "available": "0" +} +``` Additionally, Alice will be refunded the 0.0235Ⓝ she attached, because the `storage_deposit_bounds.max` specifies that Bob's account cannot have a total balance larger than 0.00235Ⓝ. @@ -149,43 +163,47 @@ Additionally, Alice will be refunded the 0.0235Ⓝ she attached, because the `st Alice decides she doesn't care about her `ft` tokens and wants to forcibly recover her registration fee. If the contract permits this operation, her remaining `ft` tokens will either be burned or transferred to another account, which she may or may not have the ability to specify prior to force-closing. -**High-level explanation** +##### High-level explanation Alice issues a transaction to unregister her account and recover the Ⓝ from her registration fee. She must attach 1 yoctoⓃ, expressed in Ⓝ as `.000000000000000000000001`. -**Technical calls** +##### Technical calls Alice calls `ft::storage_unregister({"force": true})` with a 1 yoctoⓃ deposit. Using NEAR CLI the command would be: - near call ft storage_unregister '{ "force": true }' \ - --accountId alice --depositYocto 1 +```shell +near call ft storage_unregister '{ "force": true }' --accountId alice --depositYocto 1 +``` The result: - true +```shell +true +``` #### 5. Account gracefully closes registration Bob wants to close his account, but has a non-zero balance of `ft` tokens. -**High-level explanation** +##### High-level explanation 1. Bob tries to gracefully close his account, calling `storage_unregister()` without specifying `force=true`. This results in an intelligible error that tells him why his account can't yet be unregistered gracefully. 2. Bob sends all of his `ft` tokens to a friend. 3. Bob retries to gracefully close his account. It works. -**Technical calls** +##### Technical calls -1. Bob calls `ft::storage_unregister()` with a 1 yoctoⓃ deposit. Using NEAR CLI the command would be: +1. Bob calls `ft::storage_unregister()` with a 1 yoctoⓃ deposit. Using NEAR CLI the command would be: - near call ft storage_unregister '' \ - --accountId bob --depositYocto 1 + ```shell + near call ft storage_unregister '' --accountId bob --depositYocto 1 + ``` - It fails with a message like "Cannot gracefully close account with positive remaining balance; bob has balance N" + It fails with a message like "Cannot gracefully close account with positive remaining balance; bob has balance N" -2. Bob transfers his tokens to a friend using `ft_transfer` from the [Fungible Token Core][FT Core] standard. +2. Bob transfers his tokens to a friend using `ft_transfer` from the [Fungible Token Core][FT Core] standard. -3. Bob tries the call from Step 1 again. It works. +3. Bob tries the call from Step 1 again. It works. ### Example 2: Social Media Contract @@ -209,49 +227,55 @@ Let's follow a user, Alice with account `alice`, as she interacts with `social` #### 1. Account registers with `social` -**High-level explanation** +##### High-level explanation -Alice issues a transaction to deposit Ⓝ for her account. While the `storage_balance_bounds.min` for this contract is 0.00235Ⓝ, the frontend she uses suggests adding 0.1Ⓝ, so that she can immediately start adding data to the app, rather than *only* registering. +Alice issues a transaction to deposit Ⓝ for her account. While the `storage_balance_bounds.min` for this contract is 0.00235Ⓝ, the frontend she uses suggests adding 0.1Ⓝ, so that she can immediately start adding data to the app, rather than _only_ registering. -**Technical calls** +##### Technical calls Using NEAR CLI: - near call social storage_deposit '' \ - --accountId alice --amount 0.1 +```shell +near call social storage_deposit '' --accountId alice --amount 0.1 +``` The result: - { - total: '100000000000000000000000', - available: '97650000000000000000000' - } +```json +{ + "total": "100000000000000000000000", + "available": "97650000000000000000000" +} +``` Here we see that she has deposited 0.1Ⓝ and that 0.00235 of it has been used to register her account, and is therefore locked by the contract. The rest is available to facilitate interaction with the contract, but could also be withdrawn by Alice by using `storage_withdraw`. #### 2. Unnecessary attempt to re-register using `registration_only` param -**High-level explanation** +##### High-level explanation Alice can't remember if she already registered and re-sends the call, using the `registration_only` param to ensure she doesn't attach another 0.1Ⓝ. -**Technical calls** +##### Technical calls Using NEAR CLI: - near call social storage_deposit '{"registration_only": true}' \ - --accountId alice --amount 0.1 +```shell +near call social storage_deposit '{"registration_only": true}' --accountId alice --amount 0.1 +``` The result: - { - total: '100000000000000000000000', - available: '97650000000000000000000' - } +```json +{ + "total": "100000000000000000000000", + "available": "97650000000000000000000" +} +``` Additionally, Alice will be refunded the extra 0.1Ⓝ that she just attached. This makes it easy for other contracts to always attempt to register users while performing batch transactions without worrying about errors or lost deposits. -Note that if Alice had not included `registration_only`, she would have ended up with a `total` of 0.2Ⓝ. +Note that if Alice had not included `registration_only`, she would have ended up with a `total` of 0.2Ⓝ. #### 3. Account increases storage deposit @@ -259,75 +283,85 @@ Assumption: `social` has a `post` function which allows creating a new post with Note that applications will probably want to avoid this situation in the first place by prompting users to top up storage deposits sufficiently before available balance runs out. -**High-level explanation** +##### High-level explanation 1. Alice issues a transaction, let's say `social.post`, and it fails with an intelligible error message to tell her that she has an insufficient storage balance to cover the cost of the operation 2. Alice issues a transaction to increase her storage balance 3. Alice retries the initial transaction and it succeeds -**Technical calls** +##### Technical calls -1. This is outside the scope of this spec, but let's say Alice calls `near call social post '{ "text": "very long message" }'`, and that this fails with a message saying something like "Insufficient storage deposit for transaction. Please call `storage_deposit` and attach at least 0.1 NEAR, then try again." +1. This is outside the scope of this spec, but let's say Alice calls `near call social post '{ "text": "very long message" }'`, and that this fails with a message saying something like "Insufficient storage deposit for transaction. Please call `storage_deposit` and attach at least 0.1 NEAR, then try again." -2. Alice deposits the proper amount in a transaction by calling `social::storage_deposit` with the attached deposit of '0.1'. Using NEAR CLI: +2. Alice deposits the proper amount in a transaction by calling `social::storage_deposit` with the attached deposit of '0.1'. Using NEAR CLI: - near call social storage_deposit '' \ - --accountId alice --amount 0.1 + ```shell + near call social storage_deposit '' --accountId alice --amount 0.1 + ``` - The result: + The result: - { - total: '200000000000000000000000', - available: '100100000000000000000000' - } + ```json + { + "total": "200000000000000000000000", + "available": "100100000000000000000000" + } + ``` -3. Alice tries the initial `near call social post` call again. It works. +3. Alice tries the initial `near call social post` call again. It works. #### 4. Removing storage and reclaiming excess deposit Assumption: Alice has more deposited than she is using. -**High-level explanation** +##### High-level explanation 1. Alice views her storage balance and sees that she has extra. 2. Alice withdraws her excess deposit. -**Technical calls** +##### Technical calls -1. Alice queries `social::storage_balance_of({ "account_id": "alice" })`. With NEAR CLI: +1. Alice queries `social::storage_balance_of({ "account_id": "alice" })`. With NEAR CLI: - near view social storage_balance_of '{"account_id": "alice"}' + ```shell + near view social storage_balance_of '{"account_id": "alice"}' + ``` - Response: + Response: - { - total: '200000000000000000000000', - available: '100100000000000000000000' - } + ```json + { + "total": "200000000000000000000000", + "available": "100100000000000000000000" + } + ``` -2. Alice calls `storage_withdraw` with a 1 yoctoⓃ deposit. NEAR CLI command: +2. Alice calls `storage_withdraw` with a 1 yoctoⓃ deposit. NEAR CLI command: - near call social storage_withdraw \ - '{"amount": "100100000000000000000000"}' \ - --accountId alice --depositYocto 1 + ```shell + near call social storage_withdraw '{"amount": "100100000000000000000000"}' \ + --accountId alice --depositYocto 1 + ``` - Result: + Result: - { - total: '200000000000000000000000', - available: '0' - } + ```json + { + "total": "200000000000000000000000", + "available": "0" + } + ``` ## Specification -**NOTES**: +NOTES: - All amounts, balances and allowance are limited by `U128` (max value 2128 - 1). - This storage standard uses JSON for serialization of arguments and results. - Amounts in arguments and results are serialized as Base-10 strings, e.g. `"100"`. This is done to avoid JSON limitation of max integer value of 253. - To prevent the deployed contract from being modified or deleted, it should not have any access keys on its account. -**Interface**: +### Interface ```ts // The structure that will be returned for the methods: @@ -337,9 +371,9 @@ Assumption: Alice has more deposited than she is using. // The `total` and `available` values are string representations of unsigned // 128-bit integers showing the balance of a specific account in yoctoⓃ. type StorageBalance = { - total: string; - available: string; -} + total: string; + available: string; +}; // The below structure will be returned for the method `storage_balance_bounds`. // Both `min` and `max` are string representations of unsigned 128-bit integers. @@ -354,9 +388,9 @@ type StorageBalance = { // which implements `max` must refund deposits that would increase a user's // storage balance beyond this amount. type StorageBalanceBounds = { - min: string; - max: string|null; -} + min: string; + max: string | null; +}; /************************************/ /* CHANGE METHODS on fungible token */ @@ -376,8 +410,8 @@ type StorageBalanceBounds = { // // Returns the StorageBalance structure showing updated balances. function storage_deposit( - account_id: string|null, - registration_only: boolean|null + account_id: string | null, + registration_only: boolean | null ): StorageBalance {} // Withdraw specified amount of available Ⓝ for predecessor account. @@ -394,7 +428,7 @@ function storage_deposit( // function-call access-key call (UX wallet security) // // Returns the StorageBalance structure showing updated balances. -function storage_withdraw(amount: string|null): StorageBalance {} +function storage_withdraw(amount: string | null): StorageBalance {} // Unregisters the predecessor account and returns the storage NEAR deposit. // @@ -416,7 +450,7 @@ function storage_withdraw(amount: string|null): StorageBalance {} // // Returns `true` iff the account was successfully unregistered. // Returns `false` iff account was not registered before. -function storage_unregister(force: boolean|null): boolean {} +function storage_unregister(force: boolean | null): boolean {} /****************/ /* VIEW METHODS */ @@ -429,15 +463,15 @@ function storage_balance_bounds(): StorageBalanceBounds {} // provided. Must panic if `account_id` is invalid. // // If `account_id` is not registered, must return `null`. -function storage_balance_of(account_id: string): StorageBalance|null {} +function storage_balance_of(account_id: string): StorageBalance | null {} ``` ## Reference Implementation The `near-contract-standards` cargo package of the [Near Rust SDK](https://github.com/near/near-sdk-rs) contain the following implementations of NEP-145: -* [Minimum Viable Interface](https://github.com/near/near-sdk-rs/blob/master/near-contract-standards/src/storage_management/mod.rs#L20) -* [Implementation](https://github.com/near/near-sdk-rs/blob/master/near-contract-standards/src/storage_management/mod.rs) +- [Minimum Viable Interface](https://github.com/near/near-sdk-rs/blob/master/near-contract-standards/src/storage_management/mod.rs#L20) +- [Implementation](https://github.com/near/near-sdk-rs/blob/master/near-contract-standards/src/storage_management/mod.rs) ## Drawbacks @@ -446,10 +480,9 @@ The `near-contract-standards` cargo package of the [Near Rust SDK](https://githu ## Future possibilities -- Ideally, contracts will update available balance for all accounts every time the NEAR blockchain's configured storage-cost-per-byte is reduced. That they *must* do so is not enforced by this current standard. +- Ideally, contracts will update available balance for all accounts every time the NEAR blockchain's configured storage-cost-per-byte is reduced. That they _must_ do so is not enforced by this current standard. ## Copyright -[copyright]: #copyright Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). diff --git a/neps/nep-0148.md b/neps/nep-0148.md index ff2a68357..1bcc59692 100644 --- a/neps/nep-0148.md +++ b/neps/nep-0148.md @@ -19,6 +19,7 @@ An interface for a fungible token's metadata. The goal is to keep the metadata f Custom fungible tokens play a major role in decentralized applications today. FTs can contain custom properties to differentiate themselves from other tokens or contracts in the ecosystem. In NEAR, many common properties can be stored right on-chain. Other properties are best stored off-chain or in a decentralized storage platform, in order to save on storage costs and allow rapid community experimentation. ## Rationale and alternatives + As blockchain technology advances, it becomes increasingly important to provide backwards compatibility and a concept of a spec. This standard encompasses all of these concerns. Prior art: @@ -36,33 +37,34 @@ A fungible token smart contract allows for discoverable properties. Some propert Alice deploys a wBTC fungible token contract. -**Assumptions** +##### Assumptions - The wBTC token contract is `wbtc`. - Alice's account is `alice`. - The precision ("decimals" in this metadata standard) on wBTC contract is `10^8`. -**High-level explanation** +##### High-level explanation Alice issues a transaction to deploy and initialize the fungible token contract, providing arguments to the initialization function that set metadata fields. -**Technical calls** +##### Technical calls 1. `alice` deploys a contract and calls `wbtc::new` with all metadata. If this deploy and initialization were done using [NEAR CLI](https://docs.near.org/tools/near-cli) the command would be: - near deploy wbtc --wasmFile res/ft.wasm --initFunction new --initArgs '{ - "owner_id": "wbtc", - "total_supply": "100000000000000", - "metadata": { - "spec": "ft-1.0.0", - "name": "Wrapped Bitcoin", - "symbol": "WBTC", - "icon": "data:image/svg+xml,%3C…", - "reference": "https://example.com/wbtc.json", - "reference_hash": "AK3YRHqKhCJNmKfV6SrutnlWW/icN5J8NUPtKsNXR1M=", - "decimals": 8 - } - }' --accountId alice +```shell +near deploy wbtc --wasmFile res/ft.wasm --initFunction new --initArgs '{ + "owner_id": "wbtc", + "total_supply": "100000000000000", + "metadata": { + "spec": "ft-1.0.0", + "name": "Wrapped Bitcoin", + "symbol": "WBTC", + "icon": "data:image/svg+xml,%3C…", + "reference": "https://example.com/wbtc.json", + "reference_hash": "AK3YRHqKhCJNmKfV6SrutnlWW/icN5J8NUPtKsNXR1M=", + "decimals": 8 + }}' --accountId alice +``` ## Reference-level explanation @@ -72,28 +74,28 @@ A fungible token contract implementing the metadata standard shall contain a fun function ft_metadata(): FungibleTokenMetadata {} ``` -**Interface**: +##### Interface ```ts type FungibleTokenMetadata = { - spec: string; - name: string; - symbol: string; - icon: string|null; - reference: string|null; - reference_hash: string|null; - decimals: number; -} + spec: string; + name: string; + symbol: string; + icon: string | null; + reference: string | null; + reference_hash: string | null; + decimals: number; +}; ``` -**An implementing contract MUST include the following fields on-chain** +An implementing contract MUST include the following fields on-chain - `spec`: a string. Should be `ft-1.0.0` to indicate that a Fungible Token contract adheres to the current versions of this Metadata and the [Fungible Token Core][FT Core] specs. This will allow consumers of the Fungible Token to know if they support the features of a given contract. - `name`: the human-readable name of the token. - `symbol`: the abbreviation, like wETH or AMPL. - `decimals`: used in frontends to show the proper significant digits of a token. This concept is explained well in this [OpenZeppelin post](https://docs.openzeppelin.com/contracts/3.x/erc20#a-note-on-decimals). -**An implementing contract MAY include the following fields on-chain** +An implementing contract MAY include the following fields on-chain - `icon`: a small image associated with this token. Must be a [data URL](https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/Data_URIs), to help consumers display it quickly while protecting user data. Recommendation: use [optimized SVG](https://codepen.io/tigt/post/optimizing-svgs-in-data-uris), which can result in high-resolution images with only 100s of bytes of [storage cost](https://docs.near.org/concepts/storage/storage-staking). (Note that these storage costs are incurred to the token owner/deployer, but that querying these icons is a very cheap & cacheable read operation for all consumers of the contract and the RPC nodes that serve the data.) Recommendation: create icons that will work well with both light-mode and dark-mode websites by either using middle-tone color schemes, or by [embedding `media` queries in the SVG](https://timkadlec.com/2013/04/media-queries-within-svg/). - `reference`: a link to a valid JSON file containing various keys offering supplementary details on the token. Example: "/ipfs/QmdmQXB2mzChmMeKY47C43LxUdg1NDJ5MWcKMKxDu7RgQm", "https://example.com/token.json", etc. If the information given in this document conflicts with the on-chain attributes, the values in `reference` shall be considered the source of truth. @@ -103,7 +105,7 @@ type FungibleTokenMetadata = { The `near-contract-standards` cargo package of the [Near Rust SDK](https://github.com/near/near-sdk-rs) contain the following implementations of NEP-148: -* [Implementation](https://github.com/near/near-sdk-rs/blob/master/near-contract-standards/src/fungible_token/metadata.rs) +- [Implementation](https://github.com/near/near-sdk-rs/blob/master/near-contract-standards/src/fungible_token/metadata.rs) ## Drawbacks @@ -112,11 +114,11 @@ The `near-contract-standards` cargo package of the [Near Rust SDK](https://githu - If on-chain icon uses a data URL or is not set but the document given by `reference` contains a privacy-violating `icon` URL, consumers & apps of this data should not naïvely display the `reference` version, but should prefer the safe version. This is technically a violation of the "`reference` setting wins" policy described above. ## Future possibilities + - Detailed conventions that may be enforced for versions. - A fleshed out schema for what the `reference` object should contain. ## Copyright -[copyright]: #copyright Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). diff --git a/neps/nep-0171.md b/neps/nep-0171.md index 2d6278007..1b7228892 100644 --- a/neps/nep-0171.md +++ b/neps/nep-0171.md @@ -27,9 +27,9 @@ This standard builds off the lessons learned in this early experimentation, and Given these attributes, this NFT standard can accomplish with one user interaction things for which other blockchains need two or three. Most noteworthy is `nft_transfer_call`, by which a user can essentially attach a token to a call to a separate contract. An example scenario: -* An [Exquisite Corpse](https://en.wikipedia.org/wiki/Exquisite_corpse) contract allows three drawings to be submitted, one for each section of a final composition, to be minted as its own NFT and sold on a marketplace, splitting royalties amongst the original artists. -* Alice draws the top third and submits it, Bob the middle third, and Carol follows up with the bottom third. Since they each use `nft_transfer_call` to both transfer their NFT to the Exquisite Corpse contract as well as call a `submit` method on it, the call from Carol can automatically kick off minting a composite NFT from the three submissions, as well as listing this composite NFT in a marketplace. -* When Dan attempts to also call `nft_transfer_call` to submit an unneeded top third of the drawing, the Exquisite Corpse contract can throw an error, and the transfer will be rolled back so that Bob maintains ownership of his NFT. +- An [Exquisite Corpse](https://en.wikipedia.org/wiki/Exquisite_corpse) contract allows three drawings to be submitted, one for each section of a final composition, to be minted as its own NFT and sold on a marketplace, splitting royalties amongst the original artists. +- Alice draws the top third and submits it, Bob the middle third, and Carol follows up with the bottom third. Since they each use `nft_transfer_call` to both transfer their NFT to the Exquisite Corpse contract as well as call a `submit` method on it, the call from Carol can automatically kick off minting a composite NFT from the three submissions, as well as listing this composite NFT in a marketplace. +- When Dan attempts to also call `nft_transfer_call` to submit an unneeded top third of the drawing, the Exquisite Corpse contract can throw an error, and the transfer will be rolled back so that Bob maintains ownership of his NFT. While this is already flexible and powerful enough to handle all sorts of existing and new use-cases, apps such as marketplaces may still benefit from the [Approval Management] extension. @@ -41,7 +41,6 @@ Prior art: ## Rationale and alternatives -[rationale-and-alternatives]: #rationale-and-alternatives - Why is this design the best in the space of possible designs? - What other designs have been considered and what is the rationale for not choosing them? @@ -50,6 +49,7 @@ Prior art: ## Specification **NOTES**: + - All amounts, balances and allowance are limited by `U128` (max value `2**128 - 1`). - Token standard uses JSON for serialization of arguments and results. - Amounts in arguments and results are serialized as Base-10 strings, e.g. `"100"`. This is done to avoid JSON limitation of max integer value of `2**53`. @@ -364,6 +364,7 @@ EVENT_JSON:{ #### Events for Other NFT Methods Note that the example events above cover two different kinds of events: + 1. Events that do not have a dedicated trigger function in the NFT Standard (`nft_mint`, `nft_burn`, `contract_metadata_update`) 2. An event that has a relevant trigger function [NFT Core Standard](https://nomicon.io/Standards/NonFungibleToken/Core.html#nft-interface) (`nft_transfer`) @@ -385,9 +386,9 @@ Please feel free to open pull requests for extending the events standard detaile This NEP had several pre-1.0.0 iterations that led to the following errata updates to this NEP: -* **2022-02-03**: updated `Token` struct field names. `id` was changed to `token_id`. This is to be consistent with current implementations of the standard and the rust SDK docs. -* **2021-12-20**: updated `nft_resolve_transfer` argument `approved_account_ids` to be type `null|Record` instead of `null|string[]`. This gives contracts a way to restore the original approved accounts and their approval IDs. More information can be found in [this](https://github.com/near/NEPs/issues/301) discussion. -* **2021-07-16**: updated `nft_transfer_call` argument `approval_id` to be type `number|null` instead of `string|null`. As stated, approval IDs are not expected to exceed the JSON limit of 2^53. +- **2022-02-03**: updated `Token` struct field names. `id` was changed to `token_id`. This is to be consistent with current implementations of the standard and the rust SDK docs. +- **2021-12-20**: updated `nft_resolve_transfer` argument `approved_account_ids` to be type `null|Record` instead of `null|string[]`. This gives contracts a way to restore the original approved accounts and their approval IDs. More information can be found in [this](https://github.com/near/NEPs/issues/301) discussion. +- **2021-07-16**: updated `nft_transfer_call` argument `approval_id` to be type `number|null` instead of `string|null`. As stated, approval IDs are not expected to exceed the JSON limit of 2^53. ### 1.1.0 - Add `contract_metadata_update` Event @@ -395,8 +396,8 @@ The extension NEP-0423 that added Contract Metadata to this NEP-0171 was approve #### Benefits -* This new event type will help indexers to invalidate their cached values reliably and efficiently -* This NEP extension only introduces an additional event type, so there is no breaking change to the original NEP +- This new event type will help indexers to invalidate their cached values reliably and efficiently +- This NEP extension only introduces an additional event type, so there is no breaking change to the original NEP #### Concerns @@ -407,7 +408,6 @@ The extension NEP-0423 that added Contract Metadata to this NEP-0171 was approve ## Copyright -[copyright]: #copyright Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). diff --git a/neps/nep-0177.md b/neps/nep-0177.md index b223eb558..2c3969ff0 100644 --- a/neps/nep-0177.md +++ b/neps/nep-0177.md @@ -114,7 +114,6 @@ Contracts should be implemented in a way to avoid extra gas fees for serializati ## Reference Implementation -[reference-implementation]: #reference-implementation This is the technical portion of the NEP. Explain the design in sufficient detail that: @@ -127,9 +126,9 @@ The section should return to the examples given in the previous section, and exp ## Drawbacks -* When this NFT contract is created and initialized, the storage use per-token will be higher than an NFT Core version. Frontends can account for this by adding extra deposit when minting. This could be done by padding with a reasonable amount, or by the frontend using the [RPC call detailed here](https://docs.near.org/docs/develop/front-end/rpc#genesis-config) that gets genesis configuration and actually determine precisely how much deposit is needed. -* Convention of `icon` being a data URL rather than a link to an HTTP endpoint that could contain privacy-violating code cannot be done on deploy or update of contract metadata, and must be done on the consumer/app side when displaying token data. -* If on-chain icon uses a data URL or is not set but the document given by `reference` contains a privacy-violating `icon` URL, consumers & apps of this data should not naïvely display the `reference` version, but should prefer the safe version. This is technically a violation of the "`reference` setting wins" policy described above. +- When this NFT contract is created and initialized, the storage use per-token will be higher than an NFT Core version. Frontends can account for this by adding extra deposit when minting. This could be done by padding with a reasonable amount, or by the frontend using the [RPC call detailed here](https://docs.near.org/docs/develop/front-end/rpc#genesis-config) that gets genesis configuration and actually determine precisely how much deposit is needed. +- Convention of `icon` being a data URL rather than a link to an HTTP endpoint that could contain privacy-violating code cannot be done on deploy or update of contract metadata, and must be done on the consumer/app side when displaying token data. +- If on-chain icon uses a data URL or is not set but the document given by `reference` contains a privacy-violating `icon` URL, consumers & apps of this data should not naïvely display the `reference` version, but should prefer the safe version. This is technically a violation of the "`reference` setting wins" policy described above. ## Future possibilities @@ -138,9 +137,10 @@ The section should return to the examples given in the previous section, and exp ## Errata -* **2022-02-03**: updated `Token` struct field names. `id` was changed to `token_id`. This is to be consistent with current implementations of the standard and the rust SDK docs. +- **2022-02-03**: updated `Token` struct field names. `id` was changed to `token_id`. This is to be consistent with current implementations of the standard and the rust SDK docs. The first version (`1.0.0`) had confusing language regarding the fields: + - `issued_at` - `expires_at` - `starts_at` @@ -149,7 +149,6 @@ The first version (`1.0.0`) had confusing language regarding the fields: It gave those fields the type `string|null` but it was unclear whether it should be a Unix epoch in milliseconds or [ISO 8601](https://www.iso.org/iso-8601-date-and-time-format.html). Upon having to revisit this, it was determined to be the most efficient to use epoch milliseconds as it would reduce the computation on the smart contract and can be derived trivially from the block timestamp. ## Copyright -[copyright]: #copyright Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). diff --git a/neps/nep-0178.md b/neps/nep-0178.md index 9ff177cef..cfbc49398 100644 --- a/neps/nep-0178.md +++ b/neps/nep-0178.md @@ -35,11 +35,11 @@ Prior art: Let's consider some examples. Our cast of characters & apps: -* Alice: has account `alice` with no contract deployed to it -* Bob: has account `bob` with no contract deployed to it -* NFT: a contract with account `nft`, implementing only the [Core NFT standard][NFT Core] with this Approval Management extension -* Market: a contract with account `market` which sells tokens from `nft` as well as other NFT contracts -* Bazaar: similar to Market, but implemented differently (spoiler alert: has no `nft_on_approve` function!), has account `bazaar` +- Alice: has account `alice` with no contract deployed to it +- Bob: has account `bob` with no contract deployed to it +- NFT: a contract with account `nft`, implementing only the [Core NFT standard][NFT Core] with this Approval Management extension +- Market: a contract with account `market` which sells tokens from `nft` as well as other NFT contracts +- Bazaar: similar to Market, but implemented differently (spoiler alert: has no `nft_on_approve` function!), has account `bazaar` Alice and Bob are already [registered][Storage Management] with NFT, Market, and Bazaar, and Alice owns a token on the NFT contract with ID=`"1"`. @@ -57,80 +57,94 @@ Let's examine the technical calls through the following scenarios: Alice approves Bob to transfer her token. -**High-level explanation** +##### High-level explanation 1. Alice approves Bob 2. Alice queries the token to verify 3. Alice verifies a different way -**Technical calls** +##### Technical calls -1. Alice calls `nft::nft_approve({ "token_id": "1", "account_id": "bob" })`. She attaches 1 yoctoⓃ, (.000000000000000000000001Ⓝ). Using [NEAR CLI](https://docs.near.org/tools/near-cli) to make this call, the command would be: +1. Alice calls `nft::nft_approve({ "token_id": "1", "account_id": "bob" })`. She attaches 1 yoctoⓃ, (.000000000000000000000001Ⓝ). Using [NEAR CLI](https://docs.near.org/tools/near-cli) to make this call, the command would be: - near call nft nft_approve \ - '{ "token_id": "1", "account_id": "bob" }' \ - --accountId alice --depositYocto 1 + ```shell + near call nft nft_approve \ + '{ "token_id": "1", "account_id": "bob" }' \ + --accountId alice --depositYocto 1 + ``` - The response: + The response: - '' + ```shell + '' + ``` -2. Alice calls view method `nft_token`: +2. Alice calls view method `nft_token`: - near view nft nft_token \ - '{ "token_id": "1" }' + ```shell + near view nft nft_token '{ "token_id": "1" }' + ``` - The response: + The response: - { - "token_id": "1", - "owner_id": "alice.near", - "approved_account_ids": { - "bob": 1, - } - } + ```json + { + "token_id": "1", + "owner_id": "alice.near", + "approved_account_ids": { + "bob": 1 + } + } + ``` -3. Alice calls view method `nft_is_approved`: +3. Alice calls view method `nft_is_approved`: - near view nft nft_is_approved \ - '{ "token_id": "1", "approved_account_id": "bob" }' + ```shell + near view nft nft_is_approved '{ "token_id": "1", "approved_account_id": "bob" }' + ``` - The response: + The response: - true + ```shell + true + ``` ### 2. Approval with cross-contract call Alice approves Market to transfer one of her tokens and passes `msg` so that NFT will call `nft_on_approve` on Market's contract. She probably does this via Market's frontend app which would know how to construct `msg` in a useful way. -**High-level explanation** +##### High-level explanation 1. Alice calls `nft_approve` to approve `market` to transfer her token, and passes a `msg` 2. Since `msg` is included, `nft` will schedule a cross-contract call to `market` 3. Market can do whatever it wants with this info, such as listing the token for sale at a given price. The result of this operation is returned as the promise outcome to the original `nft_approve` call. -**Technical calls** +##### Technical calls -1. Using near-cli: +1. Using near-cli: - near call nft nft_approve '{ - "token_id": "1", - "account_id": "market", - "msg": "{\"action\": \"list\", \"price\": \"100\", \"token\": \"nDAI\" }" - }' --accountId alice --depositYocto 1 + ```shell + near call nft nft_approve '{ + "token_id": "1", + "account_id": "market", + "msg": "{\"action\": \"list\", \"price\": \"100\", \"token\": \"nDAI\" }" + }' --accountId alice --depositYocto 1 + ``` - At this point, near-cli will hang until the cross-contract call chain fully resolves, which would also be true if Alice used a Market frontend using [near-api-js](https://docs.near.org/tools/near-api-js/quick-reference). Alice's part is done, though. The rest happens behind the scenes. + At this point, near-cli will hang until the cross-contract call chain fully resolves, which would also be true if Alice used a Market frontend using [near-api-js](https://docs.near.org/tools/near-api-js/quick-reference). Alice's part is done, though. The rest happens behind the scenes. -2. `nft` schedules a call to `nft_on_approve` on `market`. Using near-cli notation for easy cross-reference with the above, this would look like: +2. `nft` schedules a call to `nft_on_approve` on `market`. Using near-cli notation for easy cross-reference with the above, this would look like: - near call market nft_on_approve '{ - "token_id": "1", - "owner_id": "alice", - "approval_id": 2, - "msg": "{\"action\": \"list\", \"price\": \"100\", \"token\": \"nDAI\" }" - }' --accountId nft + ```shell + near call market nft_on_approve '{ + "token_id": "1", + "owner_id": "alice", + "approval_id": 2, + "msg": "{\"action\": \"list\", \"price\": \"100\", \"token\": \"nDAI\" }" + }' --accountId nft + ``` -3. `market` now knows that it can sell Alice's token for 100 [nDAI](https://explorer.mainnet.near.org/accounts/6b175474e89094c44da98b954eedeac495271d0f.factory.bridge.near), and that when it transfers it to a buyer using `nft_transfer`, it can pass along the given `approval_id` to ensure that Alice hasn't changed her mind. It can schedule any further cross-contract calls it wants, and if it returns these promises correctly, Alice's initial near-cli call will resolve with the outcome from the final step in the chain. If Alice actually made this call from a Market frontend, the frontend can use this return value for something useful. +3. `market` now knows that it can sell Alice's token for 100 [nDAI](https://explorer.mainnet.near.org/accounts/6b175474e89094c44da98b954eedeac495271d0f.factory.bridge.near), and that when it transfers it to a buyer using `nft_transfer`, it can pass along the given `approval_id` to ensure that Alice hasn't changed her mind. It can schedule any further cross-contract calls it wants, and if it returns these promises correctly, Alice's initial near-cli call will resolve with the outcome from the final step in the chain. If Alice actually made this call from a Market frontend, the frontend can use this return value for something useful. ### 3. Approval with cross-contract call, edge case @@ -138,91 +152,105 @@ Alice approves Bazaar and passes `msg` again. Maybe she actually does this via n Not to worry, though, she checks `nft_is_approved` and sees that she did successfully approve Bazaar, despite the error. She will have to find a new way to list her token for sale in Bazaar, rather than using the same `msg` shortcut that worked for Market. -**High-level explanation** +##### High-level explanation 1. Alice calls `nft_approve` to approve `bazaar` to transfer her token, and passes a `msg`. 2. Since `msg` is included, `nft` will schedule a cross-contract call to `bazaar`. 3. Bazaar doesn't implement `nft_on_approve`, so this call results in an error. The approval still worked, but Alice sees an error in her near-cli output. 4. Alice checks if `bazaar` is approved, and sees that it is, despite the error. -**Technical calls** +##### Technical calls -1. Using near-cli: +1. Using near-cli: - near call nft nft_approve '{ - "token_id": "1", - "account_id": "bazaar", - "msg": "{\"action\": \"list\", \"price\": \"100\", \"token\": \"nDAI\" }" - }' --accountId alice --depositYocto 1 + ```shell + near call nft nft_approve '{ + "token_id": "1", + "account_id": "bazaar", + "msg": "{\"action\": \"list\", \"price\": \"100\", \"token\": \"nDAI\" }" + }' --accountId alice --depositYocto 1 + ``` -2. `nft` schedules a call to `nft_on_approve` on `market`. Using near-cli notation for easy cross-reference with the above, this would look like: +2. `nft` schedules a call to `nft_on_approve` on `market`. Using near-cli notation for easy cross-reference with the above, this would look like: - near call bazaar nft_on_approve '{ - "token_id": "1", - "owner_id": "alice", - "approval_id": 3, - "msg": "{\"action\": \"list\", \"price\": \"100\", \"token\": \"nDAI\" }" - }' --accountId nft + ```shell + near call bazaar nft_on_approve '{ + "token_id": "1", + "owner_id": "alice", + "approval_id": 3, + "msg": "{\"action\": \"list\", \"price\": \"100\", \"token\": \"nDAI\" }" + }' --accountId nft + ``` -3. 💥 `bazaar` doesn't implement this method, so the call results in an error. Alice sees this error in the output from near-cli. +3. 💥 `bazaar` doesn't implement this method, so the call results in an error. Alice sees this error in the output from near-cli. -4. Alice checks if the approval itself worked, despite the error on the cross-contract call: +4. Alice checks if the approval itself worked, despite the error on the cross-contract call: - near view nft nft_is_approved \ - '{ "token_id": "1", "approved_account_id": "bazaar" }' + ```shell + near view nft nft_is_approved \ + '{ "token_id": "1", "approved_account_id": "bazaar" }' + ``` - The response: + The response: - true + ```shell + true + ``` ### 4. Approval IDs Bob buys Alice's token via Market. Bob probably does this via Market's frontend, which will probably initiate the transfer via a call to `ft_transfer_call` on the nDAI contract to transfer 100 nDAI to `market`. Like the NFT standard's "transfer and call" function, [Fungible Token][FT Core]'s `ft_transfer_call` takes a `msg` which `market` can use to pass along information it will need to pay Alice and actually transfer the NFT. The actual transfer of the NFT is the only part we care about here. -**High-level explanation** +##### High-level explanation 1. Bob signs some transaction which results in the `market` contract calling `nft_transfer` on the `nft` contract, as described above. To be trustworthy and pass security audits, `market` needs to pass along `approval_id` so that it knows it has up-to-date information. -**Technical calls** +##### Technical calls Using near-cli notation for consistency: - near call nft nft_transfer '{ - "receiver_id": "bob", - "token_id": "1", - "approval_id": 2, - }' --accountId market --depositYocto 1 +```shell +near call nft nft_transfer '{ + "receiver_id": "bob", + "token_id": "1", + "approval_id": 2, + }' --accountId market --depositYocto 1 +``` ### 5. Approval IDs, edge case Bob transfers same token back to Alice, Alice re-approves Market & Bazaar, listing her token at a higher price than before. Bazaar is somehow unaware of these changes, and still stores `approval_id: 3` internally along with Alice's old price. Bob tries to buy from Bazaar at the old price. Like the previous example, this probably starts with a call to a different contract, which eventually results in a call to `nft_transfer` on `bazaar`. Let's consider a possible scenario from that point. -**High-level explanation** +##### High-level explanation Bob signs some transaction which results in the `bazaar` contract calling `nft_transfer` on the `nft` contract, as described above. To be trustworthy and pass security audits, `bazaar` needs to pass along `approval_id` so that it knows it has up-to-date information. It does not have up-to-date information, so the call fails. If the initial `nft_transfer` call is part of a call chain originating from a call to `ft_transfer_call` on a fungible token, Bob's payment will be refunded and no assets will change hands. -**Technical calls** +##### Technical calls Using near-cli notation for consistency: - near call nft nft_transfer '{ - "receiver_id": "bob", - "token_id": "1", - "approval_id": 3, - }' --accountId bazaar --depositYocto 1 +```shell +near call nft nft_transfer '{ + "receiver_id": "bob", + "token_id": "1", + "approval_id": 3, + }' --accountId bazaar --depositYocto 1 +``` ### 6. Revoke one Alice revokes Market's approval for this token. -**Technical calls** +##### Technical calls Using near-cli: - near call nft nft_revoke '{ - "account_id": "market", - "token_id": "1", - }' --accountId alice --depositYocto 1 +```shell +near call nft nft_revoke '{ + "account_id": "market", + "token_id": "1", + }' --accountId alice --depositYocto 1 +``` Note that `market` will not get a cross-contract call in this case. The implementers of the Market app should implement [cron](https://en.wikipedia.org/wiki/Cron)-type functionality to intermittently check that Market still has the access they expect. @@ -230,13 +258,15 @@ Note that `market` will not get a cross-contract call in this case. The implemen Alice revokes all approval for this token. -**Technical calls** +##### Technical calls Using near-cli: - near call nft nft_revoke_all '{ - "token_id": "1", - }' --accountId alice --depositYocto 1 +```shell +near call nft nft_revoke_all '{ + "token_id": "1", + }' --accountId alice --depositYocto 1 +``` Again, note that no previous approvers will get cross-contract calls in this case. @@ -260,7 +290,7 @@ Example token data: "owner_id": "alice.near", "approved_account_ids": { "bob.near": 1, - "carol.near": 2, + "carol.near": 2 } } ``` @@ -287,7 +317,7 @@ Keeping with the example above, say the initial approval of the second marketpla "owner_id": "alice.near", "approved_account_ids": { "marketplace_1.near": 1, - "marketplace_2.near": 2, + "marketplace_2.near": 2 } } ``` @@ -299,7 +329,7 @@ But after the transfers and re-approval described above, the token might have `a "token_id": "1", "owner_id": "alice.near", "approved_account_ids": { - "marketplace_2.near": 3, + "marketplace_2.near": 3 } } ``` @@ -311,7 +341,6 @@ The marketplace then tries to call `nft_transfer`, passing outdated information: near call nft-contract.near nft_transfer '{ "approval_id": 2 }' ``` - ### Interface The NFT contract must implement the following methods: @@ -346,8 +375,8 @@ The NFT contract must implement the following methods: function nft_approve( token_id: TokenId, account_id: string, - msg: string|null, -): void|Promise {} + msg: string | null +): void | Promise {} // Revoke an approved account for a specific token. // @@ -361,10 +390,7 @@ function nft_approve( // Arguments: // * `token_id`: the token for which to revoke an approval // * `account_id`: the account to remove from `approved_account_ids` -function nft_revoke( - token_id: string, - account_id: string -) {} +function nft_revoke(token_id: string, account_id: string) {} // Revoke all approved accounts for a specific token. // @@ -397,7 +423,7 @@ function nft_revoke_all(token_id: string) {} function nft_is_approved( token_id: string, approved_account_id: string, - approval_id: number|null + approval_id: number | null ): boolean {} ``` @@ -405,8 +431,8 @@ function nft_is_approved( In the description of `nft_approve` above, it states: - Contract MUST panic if addition would cause `nft_revoke_all` to exceed - single-block gas limit. +> Contract MUST panic if addition would cause `nft_revoke_all` to exceed +> single-block gas limit. What does this mean? @@ -418,7 +444,6 @@ Contracts must prevent this by capping the number of approved_account_ids for a Contract authors may choose to set a cap of something small and safe like 10 approved_account_ids, or they could dynamically calculate whether a new approval would break future calls to `nft_revoke_all`. But every contract MUST ensure that they never break the functionality of `nft_revoke_all`. - ### Approved Account Contract Interface If a contract that gets approved to transfer NFTs wants to, it can implement `nft_on_approve` to update its own state when granted approval for a token: @@ -441,7 +466,7 @@ function nft_on_approve( token_id: TokenId, owner_id: string, approval_id: number, - msg: string, + msg: string ) {} ``` @@ -461,10 +486,9 @@ NFT contracts should be implemented in a way to avoid extra gas fees for seriali ## Errata -* **2022-02-03**: updated `Token` struct field names. `id` was changed to `token_id` and `approvals` was changed to `approved_account_ids`. This is to be consistent with current implementations of the standard and the rust SDK docs. +- **2022-02-03**: updated `Token` struct field names. `id` was changed to `token_id` and `approvals` was changed to `approved_account_ids`. This is to be consistent with current implementations of the standard and the rust SDK docs. ## Copyright -[copyright]: #copyright Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). diff --git a/neps/nep-0181.md b/neps/nep-0181.md index cc1e990c4..716792500 100644 --- a/neps/nep-0181.md +++ b/neps/nep-0181.md @@ -87,7 +87,6 @@ At the time of this writing, the specialized collections in the `near-sdk` Rust [Implementation](https://github.com/near/near-sdk-rs/blob/master/near-contract-standards/src/non_fungible_token/enumeration/enumeration_impl.rs) ## Copyright -[copyright]: #copyright Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). diff --git a/neps/nep-0199.md b/neps/nep-0199.md index 0821fe357..2e1322d7a 100644 --- a/neps/nep-0199.md +++ b/neps/nep-0199.md @@ -20,15 +20,16 @@ Currently, NFTs on NEAR support the field `owner_id`, but lack flexibility for o Therefore, the core goal of this standard is to define a set of methods for financial contracts to call, without specifying how NFT contracts define the divide of payout mechanics, and a standard `Payout` response structure. - ## Specification This Payout extension standard adds two methods to NFT contracts: + - a view method: `nft_payout`, accepting a `token_id` and some `balance`, returning the `Payout` mapping for the given token. - a call method: `nft_transfer_payout`, accepting all the arguments of`nft_transfer`, plus a field for some `Balance` that calculates the `Payout`, calls `nft_transfer`, and returns the `Payout` mapping. Financial contracts MUST validate several invariants on the returned `Payout`: + 1. The returned `Payout` MUST be no longer than the given maximum length (`max_len_payout` parameter) if provided. Payouts of excessive length can become prohibitively gas-expensive. Financial contracts can specify the maximum length of payout the contract is willing to respect with the `max_len_payout` field on `nft_transfer_payout`. 2. The balances MUST add up to less than or equal to the `balance` argument in `nft_transfer_payout`. If the balance adds up to less than the `balance` argument, the financial contract MAY claim the remainder for itself. 3. The sum of the balances MUST NOT overflow. This is technically identical to 2, but financial contracts should be expected to handle this possibility. @@ -41,7 +42,8 @@ If the Payout contains any addresses that do not exist, the financial contract M Financial contracts MAY take a cut of the NFT sale price as commission, subtracting their cut from the total token sale price, and calling `nft_transfer_payout` with the remainder. ## Example Flow -``` + +```text ┌─────────────────────────────────────────────────┐ │Token Owner approves marketplace for token_id "0"│ ├─────────────────────────────────────────────────┘ @@ -127,6 +129,5 @@ In the future, the NFT contract itself may be able to place an NFT transfer is a - Version `2.0.0` contains the intended `approval_id` of `u64` instead of the stringified `U64` version. This was an oversight, but since the standard was live for a few months before noticing, the team thought it best to bump the major version. ## Copyright -[copyright]: #copyright -Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). \ No newline at end of file +Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). diff --git a/neps/nep-0245.md b/neps/nep-0245.md index 8713bcf99..82c11c5ae 100644 --- a/neps/nep-0245.md +++ b/neps/nep-0245.md @@ -52,6 +52,7 @@ To recap, we choose to create this standard, to improve interoperability, develo ## Specification **NOTES**: + - All amounts, balances and allowance are limited by `U128` (max value `2**128 - 1`). - Token standard uses JSON for serialization of arguments and results. - Amounts in arguments and results are serialized as Base-10 strings, e.g. `"100"`. This is done to avoid JSON limitation of max integer value of `2**53`. @@ -400,6 +401,7 @@ NEAR and third-party applications need to track Note that applications, including NEAR Wallet, could require implementing additional methods to display tokens correctly such as [`mt_metadata`][MT Metadata] and [`mt_tokens_for_owner`][MT Enumeration]. ### Events Interface + Multi Token Events MUST have `standard` set to `"nep245"`, standard version set to `"1.0.0"`, `event` value is one of `mt_mint`, `mt_burn`, `mt_transfer`, and `data` must be of one of the following relevant types: `MtMintLog[] | MtBurnLog[] | MtTransferLog[]`: @@ -553,6 +555,7 @@ EVENT_JSON:{ ## Further Event Methods Note that the example events covered above cover two different kinds of events: + 1. Events that are not specified in the MT Standard (`mt_mint`, `mt_burn`) 2. An event that is covered in the [Multi Token Core Standard](https://nomicon.io/Standards/Tokens/MultiToken/Core#mt-interface). (`mt_transfer`) @@ -569,7 +572,6 @@ Please feel free to open pull requests for extending the events standard detaile ## Copyright -[copyright]: #copyright Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). diff --git a/neps/nep-0297.md b/neps/nep-0297.md index e7ad4fde1..b4de6cd37 100644 --- a/neps/nep-0297.md +++ b/neps/nep-0297.md @@ -26,7 +26,6 @@ Events address this issue, providing other applications with the needed standard Initial discussion is [here](https://github.com/near/NEPs/issues/254). ## Rationale and alternatives -[rationale-and-alternatives]: #rationale-and-alternatives - Why is this design the best in the space of possible designs? - What other designs have been considered and what is the rationale for not choosing them? @@ -53,14 +52,15 @@ JSON string should have the following interface: // * `event`: type of the event, e.g. nft_mint // * `data`: associate event data. Strictly typed for each set {standard, version, event} inside corresponding NEP interface EventLogData { - standard: string, - version: string, - event: string, - data?: unknown, + standard: string; + version: string; + event: string; + data?: unknown; } ``` Thus, to emit an event, you only need to log a string following the rules above. Here is a bare-bones example using Rust SDK `near_sdk::log!` macro (security note: prefer using `serde_json` or alternatives to serialize the JSON string to avoid potential injections and corrupted events): + ```rust use near_sdk::log; @@ -72,7 +72,7 @@ log!( // ... ``` -#### Valid event logs: +#### Valid event logs ```js EVENT_JSON:{ @@ -93,9 +93,10 @@ EVENT_JSON:{ } ``` -#### Invalid event logs: +#### Invalid event logs + +- Two events in a single log entry (instead, call `log` for each individual event) -* Two events in a single log entry (instead, call `log` for each individual event) ```js EVENT_JSON:{ "standard": "nepXXX", @@ -108,11 +109,15 @@ EVENT_JSON:{ "event": "xyz_is_triggered" } ``` -* Invalid JSON data + +- Invalid JSON data + ```js EVENT_JSON:invalid json ``` -* Missing required fields `standard`, `version` or `event` + +- Missing required fields `standard`, `version` or `event` + ```js EVENT_JSON:{ "standard": "nepXXX", @@ -130,10 +135,10 @@ EVENT_JSON:{ [Non-Fungible Token Events Implementation](https://github.com/near/near-sdk-rs/blob/master/near-contract-standards/src/non_fungible_token/events.rs) ## Drawbacks + There is a known limitation of 16kb strings when capturing logs. This impacts the amount of events that can be processed. ## Copyright -[copyright]: #copyright -Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). \ No newline at end of file +Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). diff --git a/neps/nep-0330.md b/neps/nep-0330.md index 51cbd89d5..0d56e4018 100644 --- a/neps/nep-0330.md +++ b/neps/nep-0330.md @@ -32,6 +32,7 @@ There is a lot of information that can be held about a contract. Ultimately, we Successful implementations of this standard will introduce a new (`ContractSourceMetadata`) struct that will hold all the necessary information to be queried for. This struct will be kept on the contract level. The metadata will include three optional fields: + - `version`: a string that references the specific commit hash or version of the code that is currently deployed on-chain. This can be included regardless of whether or not the contract is open-sourced and can also be used for organizational purposes. - `link`: a string that references the link to the open-source code. This can be anything such as Github or a CID to somewhere on IPFS. - `standards`: a list of objects (see type definition below) that enumerates the NEPs supported by the contract. If this extension is supported, it is advised to also include NEP-330 version 1.1.0 in the list (`{standard: "nep330", version: "1.1.0"}`). @@ -169,6 +170,5 @@ The extension NEP-351 that added Contract Metadata to this NEP-330 was approved ## Copyright -[copyright]: #copyright Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). diff --git a/neps/nep-0364.md b/neps/nep-0364.md index 8cdc93797..3863cb38f 100644 --- a/neps/nep-0364.md +++ b/neps/nep-0364.md @@ -49,27 +49,27 @@ near call sitoula-test.testnet verify_ed25519 '{"signature_p1": [145,193,203,18, With `iterations = 130` **all these calls return ExecutionError**: `'Exceeded the maximum amount of gas allowed to burn per contract.'` With iterations = 50 these are the results: -``` +```text ed25519: tx id 6DcJYfkp9fGxDGtQLZ2m6PEDBwKHXpk7Lf5VgDYLi9vB (299 Tgas) ``` - Performance in wall clock time when you compile the signature validation library directly from rust to native. Here are the results on an AMD Ryzen 9 5900X 12-Core Processor machine: -``` +```text # 10k signature verifications ed25519: took 387ms ``` - Performance in wall clock time when you compile the library into wasm first and then use the single-pass compiler in Wasmer 1 to then compile to native. -``` +```text ed25519: took 9926ms ``` As an extra data point, when passing `--enable-simd` instead of `--singlepass` -``` +```text ed25519: took 3085ms ``` @@ -90,7 +90,7 @@ cargo run --bin benches --release Overall: the difference between the two versions (native vs wasi + singlepass is) -``` +```text ed25519: 25.64x slower ``` @@ -150,7 +150,7 @@ extern "C"{ /// /// # Errors /// -/// If the signature size is not equal to 64 bytes, or public key length is not equal to 32 bytes, contract execution is terminated with an error. +/// If the signature size is not equal to 64 bytes, or public key length is not equal to 32 bytes, contract execution is terminated with an error. fn ed25519_verify( sig_len: u64, sig_ptr: u64, @@ -164,10 +164,9 @@ extern "C"{ And a `rust-sdk` possible implementation could look like this: ```rs - pub fn ed25519_verify(sig: &ed25519::Signature, msg: &[u8], pub_key: &ed25519::Public) -> bool; - ``` + Once this NEP is approved and integrated, these functions will be available in the `near_sdk` crate in the `env` module. @@ -195,6 +194,4 @@ I currently do not envision any extension in this regard. ## Copyright -[copyright]: #copyright - Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). diff --git a/neps/nep-0366.md b/neps/nep-0366.md index b53da8d71..e419c9851 100644 --- a/neps/nep-0366.md +++ b/neps/nep-0366.md @@ -30,30 +30,33 @@ This design has severe limitations as it requires the user to deploy such contra ## Specification -* **User** (Sender) is the one who is going to send the `DelegateAction` to Receiver via Relayer. -* **Relayer** is the one who publishes the `DelegateAction` to the protocol. -* **User** and Relayer doesn't trust each other. +- **User** (Sender) is the one who is going to send the `DelegateAction` to Receiver via Relayer. +- **Relayer** is the one who publishes the `DelegateAction` to the protocol. +- **User** and Relayer doesn't trust each other. The main flow of the meta transaction will be as follows: - - User specifies `sender_id` (the user's account id), `receiver_id` (the receiver's account id) and other information (see `DelegateAction` format). - - User signs `DelegateAction` specifying the set of actions that they need to be executed. - - User forms `SignedDelegateAction` with the `DelegateAction` and the signature. - - User forms `DelegateActionMessage` with the `SignedDelegateAction`. - - User sends `DelegateActionMessage` data to the relayer. - - Relayer verifies actions specified in `DelegateAction`: the total cost and whether the user included the reward for the relayer. - - Relayer forms a `Transaction` with `receiver_id` equals to `delegate_action.sender_id` and `actions: [SignedDelegateAction { ... }]`. Signs it with its key. Note that such transactions can contain other actions toward user's account (for example calling a function). - - This transaction is processed normally. A `Receipt` is created with a copy of the actions in the transaction. - - When processing a `SignedDelegateAction`, a number of checks are done (see below), mainly a check to ensure that the `signature` matches the user account's key. - - When a `Receipt` with a valid `SignedDelegateAction` in actions arrives at the user's account, it gets executed. Execution means creation of a new Receipt with `receiver_id: AccountId` and `actions: Action` matching `receiver_id` and `actions` in the `DelegateAction`. - - The new `Receipt` looks like a normal receipt that could have originated from the user's account, with `predeccessor_id` equal to tbe user's account, `signer_id` equal to the relayer's account, `signer_public_key` equal to the relayer's public key. + +- User specifies `sender_id` (the user's account id), `receiver_id` (the receiver's account id) and other information (see `DelegateAction` format). +- User signs `DelegateAction` specifying the set of actions that they need to be executed. +- User forms `SignedDelegateAction` with the `DelegateAction` and the signature. +- User forms `DelegateActionMessage` with the `SignedDelegateAction`. +- User sends `DelegateActionMessage` data to the relayer. +- Relayer verifies actions specified in `DelegateAction`: the total cost and whether the user included the reward for the relayer. +- Relayer forms a `Transaction` with `receiver_id` equals to `delegate_action.sender_id` and `actions: [SignedDelegateAction { ... }]`. Signs it with its key. Note that such transactions can contain other actions toward user's account (for example calling a function). +- This transaction is processed normally. A `Receipt` is created with a copy of the actions in the transaction. +- When processing a `SignedDelegateAction`, a number of checks are done (see below), mainly a check to ensure that the `signature` matches the user account's key. +- When a `Receipt` with a valid `SignedDelegateAction` in actions arrives at the user's account, it gets executed. Execution means creation of a new Receipt with `receiver_id: AccountId` and `actions: Action` matching `receiver_id` and `actions` in the `DelegateAction`. +- The new `Receipt` looks like a normal receipt that could have originated from the user's account, with `predeccessor_id` equal to tbe user's account, `signer_id` equal to the relayer's account, `signer_public_key` equal to the relayer's public key. ## Diagram -![](assets/nep-0366/NEP-DelegateAction.png) - ## Limitations - * If User account exist, then deposit and gas are refunded as usual: gas is refuned to Relayer, deposit is refunded to User. - * If User account doesn't exist then gas is refunded to Relayer, deposit is burnt. - * `DelegateAction` actions mustn't contain another `DelegateAction` (`DelegateAction` can't contain the nested ones). +![Delegate Action Diagram](assets/nep-0366/NEP-DelegateAction.png) + +## Limitations + +- If User account exist, then deposit and gas are refunded as usual: gas is refuned to Relayer, deposit is refunded to User. +- If User account doesn't exist then gas is refunded to Relayer, deposit is burnt. +- `DelegateAction` actions mustn't contain another `DelegateAction` (`DelegateAction` can't contain the nested ones). ### DelegateAction @@ -85,9 +88,10 @@ pub struct SignedDelegateAction { } ``` - Supporting batches of `actions` means `DelegateAction` can be used to initiate complex steps like creating new accounts, transferring funds, deploying contracts, and executing an initialization function all within the same transaction. +Supporting batches of `actions` means `DelegateAction` can be used to initiate complex steps like creating new accounts, transferring funds, deploying contracts, and executing an initialization function all within the same transaction. + +##### Validation -***Validation***: 1. Validate `DelegateAction` doesn't contain a nested `DelegateAction` in actions. 2. To ensure that a `DelegateAction` is correct, on receipt the following signature verification is performed: `verify_signature(hash(delegate_action), delegate_action.public_key, signature)`. 3. Verify `transaction.receiver_id` matches `delegate_action.sender_id`. @@ -96,6 +100,7 @@ pub struct SignedDelegateAction { 6. Verify `delegate_action.nonce > sender.access_key.nonce`. A `message` is formed in the following format: + ```rust struct DelegateActionMessage { signed_delegate_action: SignedDelegateAction @@ -103,75 +108,87 @@ struct DelegateActionMessage { ``` The next set of security concerns are addressed by this format: - - `sender_id` is included to ensure that the relayer sets the correct `transaction.receiver_id`. - - `max_block_height` is included to ensure that the `DelegateAction` isn't expired. - - `nonce` is included to ensure that the `DelegateAction` can't be replayed again. - - `public_key` and `sender_id` are needed to ensure that on the right account, work across rotating keys and fetch the correct `nonce`. + +- `sender_id` is included to ensure that the relayer sets the correct `transaction.receiver_id`. +- `max_block_height` is included to ensure that the `DelegateAction` isn't expired. +- `nonce` is included to ensure that the `DelegateAction` can't be replayed again. +- `public_key` and `sender_id` are needed to ensure that on the right account, work across rotating keys and fetch the correct `nonce`. The permissions are verified based on the variant of `public_key`: - - `AccessKeyPermission::FullAccess`, all actions are allowed. - - `AccessKeyPermission::FunctionCall`, only a single `FunctionCall` action is allowed in `actions`. - - `DelegateAction.receiver_id` must match to the `account[public_key].receiver_id` - - `DelegateAction.actions[0].method_name` must be in the `account[public_key].method_names` -***Outcomes***: +- `AccessKeyPermission::FullAccess`, all actions are allowed. +- `AccessKeyPermission::FunctionCall`, only a single `FunctionCall` action is allowed in `actions`. + - `DelegateAction.receiver_id` must match to the `account[public_key].receiver_id` + - `DelegateAction.actions[0].method_name` must be in the `account[public_key].method_names` + +##### Outcomes + - If the `signature` matches the receiver's account's `public_key`, a new receipt is created from this account with a set of `ActionReceipt { receiver_id, action }` for each action in `actions`. +##### Recommendations -***Recommendations*** - Because the User doesn't trust the Relayer, the User should verify whether the Relayer has submitted the `DelegateAction` and the execution result. -#### Errors +### Errors - If the Sender's account doesn't exist + ```rust /// Happens when TX receiver_id doesn't exist AccountDoesNotExist ``` - If the `signature` does not match the data and the `public_key` of the given key, then the following error will be returned + ```rust /// Signature does not match the provided actions and given signer public key. DelegateActionInvalidSignature ``` - If the `sender_id` doesn't match the `tx.receiver_id` + ```rust /// Receiver of the transaction doesn't match Sender of the delegate action DelegateActionSenderDoesNotMatchReceiver ``` - If the current block is equal or greater than `max_block_height` + ```rust /// Delegate action has expired DelegateActionExpired ``` - If the `public_key` does not exist for Sender account + ```rust /// The given public key doesn't exist for Sender account DelegateActionAccessKeyError ``` - If the `nonce` does match the `public_key` for the `sender_id` + ```rust /// Nonce must be greater sender[public_key].nonce DelegateActionInvalidNonce ``` - If `nonce` is too large + ```rust /// DelegateAction nonce is larger than the upper bound given by the block height (block_height * 1e6) DelegateActionNonceTooLarge ``` - If the list of delegated actions contains another `DelegateAction` + ```rust /// DelegateAction actions contain another DelegateAction DelegateActionCantContainNestedOne ``` - If the list of Transaction actions contains several `DelegateAction` + ```rust /// There should be the only one DelegateAction DelegateActionMustBeOnlyOne @@ -183,21 +200,20 @@ See the [DelegateAction specification](/specs/RuntimeSpec/Actions.md#DelegateAct Delegate actions do not override `signer_public_key`, leaving that to the original signer that initiated the transaction (e.g. the relayer in the meta transaction case). Although it is possible to override the `signer_public_key` in the context with one from the `DelegateAction`, there is no clear value in that. -See the ***Validation*** section in [DelegateAction specification](/specs/RuntimeSpec/Actions.md#DelegateAction) for security considerations around what the user signs and the validation of actions with different permissions. +See the **_Validation_** section in [DelegateAction specification](/specs/RuntimeSpec/Actions.md#DelegateAction) for security considerations around what the user signs and the validation of actions with different permissions. ## Drawbacks -* Increases complexity of NEAR's transactional model. -* Meta transactions take an extra block to execute, as they first need to be included by the originating account, then routed to the delegate account, and only after that to the real destination. -* User can't call functions from different contracts in same `DelegateAction`. This is because `DelegateAction` has only one receiver for all inner actions. -* The Relayer must verify most of the parameters before submitting `DelegateAction`, making sure that one of the function calls is the reward action. Either way, this is a risk for Relayer in general. -* User must not trust Relayer’s response and should check execution errors in Blockchain. +- Increases complexity of NEAR's transactional model. +- Meta transactions take an extra block to execute, as they first need to be included by the originating account, then routed to the delegate account, and only after that to the real destination. +- User can't call functions from different contracts in same `DelegateAction`. This is because `DelegateAction` has only one receiver for all inner actions. +- The Relayer must verify most of the parameters before submitting `DelegateAction`, making sure that one of the function calls is the reward action. Either way, this is a risk for Relayer in general. +- User must not trust Relayer’s response and should check execution errors in Blockchain. ## Future possibilities Supporting ZK proofs instead of just signatures can allow for anonymous transactions, which pay fees to relayers anonymously. ## Copyright -[copyright]: #copyright Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). diff --git a/neps/nep-0399.md b/neps/nep-0399.md index 725be4a50..77256b0e8 100644 --- a/neps/nep-0399.md +++ b/neps/nep-0399.md @@ -19,17 +19,17 @@ allows to make storage reads faster, make storage fees more predictable and pote Currently, the blockchain state is stored in our storage only in the format of persistent merkelized tries. Although it is needed to compute state roots and prove the validity of states, reading from it requires a -traversal from the trie root to the leaf node that contains the key value pair, which could mean up to -2 * key_length disk accesses in the worst case. +traversal from the trie root to the leaf node that contains the key value pair, which could mean up to +2 \* key_length disk accesses in the worst case. -In addition, we charge receipts by the number of trie nodes they touched (TTN cost). Note that the number -of touched trie node does not always equal to the key length, it depends on the internal trie structure. +In addition, we charge receipts by the number of trie nodes they touched (TTN cost). Note that the number +of touched trie node does not always equal to the key length, it depends on the internal trie structure. Based on some feedback from contract developers collected in the past, they are interested in predictable fees, but TTN costs are annoying to predict and can lead to unexpected excess of the gas limit. They are also a burden for NEAR Protocol client implementations, i.e. nearcore, as exact TTN number must be computed deterministically by all clients. This prevents storage optimizations that use other strategies than nearcore uses today. -With Flat Storage, number of disk reads is reduced from worst-case 2 * key_length to exactly 2, storage read gas +With Flat Storage, number of disk reads is reduced from worst-case 2 \* key_length to exactly 2, storage read gas fees are simplified by getting rid of TTN cost, and potentially can be further reduced because fewer disk reads are needed. @@ -41,18 +41,18 @@ A: Space of possible designs is quite big here, let's show some meaningful examp The most straightforward one is just to increase TTN, or align it with biggest possible value, or alternatively increase the base fees for storage reads and writes. However, technically the biggest TTN could be 4096 as of today. And we tend -to strongly avoid increasing fees, because it may break existing contract calls, not even mentioning that it would greatly +to strongly avoid increasing fees, because it may break existing contract calls, not even mentioning that it would greatly reduce capacity of NEAR blocks, because for current mainnet usecases depth is usually below 20. We also consider changing tree type from Trie to AVL, B-tree, etc. to make number of traversed nodes more stable and predictable. But we approached AVL idea, and implementation turned out to be tricky, so we didn't go -much further than POC here: https://github.com/near/nearcore/discussions/4815. Also for most key-value pairs +much further than POC here: https://github.com/near/nearcore/discussions/4815. Also for most key-value pairs tree depth will actually increase - for example, if you have 1M keys, depth is always 20, and it would cause increasing fees as well. Size of intermediate node also increases, because we have to need to store a key there to decide whether we should go to the left or right child. Separate idea is to get rid of global state root completely: https://github.com/near/NEPs/discussions/425. Instead, -we could track the latest account state in the block where it was changed. But after closer look, it brings us to +we could track the latest account state in the block where it was changed. But after closer look, it brings us to similar questions - if some key was untouched for a long time, it becomes harder to find exact block to find latest value for it, and we need some tree-shaped structure again. Because ideas like that could be also extremely invasive, we stopped considering them at this point. @@ -66,67 +66,69 @@ Q: What other designs have been considered and what is the rationale for not cho A: There were several ideas on Flat Storage implementation. One of questions is whether we need global flat storage for all shards or separate flat storages. Due to how sharding works, we have make flat storages separate, because in -the future node may have to catchup new shard while already tracking old shards, and flat storage heads (see +the future node may have to catchup new shard while already tracking old shards, and flat storage heads (see Specification) must be different for these shards. Flat storage deltas are another tricky part of design, but we cannot avoid them, because at certain points of time different nodes can disagree what is the current chain head, and they have to support reads for some subset of latest blocks with decent speed. We can't really fallback to Trie in such cases because storage reads for it are much slower. -Another implementation detail is where to put flat storage head. The planned implementation doesn't rely on that +Another implementation detail is where to put flat storage head. The planned implementation doesn't rely on that significantly and can be changed, but for MVP we assume flat storage head = chain final head as a simplest solution. Q: What is the impact of not doing this? -A: Storage reads will remain inefficiently implemented and cost more than they should, and the gas fees will remain +A: Storage reads will remain inefficiently implemented and cost more than they should, and the gas fees will remain difficult for the contract developers to predict. ## Specification -The key idea of Flat Storage is to store a direct mapping from trie keys to values in the DB. -Here the values of this mapping can be either the value corresponding to the trie key itself, -or the value ref, a hash that points to the address of the value. If the value itself is stored, -only one disk read is needed to look up a value from flat storage, otherwise two disk reads are needed if the value -ref is stored. We will discuss more in the following section for whether we use values or value refs. -For the purpose of high level discussion, it suffices to say that with Flat Storage, +The key idea of Flat Storage is to store a direct mapping from trie keys to values in the DB. +Here the values of this mapping can be either the value corresponding to the trie key itself, +or the value ref, a hash that points to the address of the value. If the value itself is stored, +only one disk read is needed to look up a value from flat storage, otherwise two disk reads are needed if the value +ref is stored. We will discuss more in the following section for whether we use values or value refs. +For the purpose of high level discussion, it suffices to say that with Flat Storage, at most two disk reads are needed to perform a storage read. -The simple design above won't work because there could be forks in the chain. In the following case, FlatStorage +The simple design above won't work because there could be forks in the chain. In the following case, FlatStorage must support key value lookups for states of the blocks on both forks. -``` + +```text / Block B1 - Block B2 - ... -block A +block A \ Block C1 - Block C2 - ... ``` The handling of forks will be the main consideration of the following design. More specifically, the design should satisfy the following requirements, -1) It should support concurrent block processing. Blocks on different forks are processed + +1. It should support concurrent block processing. Blocks on different forks are processed concurrently in the nearcore Client code, the struct which responsibility includes receiving blocks from network, scheduling applying chunks and writing results of that to disk. Flat storage API must be aligned with that. -2) In case of long forks, block processing time should not be too much longer than the average case. - We don’t want this case to be exploitable. It is acceptable that block processing time is 200ms longer, - which may slow down block production, but probably won’t cause missing blocks and chunks. +2. In case of long forks, block processing time should not be too much longer than the average case. + We don’t want this case to be exploitable. It is acceptable that block processing time is 200ms longer, + which may slow down block production, but probably won’t cause missing blocks and chunks. 10s delays are not acceptable and may lead to more forks and instability in the network. -3) The design must be able to decrease storage access cost in all cases, - since we are going to change the storage read fees based on flat storage. - We can't conditionally enable Flat Storage for some blocks and disable it for other, because - the fees we charge must be consistent. - -The mapping of key value pairs FlatStorage stored on disk matches the state at some block. -We call this block the head of flat storage, or the flat head. During block processing, -the flat head is set to the last final block. The Doomslug consensus algorithm -guarantees that if a block is final, all future final blocks must be descendants of this block. -In other words, any block that is not built on top of the last final block can be discarded because they -will never be finalized. As a result, if we use the last final block as the flat head, any block +3. The design must be able to decrease storage access cost in all cases, + since we are going to change the storage read fees based on flat storage. + We can't conditionally enable Flat Storage for some blocks and disable it for other, because + the fees we charge must be consistent. + +The mapping of key value pairs FlatStorage stored on disk matches the state at some block. +We call this block the head of flat storage, or the flat head. During block processing, +the flat head is set to the last final block. The Doomslug consensus algorithm +guarantees that if a block is final, all future final blocks must be descendants of this block. +In other words, any block that is not built on top of the last final block can be discarded because they +will never be finalized. As a result, if we use the last final block as the flat head, any block FlatStorage needs to process is a descendant of the flat head. -To support key value lookups for other blocks that are not the flat head, FlatStorage will +To support key value lookups for other blocks that are not the flat head, FlatStorage will store key value changes(deltas) per block for these blocks. -We call these deltas FlatStorageDelta (FSD). Let’s say the flat storage head is at block h, -and we are applying transactions based on block h’. Since h is the last final block, +We call these deltas FlatStorageDelta (FSD). Let’s say the flat storage head is at block h, +and we are applying transactions based on block h’. Since h is the last final block, h is an ancestor of h'. To access the state at block h', we need FSDs of all blocks between h and h'. -Note that all these FSDs must be stored in memory, otherwise, the access of FSDs will trigger +Note that all these FSDs must be stored in memory, otherwise, the access of FSDs will trigger more disk reads and we will have to set storage key read fee higher. ### FSD size estimation @@ -135,10 +137,10 @@ We prefer to store deltas in memory, because memory read is much faster than dis access requires increasing storage fees, which is not desirable. To reduce delta size, we will store hashes of trie keys instead of keys, because deltas are read-only. Now let's carefully estimate FSD size. -We can do so using protocol fees as of today. Assume that flat state stores a mapping from keys to value refs. +We can do so using protocol fees as of today. Assume that flat state stores a mapping from keys to value refs. Maximal key length is ~2 KiB which is the limit of contract data key size. During wasm execution, we pay -`wasm_storage_write_base` = 64 Ggas per call. Entry size is 68 B for key hash and value ref. -Then the total size of keys changed in a block is at most +`wasm_storage_write_base` = 64 Ggas per call. Entry size is 68 B for key hash and value ref. +Then the total size of keys changed in a block is at most `chunk_gas_limit / gas_per_entry * entry_size * num_shards = (1300 Tgas / 64 Ggas) * 68 B * 4 ~= 5.5 MiB`. Assuming that we can increase RAM requirements by 1 GiB, we can afford to store deltas for 100-200 blocks @@ -146,11 +148,11 @@ simultaneously. Note that if we store a value instead of value ref, size of FSDs can potentially be much larger. Because value limit is 4 MiB, we can’t apply previous argument about base cost. -Since `wasm_storage_write_value_byte` = 31 Mgas, values contribution to FSD size can be estimated as -`(1300 Tgas / storage_write_value_byte * num_shards)`, or ~167 MiB. Same estimation for trie keys gives 54 MiB. -The advantage of storing values instead of value refs is that it saves one disk read if the key has been -modified in the recent blocks. It may be beneficial if we get many transactions or receipts touching the same -trie keys in consecutive blocks, but it is hard to estimate the value of such benefits without more data. +Since `wasm_storage_write_value_byte` = 31 Mgas, values contribution to FSD size can be estimated as +`(1300 Tgas / storage_write_value_byte * num_shards)`, or ~167 MiB. Same estimation for trie keys gives 54 MiB. +The advantage of storing values instead of value refs is that it saves one disk read if the key has been +modified in the recent blocks. It may be beneficial if we get many transactions or receipts touching the same +trie keys in consecutive blocks, but it is hard to estimate the value of such benefits without more data. We may store only short values ("inlining"), but this idea is orthogonal and can be applied separately. ### Protocol changes @@ -160,80 +162,84 @@ Flat Storage itself doesn't change protocol. We only change impacted storage cos #### Storage Reads Latest proposal for shipping storage reads is [here](https://github.com/near/nearcore/issues/8006#issuecomment-1473718509). -It solves several issues with costs, but the major impact of flat storage is that essentially for reads +It solves several issues with costs, but the major impact of flat storage is that essentially for reads `wasm_touching_trie_node` and `wasm_read_cached_trie_node` are reduced to 0. Reason is that before we had to cover costs -of reading nodes from memory or disk, and with flat storage we make only 2 DB reads. +of reading nodes from memory or disk, and with flat storage we make only 2 DB reads. Latest up-to-date gas and compute costs can be found in nearcore repo. #### Storage Writes Storage writes are charged similarly to reads and include TTN as well, because updating the leaf trie -node which stores the value to the trie key requires updating all trie nodes on the path leading to the leaf node. -All writes are committed at once in one db transaction at the end of block processing, outside of runtime after -all receipts in a block are executed. However, at the time of execution, runtime needs to calculate the cost, +node which stores the value to the trie key requires updating all trie nodes on the path leading to the leaf node. +All writes are committed at once in one db transaction at the end of block processing, outside of runtime after +all receipts in a block are executed. However, at the time of execution, runtime needs to calculate the cost, which means it needs to know how many trie nodes the write affects, so runtime will issue a read for every write to calculate the TTN cost for the write. Such reads cannot be replaced by a read in FlatStorage because FlatStorage does -not provide the path to the trie node. +not provide the path to the trie node. + +There are multiple proposals on how storage writes can work with FlatStorage. -There are multiple proposals on how storage writes can work with FlatStorage. -- Keep it the same. The cost of writes remain the same. Note that this can increase the cost for writes in +- Keep it the same. The cost of writes remain the same. Note that this can increase the cost for writes in some cases, for example, if a contract first read from a key and then writes to the same key in the same chunk. - Without FlatStorage, the key will be cached in the chunk cache after the read, so the write will cost less. - With FlatStorage, the read will go through FlatStorage, the write will not find the key in the chunk cache and + Without FlatStorage, the key will be cached in the chunk cache after the read, so the write will cost less. + With FlatStorage, the read will go through FlatStorage, the write will not find the key in the chunk cache and it will cost more. - Remove the TTN cost from storage write fees. Currently, there are two ideas in this direction. - - Charge based on maximum depth of a contract’s state, instead of per-touch-trie node. - - Charge based on key length only. - - Both of the above ideas would allow us to get rid of trie traversal ("reads-for-writes") from the critical path of - block execution. However, + - Charge based on maximum depth of a contract’s state, instead of per-touch-trie node. + - Charge based on key length only. + Both of the above ideas would allow us to get rid of trie traversal ("reads-for-writes") from the critical path of + block execution. However, it is unclear at this point what the new cost would look like and whether further optimizations are needed - to bring down the cost for writes in the new cost model. + to bring down the cost for writes in the new cost model. See https://gov.near.org/t/storage-write-optimizations/30083 for more details. -While storage writes are not fully implemented yet, we may increase parameter compute cost for storage writes implemented -in https://github.com/near/NEPs/pull/455 as an intermediate solution. +While storage writes are not fully implemented yet, we may increase parameter compute cost for storage writes implemented +in https://github.com/near/NEPs/pull/455 as an intermediate solution. ### Migration Plan + There are two main questions regarding to how to enable FlatStorage. -1) Whether there should be database migration. The main challenge of enabling FlatStorage will be to build the flat state + +1. Whether there should be database migration. The main challenge of enabling FlatStorage will be to build the flat state column, which requires iterating the entire state. Estimations showed that it takes 10 hours to build - flat state for archival nodes and 5 hours for rpc and validator nodes in 8 threads. The main concern is that if + flat state for archival nodes and 5 hours for rpc and validator nodes in 8 threads. The main concern is that if it takes too long for archival node to migrate, - they may have a hard time catching up later since the block processing speed of archival nodes is not very fast. + they may have a hard time catching up later since the block processing speed of archival nodes is not very fast. + + Alternatively, we can build the flat state in a background process while the node is running. This provides a better + experience for both archival and validator nodes since the migration process is transient to them. It would require + more implementation effort from our side. - Alternatively, we can build the flat state in a background process while the node is running. This provides a better - experience for both archival and validator nodes since the migration process is transient to them. It would require - more implementation effort from our side. - We currently proceed with background migration using 8 threads. -2) Whether there should be a protocol upgrade. The enabling of FlatStorage itself does not require a protocol upgrade, since -it is an internal storage implementation that doesn't change protocol level. However, a protocol upgrade is needed + +2. Whether there should be a protocol upgrade. The enabling of FlatStorage itself does not require a protocol upgrade, since + it is an internal storage implementation that doesn't change protocol level. However, a protocol upgrade is needed if we want to adjust fees based on the storage performance with FlatStorage. These two changes can happen in one release, - or we can be release them separately. We propose that the enabling of FlatStorage and the protocol upgrade - to adjust fees should happen in separate release to reduce the risk. The period between the two releases can be - used to test the stability and performance of FlatStorage. Because it is not a protocol change, it is easy to roll back + or we can be release them separately. We propose that the enabling of FlatStorage and the protocol upgrade + to adjust fees should happen in separate release to reduce the risk. The period between the two releases can be + used to test the stability and performance of FlatStorage. Because it is not a protocol change, it is easy to roll back the change in case any issue arises. -## Reference Implementation +## Reference Implementation + FlatStorage will implement the following structs. `FlatStorageChunkView`: interface for getting value or value reference from flat storage for specific shard, block hash and trie key. In current logic we plan to make it part of `Trie`, -and all trie reads will be directed to this object. Though we could work with chunk hashes, we don't, +and all trie reads will be directed to this object. Though we could work with chunk hashes, we don't, because block hashes are easier to navigate. `FlatStorage`: API for interacting with flat storage for fixed shard, including updating head, - adding new delta and creating `FlatStorageChunkView`s. - for example, all block deltas that are stored in flat storage and the flat - storage head. `FlatStorageChunkView` can access `FlatStorage` to get the list of - deltas it needs to apply on top of state of current flat head in order to - compute state of a target block. +adding new delta and creating `FlatStorageChunkView`s. +for example, all block deltas that are stored in flat storage and the flat +storage head. `FlatStorageChunkView` can access `FlatStorage` to get the list of +deltas it needs to apply on top of state of current flat head in order to +compute state of a target block. `FlatStorageManager`: owns flat storages for all shards, being stored in `NightshadeRuntime`, accepts - updates from `Chain` side, caused by successful processing of chunk or block. +updates from `Chain` side, caused by successful processing of chunk or block. `FlatStorageCreator`: handles flat storage structs creation or initiates background creation (aka migration process) if flat storage data is not presend on DB yet. @@ -241,37 +247,42 @@ process) if flat storage data is not presend on DB yet. `FlatStateDelta`: a HashMap that contains state changes introduced in a chunk. They can be applied on top the state at flat storage head to compute state at another block. -The reason for having separate flat storages that there are two modes of block processing, -normal block processing and block catchups. +The reason for having separate flat storages that there are two modes of block processing, +normal block processing and block catchups. Since they are performed on different ranges of blocks, flat storage need to be able to support different range of blocks on different shards. Therefore, we separate the flat storage objects used for different shards. ### DB columns + `DBCol::FlatState` stores a mapping from trie keys to the value corresponding to the trie keys, based on the state of the block at flat storage head. -- *Rows*: trie key (`Vec`) -- *Column type*: `ValueRef` + +- _Rows_: trie key (`Vec`) +- _Column type_: `ValueRef` `DBCol::FlatStateDeltas` stores all existing FSDs as mapping from `(shard_id, block_hash, trie_key)` to the `ValueRef`. To read the whole delta, we read all values for given key prefix. This delta stores all state changes introduced in the given shard of the given block. -- *Rows*: `{ shard_id, block_hash, trie_key }` -- *Column type*: `ValueRef` + +- _Rows_: `{ shard_id, block_hash, trie_key }` +- _Column type_: `ValueRef` Note that `FlatStateDelta`s needed are stored in memory, so during block processing this column won't be used - at all. This column is only used to load deltas into memory at `FlatStorage` initialization time when node starts. +at all. This column is only used to load deltas into memory at `FlatStorage` initialization time when node starts. `DBCol::FlatStateMetadata` stores miscellaneous data about flat storage layout, including current flat storage head, current creation status and info about deltas existence. We don't specify exact format here because it is under discussion and can be tweaked until release. Similarly, flat head is also stored in `FlatStorage` in memory, so this column is only used to initialize - `FlatStorage` when node starts. +`FlatStorage` when node starts. ### `FlatStateDelta` + `FlatStateDelta` stores a mapping from trie keys to value refs. If the value is `None`, it means the key is deleted in the block. + ```rust pub struct FlatStateDelta(HashMap, Option>); ``` @@ -279,13 +290,16 @@ pub struct FlatStateDelta(HashMap, Option>); ```rust pub fn from_state_changes(changes: &[RawStateChangesWithTrieKey]) -> FlatStateDelta ``` -Converts raw state changes to flat state delta. The raw state changes will be returned as part of the result of + +Converts raw state changes to flat state delta. The raw state changes will be returned as part of the result of `Runtime::apply_transactions`. They will be converted to `FlatStateDelta` to be added to `FlatStorage` during `Chain::postprocess_block` or `Chain::catch_up_postprocess`. ### `FlatStorageChunkView` -`FlatStorageChunkView` will be created for a shard `shard_id` and a block `block_hash`, and it can perform + +`FlatStorageChunkView` will be created for a shard `shard_id` and a block `block_hash`, and it can perform key value lookup for the state of shard `shard_id` after block `block_hash` is applied. + ```rust pub struct FlatStorageChunkView { /// Used to access flat state stored at the head of flat storage. @@ -299,21 +313,23 @@ flat_storage: FlatStorage, ``` `FlatStorageChunkView` will provide the following interface. + ```rust pub fn get_ref( &self, key: &[u8], ) -> Result, StorageError> ``` + Returns the value or value reference corresponding to the given `key` for the state that this `FlatStorageChunkView` object represents, i.e., the state that after block `self.block_hash` is applied. ### `FlatStorageManager` -`FlatStorageManager` will be stored as part of `ShardTries` and `NightshadeRuntime`. Similar to how `ShardTries` is used to +`FlatStorageManager` will be stored as part of `ShardTries` and `NightshadeRuntime`. Similar to how `ShardTries` is used to construct new `Trie` objects given a state root and a shard id, `FlatStorageManager` is used to construct -a new `FlatStorageChunkView` object given a block hash and a shard id. +a new `FlatStorageChunkView` object given a block hash and a shard id. ```rust pub fn new_flat_storage_chunk_view( @@ -322,6 +338,7 @@ pub fn new_flat_storage_chunk_view( block_hash: Option, ) -> FlatStorageChunkView ``` + Creates a new `FlatStorageChunkView` to be used for performing key value lookups on the state of shard `shard_id` after block `block_hash` is applied. @@ -331,8 +348,9 @@ pub fn get_flat_storage( shard_id: ShardId, ) -> Result ``` -Returns the `FlatStorage` for the shard `shard_id`. This function is needed because even though -`FlatStorage` is part of `NightshadeRuntime`, `Chain` also needs access to `FlatStorage` to update flat head. + +Returns the `FlatStorage` for the shard `shard_id`. This function is needed because even though +`FlatStorage` is part of `NightshadeRuntime`, `Chain` also needs access to `FlatStorage` to update flat head. We will also create a function with the same in `NightshadeRuntime` that calls this function to provide `Chain` to access to `FlatStorage`. @@ -345,10 +363,11 @@ pub fn remove_flat_storage( Removes flat storage for shard if we stopped tracking it. -###`FlatStorage` -`FlatStorage` is created per shard. It provides information to which blocks the flat storage +### `FlatStorage` + +`FlatStorage` is created per shard. It provides information to which blocks the flat storage on the given shard currently supports and what block deltas need to be applied on top the stored -flat state on disk to get the state of the target block. +flat state on disk to get the state of the target block. ```rust fn get_blocks_to_head( @@ -356,7 +375,8 @@ fn get_blocks_to_head( target_block_hash: &CryptoHash, ) -> Result, FlatStorageError> ``` -Returns the list of deltas between blocks `target_block_hash` (inclusive) and flat head (exclusive), + +Returns the list of deltas between blocks `target_block_hash` (inclusive) and flat head (exclusive), Returns an error if `target_block_hash` is not a direct descendent of the current flat head. This function will be used in `FlatStorageChunkView::get_ref`. Note that we can't call it once and store during applying chunk, because in parallel to that some block can be processed and flat head can be updated. @@ -364,9 +384,10 @@ chunk, because in parallel to that some block can be processed and flat head can ```rust fn update_flat_head(&self, new_head: &CryptoHash) -> Result<(), FlatStorageError> ``` + Updates the head of the flat storage, including updating the flat head in memory and on disk, -update the flat state on disk to reflect the state at the new head, and gc the `FlatStateDelta`s that -are no longer needed from memory and from disk. +update the flat state on disk to reflect the state at the new head, and gc the `FlatStateDelta`s that +are no longer needed from memory and from disk. ```rust fn add_block( @@ -391,7 +412,8 @@ Returns `ValueRef` from flat storage state on top of `block_hash`. Returns `None block is not supported. ### Thread Safety -We should note that the implementation of `FlatStorage` must be thread safe because it can + +We should note that the implementation of `FlatStorage` must be thread safe because it can be concurrently accessed by multiple threads. A node can process multiple blocks at the same time if they are on different forks, and chunks from these blocks can trigger storage reads in parallel. Therefore, `FlatStorage` will be guarded by a `RwLock` so its access can be shared safely: @@ -424,19 +446,19 @@ for block processing. For storage write in general Flat Storage is even a net im necessity to traverse changed nodes during write execution ("reads-for-writes"), and we can apply optimizations there (see "Storage Writes" section). -Implementing FlatStorage will require a lot of engineering effort and introduce code that will make the codebase more +Implementing FlatStorage will require a lot of engineering effort and introduce code that will make the codebase more complicated. In particular, we had to extend `RuntimeAdapter` API with flat storage-related method after thorough considerations. We are confident that FlatStorage will bring a lot of performance benefit, but we can only measure the exact -improvement after the implementation. We may find that the benefit FlatStorage brings is not +improvement after the implementation. We may find that the benefit FlatStorage brings is not worth the effort, but it is very unlikely. It will make the state rollback harder in the future when we enable challenges in phase 2 of sharding. -When a challenge is accepted and the state needs to be rolled back to a previous block, the entire flat state needs to -be rebuilt, which could take a long time. Alternatively, we could postpone garbage collection of deltas and add support +When a challenge is accepted and the state needs to be rolled back to a previous block, the entire flat state needs to +be rebuilt, which could take a long time. Alternatively, we could postpone garbage collection of deltas and add support of applying them backwards. Speaking of new sharding phases, once nodes are no longer tracking all shards, Flat Storage must have support for adding -or removing state for some specific shard. Adding new shard is a tricky but natural extension of catchup process. Our +or removing state for some specific shard. Adding new shard is a tricky but natural extension of catchup process. Our current approach for removal is to iterate over all entries in `DBCol::FlatState` and find out for each trie key to which shard it belongs to. We would be happy to assume that each shard is represented by set of contiguous ranges in `DBCol::FlatState` and make removals simpler, but this is still under discussion. @@ -462,21 +484,20 @@ The NEP was approved by Protocol Working Group members on March 16, 2023 ([meeti #### Benefits -* The proposal makes serving reads more efficient; making the NEAR protocol cheaper to use and increasing the capacity of the network; -* The proposal makes estimating gas costs for a transaction easier as the fees for reading are no longer a function of the trie structure whose shape the smart contract developer does not know ahead of time and can continuously change. -* The proposal should open doors to enabling future efficiency gains in the protocol and further simplifying gas fee estimations. -* 'Secondary' index over the state data - which would allow further optimisations in the future. +- The proposal makes serving reads more efficient; making the NEAR protocol cheaper to use and increasing the capacity of the network; +- The proposal makes estimating gas costs for a transaction easier as the fees for reading are no longer a function of the trie structure whose shape the smart contract developer does not know ahead of time and can continuously change. +- The proposal should open doors to enabling future efficiency gains in the protocol and further simplifying gas fee estimations. +- 'Secondary' index over the state data - which would allow further optimisations in the future. #### Concerns -| # | Concern | Resolution | Status | -| - | - | - | - | -| 1 | The cache requires additional database storage | There is an upper bound on how much additional storage is needed. The costs for the additional disk storage should be negligible | Not an issue | -| 2 | Additional implementation complexity | Given the benefits of the proposal, I believe the complexity is justified | not an issue | -| 3 | Additional memory requirement | Most node operators are already operating over-provisioned machines which can handle the additional memory requirement. The minimum requirements should be raised but it appears that minimum requirements are already not enough to operate a node | This is a concern but it is not specific to this project | -| 4 | Slowing down the read-update-write workload | This is common pattern in smart contracts so indeed a concern. However, there are future plans on how to address this by serving writes from the flat storage as well which will also reduce the fees of serving writes and make further improvements to the NEAR protocol | This is a concern but hopefully will be addressed in future iterations of the project | +| # | Concern | Resolution | Status | +| --- | ---------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------- | +| 1 | The cache requires additional database storage | There is an upper bound on how much additional storage is needed. The costs for the additional disk storage should be negligible | Not an issue | +| 2 | Additional implementation complexity | Given the benefits of the proposal, I believe the complexity is justified | not an issue | +| 3 | Additional memory requirement | Most node operators are already operating over-provisioned machines which can handle the additional memory requirement. The minimum requirements should be raised but it appears that minimum requirements are already not enough to operate a node | This is a concern but it is not specific to this project | +| 4 | Slowing down the read-update-write workload | This is common pattern in smart contracts so indeed a concern. However, there are future plans on how to address this by serving writes from the flat storage as well which will also reduce the fees of serving writes and make further improvements to the NEAR protocol | This is a concern but hopefully will be addressed in future iterations of the project | ## Copyright -[copyright]: #copyright Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). diff --git a/neps/nep-0413.md b/neps/nep-0413.md index bbac6797e..54da3906e 100644 --- a/neps/nep-0413.md +++ b/neps/nep-0413.md @@ -14,57 +14,70 @@ Created: 25-Oct-2022 A standardized Wallet API method, namely `signMessage`, that allows users to sign a message for a specific recipient using their NEAR account. ## Motivation + NEAR users want to create messages destined to a specific recipient using their accounts. This has multiple applications, one of them being authentication in third-party services. Currently, there is no standardized way for wallets to sign a message destined to a specific recipient. ## Rationale and Alternatives + Users want to sign messages for a specific recipient without incurring in GAS fees, nor compromising their account's security. This means that the message being signed: -1) Must be signed off-chain, with no transactions being involved. -2) Must include the recipient's name and a nonce. -3) Cannot represent a valid transaction. -3) Must be signed using a Full Access Key. -4) Should be simple to produce/verify, and transmitted securely. +1. Must be signed off-chain, with no transactions being involved. +2. Must include the recipient's name and a nonce. +3. Cannot represent a valid transaction. +4. Must be signed using a Full Access Key. +5. Should be simple to produce/verify, and transmitted securely. ### Why Off-Chain? + So the user would not incur in GAS fees, nor the signed message gets broadcasted into a public network. ### Why The Message MUST NOT be a Transaction? How To Ensure This? + An attacker could make the user inadvertently sign a valid transaction which, once signed, could be submitted into the network to execute it. #### How to Ensure the Message is not a Transaction + In NEAR, transactions are encoded in Borsh before being signed. The first attribute of a transaction is a `signerId: string`, which is encoded as: (1) 4 bytes representing the string's length, (2) N bytes representing the string itself. By prepending the prefix tag $2^{31} + 413$ we can both ensure that (1) the whole message is an invalid transaction (since the string would be too long to be a valid signer account id), (2) this NEP is ready for a potential future protocol update, in which non-consensus messages are tagged using $2^{31}$ + NEP-number. ### Why The Message Needs to Include a Receiver and Nonce? + To stop a malicious app from requesting the user to sign a message for them, only to relay it to a third-party. Including the recipient and making sure the user knows about it should mitigate these kind of attacks. Meanwhile, including a nonce helps to mitigate replay attacks, in which an attacker can delay or re-send a signed message. ### Why using a FullAccess Key? Why Not Simply Creating an [FunctionCall Key](https://docs.near.org/concepts/basics/accounts/access-keys) for Signing? -The most common flow for [NEAR user authentication into a Web3 frontend](https://docs.near.org/develop/integrate/frontend#user-sign-in--sign-out) involves the creation of a [FunctionCall Key](](https://docs.near.org/concepts/basics/accounts/access-keys)). + +The most common flow for [NEAR user authentication into a Web3 frontend](https://docs.near.org/develop/integrate/frontend#user-sign-in--sign-out) involves the creation of a [FunctionCall Key](<](https://docs.near.org/concepts/basics/accounts/access-keys)>). One might feel tempted to reproduce such process here, for example, by creating a key that can only be used to call a non-existing method in the user's account. This is a bad idea because: + 1. The user would need to expend gas in creating a new key. 2. Any third-party can ask the user to create a `FunctionCall Key`, thus opening an attack vector. Using a FullAccess key allows us to be sure that the challenge was signed by the user (since nobody should have access to their `FullAccess Key`), while keeping the constraints of not expending gas in the process (because no new key needs to be created). ### Why The Input Needs to Include a State? + Including a state helps to mitigate [CSRF attacks](https://auth0.com/docs/secure/attack-protection/state-parameters). This way, if a message needs to be signed for authentication purposes, the auth service can keep a state to make sure the auth request comes from the right author. ### How to Return the Signed Message in a Safe Way + Sending the signed message in a query string to an arbitrary URL (even within the correct domain) is not secure as the data can be leaked (e.g. through headers, etc). Using URL fragments instead will improve security, since [URL fragments are not included in the `Referer`](https://greenbytes.de/tech/webdav/rfc2616.html#header.referer). ### NEAR Signatures + NEAR transaction signatures are not plain Ed25519 signatures but Ed25519 signatures of a SHA-256 hash (see [near/nearcore#2835](https://github.com/near/nearcore/issues/2835)). Any protocol that signs anything with NEAR account keys should use the same signature format. ## Specification + Wallets must implement a `signMessage` method, which takes a `message` destined to a specific `recipient` and transform it into a verifiable signature. ### Input Interface + `signMessage` must implement the following input interface: ```jsx @@ -78,6 +91,7 @@ interface SignMessageParams { ``` ### Structure + `signMessage` must embed the input `message`, `recipient` and `nonce` into the following predefined structure: ```rust @@ -90,8 +104,10 @@ struct Payload { ``` ### Signature + In order to create a signature, `signMessage` must: -1. Create a `Payload` object. + +1. Create a `Payload` object. 2. Convert the `payload` into its [Borsh Representation](https://borsh.io). 3. Prepend the 4-bytes borsh representation of $2^{31}+413$, as the [prefix tag](https://github.com/near/NEPs/pull/461). 4. Compute the `SHA256` hash of the serialized-prefix + serialized-tag. @@ -100,7 +116,9 @@ In order to create a signature, `signMessage` must: > If the wallet does not hold any `full-access` keys, then it must return an error. ### Example + Assuming that the `signMessage` method was invoked, and that: + - The input `message` is `"hi"` - The input `nonce` is `[0,...,31]` - The input `recipient` is `"myapp.com"` @@ -115,30 +133,36 @@ sha256.hash(Borsh.serialize(2147484061) + Borsh.serialize(Payload{message:" ``` ### Output Interface -`signMessage` must return an object containing the **base64** representation of the `signature`, and all the data necessary to verify such signature. + +`signMessage` must return an object containing the **base64** representation of the `signature`, and all the data necessary to verify such signature. ```jsx interface SignedMessage { accountId: string; // The account name to which the publicKey corresponds as plain text (e.g. "alice.near") - publicKey: string; // The public counterpart of the key used to sign, expressed as a string with format ":" (e.g. "ed25519:6TupyNrcHGTt5XRLmHTc2KGaiSbjhQi1KHtCXTgbcr4Y") + publicKey: string; // The public counterpart of the key used to sign, expressed as a string with format ":" (e.g. "ed25519:6TupyNrcHGTt5XRLmHTc2KGaiSbjhQi1KHtCXTgbcr4Y") signature: string; // The base64 representation of the signature. state?: string; // Optional, applicable to browser wallets (e.g. MyNearWallet). The same state passed in SignMessageParams. } ``` ### Returning the signature + #### Web Wallets + Web Wallets, such as [MyNearWallet](https://mynearwallet.com), should directly return the `SignedMessage` to the `SignMessageParams.callbackUrl`, passing the `accountId`,`publicKey`, `signature` and the state as URL fragments. This is: `#accountId=&publicKey=&signature=&state=`. If the signing process fails, then the wallet must return an error message and the state as string fragments: `#error=&state=`. #### Other Wallets + Non-web Wallets, such as [Ledger](https://www.ledger.com) can directly return the `SignedMessage` (in preference as a JSON object) and raise an error on failure. ## References + A full example on how to implement the `signMessage` method can be [found here](https://github.com/gagdiez/near-login/blob/main/tests/authentication/auth.ava.ts#L27-#L65). ## Drawbacks + Accounts that do not hold a FullAccess Key will not be able to sign this kind of messages. However, this is a necessary tradeoff for security since any third-party can ask the user to create a FunctionAccess key. At the time of writing this NEP, the NEAR ledger app is unable to sign this kind of messages, since currently it can only sign pure transactions. This however can be overcomed by modifying the NEAR ledger app implementation in the near future. @@ -148,11 +172,12 @@ Non-expert subjects could use this standard to authenticate users in an unsecure ## Decision Context ### 1.0.0 - Initial Version + The Wallet Standards Working Group members approved this NEP on January 17, 2023 ([meeting recording](https://youtu.be/Y6z7lUJSUuA)). ### 1.1.0 - First Revison -Important Security concerns were raised by a community member, driving us to change the proposed implementation. +Important Security concerns were raised by a community member, driving us to change the proposed implementation. ### Benefits @@ -162,15 +187,14 @@ Important Security concerns were raised by a community member, driving us to cha ### Concerns -| # | Concern | Resolution | Status | -| - | - | - | - | -| 1 | Implementing the signMessage standard will divide wallets into those that will quickly add support for it and those that will take significantly longer. In this case, some services may not work correctly for some users | (1) Be careful when adding functionality with signMessage with legacy and ensure that alternative authorization methods are possible. For example by adding publicKey. (2) Oblige wallets to implement a standard in specific deadlines to save their support in wallet selector | Resolved | -| 2 | Large number of off-chain transactions will reduce activity in the blockchain and may negatively affect NEAR rate and attractiveness to third-party developers | There seems to be a general agreement that it is a good default | Resolved | -| 3 | `receiver` terminology can be misleading and confusing when existing functionality is taken into consideration (`signTransaction`) | It was recommended for the community to vote for a new name, and the NEP was updated changing `receiver` to `recipient` | Resolved | -| 4 | The NEP should emphasize that `nonce` and `receiver` should be clearly displayed to the user in the signing requests by wallets to achieve the desired security from these params being included | We strongly recommend the wallet to clearly display all the elements that compose the message being signed. However, this pertains to the wallet's UI and UX, and not to the method's specification, thus the NEP was not changed. | Resolved | -| 5 | NEP-408 (Injected Wallet API) should be extended with this new `signMessage` method | It is not a blocker for this NEP, but a follow-up NEP-extension proposal is welcome. | Resolved | +| # | Concern | Resolution | Status | +| --- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- | +| 1 | Implementing the signMessage standard will divide wallets into those that will quickly add support for it and those that will take significantly longer. In this case, some services may not work correctly for some users | (1) Be careful when adding functionality with signMessage with legacy and ensure that alternative authorization methods are possible. For example by adding publicKey. (2) Oblige wallets to implement a standard in specific deadlines to save their support in wallet selector | Resolved | +| 2 | Large number of off-chain transactions will reduce activity in the blockchain and may negatively affect NEAR rate and attractiveness to third-party developers | There seems to be a general agreement that it is a good default | Resolved | +| 3 | `receiver` terminology can be misleading and confusing when existing functionality is taken into consideration (`signTransaction`) | It was recommended for the community to vote for a new name, and the NEP was updated changing `receiver` to `recipient` | Resolved | +| 4 | The NEP should emphasize that `nonce` and `receiver` should be clearly displayed to the user in the signing requests by wallets to achieve the desired security from these params being included | We strongly recommend the wallet to clearly display all the elements that compose the message being signed. However, this pertains to the wallet's UI and UX, and not to the method's specification, thus the NEP was not changed. | Resolved | +| 5 | NEP-408 (Injected Wallet API) should be extended with this new `signMessage` method | It is not a blocker for this NEP, but a follow-up NEP-extension proposal is welcome. | Resolved | ## Copyright -[copyright]: #copyright Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). diff --git a/neps/nep-0418.md b/neps/nep-0418.md index d6788a155..9c6f9ed96 100644 --- a/neps/nep-0418.md +++ b/neps/nep-0418.md @@ -37,6 +37,7 @@ The error inside `attached_deposit` for view calls will be removed, and for all Currently, the implementation for `attached_deposit` is as follows: + ```rust pub fn attached_deposit(&mut self, balance_ptr: u64) -> Result<()> { self.gas_counter.pay_base(base)?; @@ -97,6 +98,5 @@ The initial version of NEP-418 was approved by Tools Working Group members on Ja | 3 | Can we assume that in all view calls, the `attached_deposit` in the VMContext always zero? | Yes, there is no way to set `attached_deposit` in view calls context | Resolved | ## Copyright -[copyright]: #copyright Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). diff --git a/neps/nep-0448.md b/neps/nep-0448.md index 6ecf862b5..e925f1ab9 100644 --- a/neps/nep-0448.md +++ b/neps/nep-0448.md @@ -14,7 +14,7 @@ A major blocker to a good new user onboarding experience is that users have to a their account. With the implementation of [NEP-366](https://github.com/near/NEPs/pull/366), users don't necessarily have to first acquire NEAR tokens in order to pay transaction fees, but they still have to pay for the storage of their account. To address this problem, we propose allowing each account to have free storage for the account itself and up to four keys -and account for the cost of storage in the gas cost of create account transaction. +and account for the cost of storage in the gas cost of create account transaction. ## Motivation @@ -31,51 +31,58 @@ and two function call access keys so that users can use two apps before graduati ## Rationale and alternatives There are a few alternative ideas: -* Completely disregard storage staking and do not change the account creation cost. This makes the implementation even -simpler. However, there may be a risk of spamming attack given that the cost of creating an account is around 0.2Tgas. -In addition, with the current design, it is easy to further reduce the cost. Going the other way is more difficult. -* Do not change how storage staking is calculated when converting to gas cost. This means that account creation cost would -be around 60Tgas, which is both high in gas (meaning that the throughput is limited and more likely for some contract to break) -and more costly for users (around 0.006N per account creation). + +- Completely disregard storage staking and do not change the account creation cost. This makes the implementation even + simpler. However, there may be a risk of spamming attack given that the cost of creating an account is around 0.2Tgas. + In addition, with the current design, it is easy to further reduce the cost. Going the other way is more difficult. +- Do not change how storage staking is calculated when converting to gas cost. This means that account creation cost would + be around 60Tgas, which is both high in gas (meaning that the throughput is limited and more likely for some contract to break) + and more costly for users (around 0.006N per account creation). ## Specification There are two main changes to the protocol: -* Account creation cost needs to be increased. For every account, at creation time, 770 bytes of storage are reserved -for the account itself + four full access keys + two function call access keys. For function call access keys, -the "free" ones cannot use `method_names` in order to minimize the storage requirement for an account. -The number of bytes is calculated as follows: - - An account takes 100 bytes due to `storage_usage_config.num_bytes_account` - - A full access key takes 42 bytes and there is an additional 40 bytes required due to `storage_usage_config.num_extra_bytes_record` - - A function call access key takes 131 bytes and there is an additional 40 bytes required due to `storage_usage_config.num_extra_bytes_record` - - Therefore the total the number of bytes is `100 + (131 + 40) * 2 + (42 + 40) * 4 = 770`. + +- Account creation cost needs to be increased. For every account, at creation time, 770 bytes of storage are reserved + for the account itself + four full access keys + two function call access keys. For function call access keys, + the "free" ones cannot use `method_names` in order to minimize the storage requirement for an account. + The number of bytes is calculated as follows: + _ An account takes 100 bytes due to `storage_usage_config.num_bytes_account` + _ A full access key takes 42 bytes and there is an additional 40 bytes required due to `storage_usage_config.num_extra_bytes_record` + _ A function call access key takes 131 bytes and there is an additional 40 bytes required due to `storage_usage_config.num_extra_bytes_record` + _ Therefore the total the number of bytes is `100 + (131 + 40) * 2 + (42 + 40) * 4 = 770`. The cost of these bytes is paid through transaction fee. Note that there is already [discussion](https://github.com/near/NEPs/issues/415) -around the storage cost of NEAR and whether it is reasonable. While this proposal does not attempt to change the entire -storage staking mechanism, the cost of storage is reduced in 10x when converting to gas. A [discussion](https://gov.near.org/t/storage-staking-price/399) -from a while ago mentioned this idea, and the concerns there were proven to be not real concerns. No one is deleting -data from storage in practice and the storage staking mechanism does not really serve its purpose. That conversion means -we increase the account creation cost to 7.7Tgas from 0.2Tgas -* Storage staking check will not be applied if an account has <= 4 full access keys and <= 2 function call access keys -and does not have a contract deployed. If an account accrues more than full access keys or function call access keys, -however, it must pay for the storage of everything including those 6 keys. This makes the implementation simpler and less error-prone. + around the storage cost of NEAR and whether it is reasonable. While this proposal does not attempt to change the entire + storage staking mechanism, the cost of storage is reduced in 10x when converting to gas. A [discussion](https://gov.near.org/t/storage-staking-price/399) + from a while ago mentioned this idea, and the concerns there were proven to be not real concerns. No one is deleting + data from storage in practice and the storage staking mechanism does not really serve its purpose. That conversion means + we increase the account creation cost to 7.7Tgas from 0.2Tgas + +- Storage staking check will not be applied if an account has <= 4 full access keys and <= 2 function call access keys + and does not have a contract deployed. If an account accrues more than full access keys or function call access keys, + however, it must pay for the storage of everything including those 6 keys. This makes the implementation simpler and less error-prone. ## Reference Implementation (Required for Protocol Working Group proposals, optional for other categories) Details of the changes described in the section above: -* Change `create_account_cost` to -``` + +- Change `create_account_cost` to + +```json "create_account_cost": { "send_sir": 3850000000000, "send_not_sir": 3850000000000, "execution": 3850000000000 }, ``` -* Change the implementation of `get_insufficient_storage_stake` to check whether an account is zero balance account. -Note that even though the intent, as described in the section above, is to limit the number of full access keys to 4 -and the number of function call access keys to 2, for the ease of implementation, it makes sense to limit the size of -`storage_usage` on an account to 770 bytes because `storage_usage` is already stored under `Account` and it does not -require any additional storage reads. More specifically, the check looks roughly as follows: + +- Change the implementation of `get_insufficient_storage_stake` to check whether an account is zero balance account. + Note that even though the intent, as described in the section above, is to limit the number of full access keys to 4 + and the number of function call access keys to 2, for the ease of implementation, it makes sense to limit the size of + `storage_usage` on an account to 770 bytes because `storage_usage` is already stored under `Account` and it does not + require any additional storage reads. More specifically, the check looks roughly as follows: + ```rust /// Returns true if an account is a zero balance account fn check_for_zero_balance_account(account: &Account) -> bool { @@ -86,10 +93,10 @@ fn check_for_zero_balance_account(account: &Account) -> bool { ## Drawbacks (Optional) - Reduction of storage cost when converting the storage cost of zero balance accounts to gas cost may be a concern. But -I argue that the current storage cost is too high. A calculation shows that the current storage cost is around 36,000 times -higher than S3 storage cost. In addition, when a user accrues any contract data or has more than three keys on their account, -they have to pay for the storage cost of everything combined. In that sense, a user would pay slightly more than what -they pay today when their account is no longer a zero-balance account. + I argue that the current storage cost is too high. A calculation shows that the current storage cost is around 36,000 times + higher than S3 storage cost. In addition, when a user accrues any contract data or has more than three keys on their account, + they have to pay for the storage cost of everything combined. In that sense, a user would pay slightly more than what + they pay today when their account is no longer a zero-balance account. ## Unresolved Issues (Optional) @@ -97,7 +104,7 @@ they pay today when their account is no longer a zero-balance account. - We may change the number of keys allowed for zero-balance accounts in the future. - A more radical thought: we can separate out zero-balance accounts into its own trie and manage them separately. This -may allow more customization on how we want zero-balance accounts to be treated. + may allow more customization on how we want zero-balance accounts to be treated. ## Decision Context @@ -113,17 +120,15 @@ The initial version of NEP-448 was approved by Protocol Working Group members on #### Concerns -| # | Concern | Resolution | Status | -| - | - | - | - | -| 1 | The number of full access keys allowed is too small | Could be done in a future iteration. | Resolved | -| 2 | No incentive for people to remove zero balance account. | Very few people actually delete their account anyways. | Resolved | -| 3 | UX of requiring balance after a user graduate from zero balance account to a regular account | The experience of graduating from zero balance account should be handled on the product side | Resolved | -| 4 | Increase of account creation cost may break some existing contracts | A thorough investigation has been done and it turns out that we only need to change the contract that is deployed on `near` slightly | Resolved | -| 5 | Account creation speed is slower due to increased cost | Unlikely to be a concern, especially given that the number of shards is expected to grow in the future | Resolved | -| 6 | Cost of transfers to implicit account increases | Unlikely to break anything at the moment, and could be addressed in the future in a different NEP (see https://github.com/near/NEPs/issues/462 for more details) | Resolved | +| # | Concern | Resolution | Status | +| --- | -------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- | +| 1 | The number of full access keys allowed is too small | Could be done in a future iteration. | Resolved | +| 2 | No incentive for people to remove zero balance account. | Very few people actually delete their account anyways. | Resolved | +| 3 | UX of requiring balance after a user graduate from zero balance account to a regular account | The experience of graduating from zero balance account should be handled on the product side | Resolved | +| 4 | Increase of account creation cost may break some existing contracts | A thorough investigation has been done and it turns out that we only need to change the contract that is deployed on `near` slightly | Resolved | +| 5 | Account creation speed is slower due to increased cost | Unlikely to be a concern, especially given that the number of shards is expected to grow in the future | Resolved | +| 6 | Cost of transfers to implicit account increases | Unlikely to break anything at the moment, and could be addressed in the future in a different NEP (see https://github.com/near/NEPs/issues/462 for more details) | Resolved | ## Copyright -[copyright]: #copyright - Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). diff --git a/neps/nep-0455.md b/neps/nep-0455.md index 6ad46950d..062589530 100644 --- a/neps/nep-0455.md +++ b/neps/nep-0455.md @@ -46,13 +46,16 @@ Setting temporary high compute costs for writes will ensure that this undercharg ## Alternatives ### Increase the gas costs for undercharged operations + We could increase the gas costs for the operations that are undercharged to match the computational time it takes to process them according to the rule 1ms = 1TGas. Pros: + - Does not require any new code or design work (but still requires a protocol version bump) - Security implications are well-understood Cons: + - Can break contracts that rely on current gas costs, in particular steeply increasing operating costs for the most active users of the blockchain (aurora and sweat) - Doing this safely and responsibly requires prior consent by the affected parties which is hard to do without disclosing security-sensitive information about undercharging in public @@ -60,16 +63,19 @@ In case of flat storage specifically, using this approach will result in a large With compute costs, we will be able to roll out the read-only flat storage with minimal impact on deployed contracts. ### Adjust the gas chunk limit + We could continuously measure the chunk production time in nearcore clients and compare it to the gas burnt. If the chunk producer observes undercharging, it decreases the limit. If there is overcharging, the limit can be increased up to a limit of at most 1000 Tgas. To make such adjustment more predictable under spiky load, we also [limit](https://nomicon.io/Economics/Economic#transaction-fees) the magnitude of change of gas limit by 0.1% per block. Pros: + - Prevents moderate undercharging from stalling the network - No protocol change necessary (as this feature is already [a part of the protocol](https://nomicon.io/Economics/Economic#transaction-fees)), we could easily experiment and revert if it does not work well Cons: + - Very broad granularity --- undercharging in one parameter affects all users, even those that never use the undercharged parts - Dependence on validator hardware --- someone running overspecced hardware will continuously want to increase the limit, others might run with underspecced hardware and continuously want to decrease the limit - Malicious undercharging attacks are unlikely to be prevented by this --- a single 10x undercharged receipt still needs to be processed using the old limit. @@ -79,6 +85,7 @@ The effective limit per chunk is `gas_limit` + 300Tgas since receipts are added Thus a gas limit of 0gas only reduces the effective limit from 1300Tgas to 300Tgas, which means a single 10x undercharged receipt can still result in a chunk with compute usage of 3 seconds (equivalent to 3000TGas) ### Allow skipping chunks in the chain + Slow chunk production in one shard can introduce additional user-visible latency in all shards as the nodes expect a regular and timely chunk production during normal operation. If processing the chunk takes much longer than 1.3s, it can cause the corresponding block and possibly more consecutive blocks to be skipped. @@ -87,9 +94,11 @@ This way will still ensure a regular block production, at a cost of lower throug The chunk should still be included in a later block to avoid stalling the affected shard. Pros: + - Fast and automatic adaptation to the blockchain workload Cons: + - For the purpose of slashing, it is hard to distinguish situations when the honest block producer skips chunk due to slowness from the situations when the block producer is offline or is maliciously stalling the block production. We need some mechanism (e.g. on-chain voting) for nodes to agree that the chunk was skipped legitimately due to slowness as otherwise we introduce new attack vectors to stall the network ## Specification @@ -126,6 +135,7 @@ Compute costs **do not** count towards the transaction/receipt gas limit of 300T Compute costs are static for each protocol version. ### Using Compute Costs + Compute costs different from gas costs are only a temporary solution. Whenever we introduce a compute cost, we as the community can discuss this publicly and find a solution to the specific problem together. @@ -144,10 +154,12 @@ Value 1 corresponds to `10^-15` seconds or 1fs (femtosecond) to match the gas co By default, the parameter compute cost matches the corresponding gas cost. Compute costs should be applicable to all gas parameters, specifically including: + - [`ExtCosts`](https://cs.github.com/near/nearcore/blob/6e08a41084c632010b1d4c42132ad58ecf1398a2/core/primitives-core/src/config.rs#L377) - [`ActionCosts`](https://cs.github.com/near/nearcore/blob/6e08a41084c632010b1d4c42132ad58ecf1398a2/core/primitives-core/src/config.rs#L456) Changes necessary to support `ExtCosts`: + 1. Track compute usage in [`GasCounter`](https://cs.github.com/near/nearcore/blob/51670e593a3741342a1abc40bb65e29ba0e1b026/runtime/near-vm-logic/src/gas_counter.rs#L47) struct 2. Track compute usage in [`VMOutcome`](https://cs.github.com/near/nearcore/blob/056c62183e31e64cd6cacfc923a357775bc2b5c9/runtime/near-vm-logic/src/logic.rs#L2868) struct (alongside `burnt_gas` and `used_gas`) 3. Store compute usage in [`ActionResult`](https://cs.github.com/near/nearcore/blob/6d2f3fcdd8512e0071847b9d2ca10fb0268f469e/runtime/runtime/src/lib.rs#L129) and aggregate it across multiple actions by modifying [`ActionResult::merge`](https://cs.github.com/near/nearcore/blob/6d2f3fcdd8512e0071847b9d2ca10fb0268f469e/runtime/runtime/src/lib.rs#L141) @@ -155,6 +167,7 @@ Changes necessary to support `ExtCosts`: 5. Enforce the chunk compute limit when the chunk is [applied](https://cs.github.com/near/nearcore/blob/6d2f3fcdd8512e0071847b9d2ca10fb0268f469e/runtime/runtime/src/lib.rs#L1325) Additional changes necessary to support `ActionCosts`: + 1. Return compute costs from [`total_send_fees`](https://cs.github.com/near/nearcore/blob/578983c8df9cc36508da2fb4a205c852e92b211a/runtime/runtime/src/config.rs#L71) 2. Store aggregate compute cost in [`TransactionCost`](https://cs.github.com/near/nearcore/blob/578983c8df9cc36508da2fb4a205c852e92b211a/runtime/runtime/src/config.rs#L22) struct 3. Propagate compute costs to [`VerificationResult`](https://cs.github.com/near/nearcore/blob/578983c8df9cc36508da2fb4a205c852e92b211a/runtime/runtime/src/verifier.rs#L330) @@ -189,6 +202,7 @@ So even with 10x difference between gas and compute costs, the DoS only becomes ## Unresolved Issues ## Future possibilities + We can also think about compute costs smaller than gas costs. For example, we charge gas instead of token balance for extra storage bytes in [NEP-448](https://github.com/near/NEPs/pull/448), it would make sense to set the compute cost to 0 for the part that covers on-chain storage if the throttling due to increased gas cost becomes problematic. Otherwise, the throughput would be throttled unnecessarily. @@ -197,6 +211,7 @@ A further option would be to change compute costs dynamically without a protocol This would be a catch-all, self-healing solution that requires zero intervention from anyone. The network would simply throttle throughput when block time remains too high for long enough. Pursuing this approach would require additional design work: + - On-chain voting to agree on new values of costs, given that inputs to the adjustment process are not deterministic (measurements of wall clock time it takes to process receipt on particular validator) - Ensuring that dynamic adjustment is done in a safe way that does not lead to erratic behavior of costs (and as a result unpredictable network throughput). Having some experience manually operating this mechanism would be valuable before introducing automation @@ -227,11 +242,11 @@ No concerns that need to be addressed. The drawbacks listed in this NEP are mino ## Copyright -[copyright]: #copyright Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). ## References + - https://gov.near.org/t/proposal-gas-weights-to-fight-instability-to-due-to-undercharging/30919 - https://github.com/near/nearcore/issues/8032 From 8e23ad6dd0fdb011f4fb160550359b88c6b2d846 Mon Sep 17 00:00:00 2001 From: Lachlan Glen <54282009+lachlanglen@users.noreply.github.com> Date: Mon, 24 Apr 2023 10:02:36 -0400 Subject: [PATCH 119/150] NEP-0469: add `nft_metadata_update` event to NEP171 (#469) See NEAR Forum discussion here: https://gov.near.org/t/extending-nep-171-events-standard-to-include-nft-update-events/30285 - Add `nft_metadata_update` event to NEP-171 events - Increment events version to `1.2.0` --- neps/nep-0171.md | 68 +++++++++++++++++++++++++++++++++++++----------- 1 file changed, 53 insertions(+), 15 deletions(-) diff --git a/neps/nep-0171.md b/neps/nep-0171.md index 1b7228892..8b0990319 100644 --- a/neps/nep-0171.md +++ b/neps/nep-0171.md @@ -6,9 +6,9 @@ DiscussionsTo: https://github.com/near/NEPs/discussions/171 Status: Final Type: Standards Track Category: Contract -Version: 1.1.0 +Version: 1.2.0 Created: 03-Mar-2022 -Updated: 07-Mar-2023 +Updated: 13-Mar-2023 Requires: 297 --- @@ -218,21 +218,21 @@ function nft_on_transfer( ### Events -NEAR and third-party applications need to track `mint`, `transfer`, `burn`, and `contract_metadata_update` events for all NFT-driven apps consistently. +NEAR and third-party applications need to track mint, transfer, burn, metadata update, and contract metadata update events for all NFT-driven apps consistently. This extension addresses that. Keep in mind that applications, including NEAR Wallet, could require implementing additional methods to display the NFTs correctly, such as [`nft_metadata`][Metadata] and [`nft_tokens_for_owner`][NFT Enumeration]). #### Events Interface -Non-Fungible Token Events MUST have `standard` set to `"nep171"`, standard version set to `"1.1.0"`, `event` value is one of `nft_mint`, `nft_burn`, `nft_transfer`, or `contract_metadata_update`, and `data` must be of one of the following relevant types: `NftMintLog[] | NftTransferLog[] | NftBurnLog[] | NftContractMetadataUpdateLog[]`: +Non-Fungible Token Events MUST have `standard` set to `"nep171"`, standard version set to `"1.2.0"`, `event` value is one of `nft_mint`, `nft_burn`, `nft_transfer`, `nft_metadata_update`, or `contract_metadata_update`, and `data` must be of one of the following relevant types: `NftMintLog[] | NftTransferLog[] | NftBurnLog[] | NftMetadataUpdateLog[] | NftContractMetadataUpdateLog[]`: ```ts interface NftEventLogData { standard: "nep171", - version: "1.1.0", - event: "nft_mint" | "nft_burn" | "nft_transfer" | "contract_metadata_update", - data: NftMintLog[] | NftTransferLog[] | NftBurnLog[] | NftContractMetadataUpdateLog[], + version: "1.2.0", + event: "nft_mint" | "nft_burn" | "nft_transfer" | "nft_metadata_update" | "contract_metadata_update", + data: NftMintLog[] | NftTransferLog[] | NftBurnLog[] | NftMetadataUpdateLog[] | NftContractMetadataUpdateLog[], } ``` @@ -276,6 +276,15 @@ interface NftTransferLog { memo?: string } +// An event log to capture token metadata updating +// Arguments +// * `token_ids`: ["1", "abc"] +// * `memo`: optional message +interface NftMetadataUpdateLog { + token_ids: string[], + memo?: string +} + // An event log to capture contract metadata updates. Note that the updated contract metadata is not included in the log, as it could easily exceed the 16KB log size limit. Listeners can query `nft_metadata` to get the updated contract metadata. // Arguments // * `memo`: optional message @@ -291,7 +300,7 @@ Single owner batch minting (pretty-formatted for readability purposes): ```js EVENT_JSON:{ "standard": "nep171", - "version": "1.1.0", + "version": "1.2.0", "event": "nft_mint", "data": [ {"owner_id": "foundation.near", "token_ids": ["aurora", "proximitylabs"]} @@ -304,7 +313,7 @@ Different owners batch minting: ```js EVENT_JSON:{ "standard": "nep171", - "version": "1.1.0", + "version": "1.2.0", "event": "nft_mint", "data": [ {"owner_id": "foundation.near", "token_ids": ["aurora", "proximitylabs"]}, @@ -318,7 +327,7 @@ Different events (separate log entries): ```js EVENT_JSON:{ "standard": "nep171", - "version": "1.1.0", + "version": "1.2.0", "event": "nft_burn", "data": [ {"owner_id": "foundation.near", "token_ids": ["aurora", "proximitylabs"]}, @@ -329,7 +338,7 @@ EVENT_JSON:{ ```js EVENT_JSON:{ "standard": "nep171", - "version": "1.1.0", + "version": "1.2.0", "event": "nft_transfer", "data": [ {"old_owner_id": "user1.near", "new_owner_id": "user2.near", "token_ids": ["meme"], "memo": "have fun!"} @@ -342,7 +351,7 @@ Authorized id: ```js EVENT_JSON:{ "standard": "nep171", - "version": "1.1.0", + "version": "1.2.0", "event": "nft_burn", "data": [ {"owner_id": "owner.near", "token_ids": ["goodbye", "aurevoir"], "authorized_id": "thirdparty.near"} @@ -350,12 +359,25 @@ EVENT_JSON:{ } ``` +NFT Metadata Update: + +```js +EVENT_JSON:{ + "standard": "nep171", + "version": "1.2.0", + "event": "nft_metadata_update", + "data": [ + {"token_ids": ["1", "2"]} + ] +} +``` + Contract metadata update: ```js EVENT_JSON:{ "standard": "nep171", - "version": "1.1.0", + "version": "1.2.0", "event": "contract_metadata_update", "data": [] } @@ -365,7 +387,7 @@ EVENT_JSON:{ Note that the example events above cover two different kinds of events: -1. Events that do not have a dedicated trigger function in the NFT Standard (`nft_mint`, `nft_burn`, `contract_metadata_update`) +1. Events that do not have a dedicated trigger function in the NFT Standard (`nft_mint`, `nft_metadata_update`, `nft_burn`, `contract_metadata_update`) 2. An event that has a relevant trigger function [NFT Core Standard](https://nomicon.io/Standards/NonFungibleToken/Core.html#nft-interface) (`nft_transfer`) This event standard also applies beyond the events highlighted here, where future events follow the same convention of as the second type. For instance, if an NFT contract uses the [approval management standard](https://nomicon.io/Standards/NonFungibleToken/ApprovalManagement.html), it may emit an event for `nft_approve` if that's deemed as important by the developer community. @@ -392,7 +414,7 @@ This NEP had several pre-1.0.0 iterations that led to the following errata updat ### 1.1.0 - Add `contract_metadata_update` Event -The extension NEP-0423 that added Contract Metadata to this NEP-0171 was approved by Contract Standards Working Group members (@frol, @abacabadabacaba, @mfornet) on January 13, 2023 ([meeting recording](https://youtu.be/pBLN9UyE6AA)). +The extension NEP-0423 that added Contract Metadata Update Event Kind to this NEP-0171 was approved by Contract Standards Working Group members (@frol, @abacabadabacaba, @mfornet) on January 13, 2023 ([meeting recording](https://youtu.be/pBLN9UyE6AA)). #### Benefits @@ -406,6 +428,22 @@ The extension NEP-0423 that added Contract Metadata to this NEP-0171 was approve | 1 | Old NFT contracts do not emit JSON Events at all; more recent NFT contracts will only emit mint/burn/transfer events, so when it comes to legacy contracts support, we won’t benefit from this new event type and only further fragment the implementations | Legacy contracts usage will die out eventually and new contracts will support new features in a non-breaking way | Resolved | | 2 | There is a need to have a similar event type for individual NFT updates | It is outside of the scope of this NEP extension. Feel free to create a follow-up proposal | Resolved | +### 1.2.0 - Add `nft_metadata_update` Event + +The extension NEP-0469 that added Token Metadata Update Event Kind to this NEP-0171 was approved by Contract Standards Working Group members (@frol, @abacabadabacaba, @mfornet, @fadeevab, @robert-zaremba) on April 21, 2023 ([meeting recording](https://youtu.be/KOIT8XDQNjM)). + +#### Benefits + +- Apps that cache indexed NFTs will benefit from having this new event type as they won't need to have a custom logic to track potentially changing NFTs or refetch all NFTs on every transaction to NFT contract +- It plays well with `contract_metadata_update` event that was introduced in version 1.1.0 of this NEP +- This NEP extension only introduces an additional event type, so there is no breaking change to the original NEP + +#### Concerns + +| # | Concern | Resolution | Status | +| - | - | - | - | +| 1 | Ecosystem will be split where legacy contracts won't emit these new events, so legacy support will still be needed | In the future, there will be fewer legacy contracts and eventually apps will have support for this type of event | Resolved | +| 2 | `nft_update` event name is ambiguous | It was decided to use `nft_metadata_update` name, instead | Resolved | ## Copyright From c4c75f2b5297b58b48db478db03122bf06654bcf Mon Sep 17 00:00:00 2001 From: Akhilesh Singhania Date: Thu, 27 Apr 2023 12:25:07 +0200 Subject: [PATCH 120/150] fix: I believe that zero-balance accounts are now finalised (#479) - marks the NEP as finalised - Adds it to the list of NEPs on the README.md --- README.md | 1 + neps/nep-0448.md | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index f22c101b5..6b81d1867 100644 --- a/README.md +++ b/README.md @@ -27,6 +27,7 @@ Changes to the protocol specification and standards are called NEAR Enhancement | [0330](https://github.com/near/NEPs/blob/master/neps/nep-0330.md) | Source Metadata | @BenKurrek | Review | | [0366](https://github.com/near/NEPs/blob/master/neps/nep-0366.md) | Meta Transactions | @ilblackdragon @e-uleyskiy @fadeevab | Draft | | [0399](https://github.com/near/NEPs/blob/master/neps/nep-0399.md) | Flat Storage | @Longarithm @mzhangmzz | Review | +| [0448](https://github.com/near/NEPs/blob/master/neps/nep-0448.md) | Zero-balance Accounts | @bowenwang1996 | Final | | [0455](https://github.com/near/NEPs/blob/master/neps/nep-0455.md) | Parameter Compute Costs | @akashin @jakmeier | Final | ## Specification diff --git a/neps/nep-0448.md b/neps/nep-0448.md index e925f1ab9..d7d2856fd 100644 --- a/neps/nep-0448.md +++ b/neps/nep-0448.md @@ -3,7 +3,7 @@ NEP: 448 Title: Zero-balance Accounts Author: Bowen Wang DiscussionsTo: https://github.com/nearprotocol/neps/pull/448 -Status: Draft +Status: Final Type: Protocol Track Created: 10-Jan-2023 --- From 9f70d41d28e46af119741378b60727d13529fcde Mon Sep 17 00:00:00 2001 From: Robert Zaremba Date: Mon, 15 May 2023 18:25:58 +0200 Subject: [PATCH 121/150] update NEP template (#474) * added Consequences and merged into it "considerations" * moved Alternatives and Future Possibilities above the Consequences / Considerations * Updated Changelog Concerns table * Added example of NEP Status section for a Pull Request description in the NEP process (`nep-0001.md`) --- nep-0000-template.md | 56 ++++++++++++++++++++++++++++---------------- neps/nep-0001.md | 52 ++++++++++++++++++++++++++++------------ 2 files changed, 73 insertions(+), 35 deletions(-) diff --git a/nep-0000-template.md b/nep-0000-template.md index a4223851a..772979545 100644 --- a/nep-0000-template.md +++ b/nep-0000-template.md @@ -70,25 +70,41 @@ The section should return to the examples given in the previous section, and exp [Explicitly outline any security concerns in relation to the NEP, and potential ways to resolve or mitigate them. At the very least, well-known relevant threats must be covered, e.g. person-in-the-middle, double-spend, XSS, CSRF, etc.] -## Drawbacks (Optional) +## Alternatives -[Explain why we should not implement this NEP and any limitations. It is helpful to record any concerns raised throughout the NEP discussion.] +[Explain any alternative designs that were considered and the rationale for not choosing them. Why your design is superior?] -## Unresolved Issues (Optional) +## Future possibilities -[Explain any issues that warrant further discussion. Considerations: +[Describe any natural extensions and evolutions to the NEP proposal, and how they would impact the project. Use this section as a tool to help fully consider all possible interactions with the project in your proposal. This is also a good place to "dump ideas"; if they are out of scope for the NEP but otherwise related. Note that having something written down in the future-possibilities section is not a reason to accept the current or a future NEP. Such notes should be in the section on motivation or rationale in this or subsequent NEPs. The section merely provides additional information.] -- What parts of the design do you expect to resolve through the NEP process before this gets merged? -- What parts of the design do you expect to resolve through the implementation of this feature before stabilization? -- What related issues do you consider out of scope for this NEP that could be addressed in the future independently of the solution that comes out of this NEP?] +## Consequences -## Alternatives +[This section describes the consequences, after applying the decision. All consequences should be summarized here, not just the "positive" ones. Record any concerns raised throughout the NEP discussion.] -[Explain any alternative designs that were considered and the rationale for not choosing them. Why your design is superior?] +### Positive -## Future possibilities +- p1 -[Describe any natural extensions and evolutions to the NEP proposal, and how they would impact the project. Use this section as a tool to help fully consider all possible interactions with the project in your proposal. This is also a good place to "dump ideas"; if they are out of scope for the NEP but otherwise related. Note that having something written down in the future-possibilities section is not a reason to accept the current or a future NEP. Such notes should be in the section on motivation or rationale in this or subsequent NEPs. The section merely provides additional information.] +### Neutral + +- n1 + +### Negative + +- n1 + +### Backwards Compatibility + +[All NEPs that introduce backwards incompatibilities must include a section describing these incompatibilities and their severity. Author must explain a proposes to deal with these incompatibilities. Submissions without a sufficient backwards compatibility treatise may be rejected outright.] + +## Unresolved Issues (Optional) + +[Explain any issues that warrant further discussion. Considerations + +- What parts of the design do you expect to resolve through the NEP process before this gets merged? +- What parts of the design do you expect to resolve through the implementation of this feature before stabilization? +- What related issues do you consider out of scope for this NEP that could be addressed in the future independently of the solution that comes out of this NEP?] ## Changelog @@ -96,25 +112,25 @@ The section should return to the examples given in the previous section, and exp ### 1.0.0 - Initial Version -[Placeholder for the context about when and who approved this NEP version.] +> Placeholder for the context about when and who approved this NEP version. #### Benefits -[Placeholder for Subject Matter Experts review for this version:] +> List of benefits filled by the Subject Matter Experts while reviewing this version: - Benefit 1 - Benefit 2 #### Concerns -[Template for Subject Matter Experts review for this version:] -| # | Concern | Resolution | Status | -| - | - | - | - | -| 1 | | | | -| 2 | | | | +> Template for Subject Matter Experts review for this version: +> Status: New | Ongoing | Resolved -## Copyright +| # | Concern | Resolution | Status | +| --: | :------ | :--------- | -----: | +| 1 | | | | +| 2 | | | | -[copyright]: #copyright +## Copyright Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). diff --git a/neps/nep-0001.md b/neps/nep-0001.md index ba343ab3e..b41bc9fd3 100644 --- a/neps/nep-0001.md +++ b/neps/nep-0001.md @@ -31,7 +31,7 @@ There are four kinds of NEPs: 3. A **Wallet Standards** NEP specifies ecosystem-wide APIs for Wallet implementations. 4. A **Developer Tools** NEP defines norms and guidelines for developer tooling in the NEAR ecosystem. -Currently, all types of NEPs follow the same process, but for Protocol NEPs a draft implementation is required. +Currently, all types of NEPs follow the same process, but for Protocol NEPs a draft implementation is required. ## Submit a NEP @@ -46,7 +46,7 @@ Before submitting a NEP, the author should first attempt to ascertain whether th In general, the process for socializing an idea is: - **Check prior proposals:** Many ideas for changing NEAR come up frequently. Please search the [Dev Gov Gigs Board](https://devgovgigs.near.social), the [NEAR Forums](https://gov.near.org), and NEPs in this repo before proposing something new. -- **Share the idea:** Submit your [idea](https://www.neardevgov.org/blog/how-to-ideate-in-the-near-developer-governance) on the [Dev Gov Gigs Board](https://devgovgigs.near.social). +- **Share the idea:** Submit your [idea](https://www.neardevgov.org/blog/how-to-ideate-in-the-near-developer-governance) on the [Dev Gov Gigs Board](https://devgovgigs.near.social). - **Get feedback:** The [Dev Gov Gigs Board](https://devgovgigs.near.social) has comment threading which allows the community to ideate, ask questions, wrestle with approaches, etc. If more immediate responses are desired, consider bringing the conversation to the appropriate [Community Group](https://gov.near.org/c/dev/community-groups/103). ### Submit a NEP Draft @@ -58,7 +58,7 @@ To submit a NEP draft as a pull request, the NEP author should: 1. Fork the [NEPs repository](https://github.com/near/NEPs). 2. Copy `nep-0000-template.md` to `neps/nep-0000-my-feature.md` (where “my-feature” is descriptive; don’t assign a NEP number yet). 3. Fill in the NEP following the NEP template guidelines. For the Header Preamble, make sure to set the status as “Draft.” -4. Push this to your GitHub fork and submit a pull request. +4. Push this to your GitHub fork and submit a pull request. 5. Now that your NEP has an open pull request, use the pull request number to update your `0000` prefix. For example, if the PR is 305, the NEP should be `neps/nep-0305-my-feature.md`. 6. Push this to your GitHub fork and submit a pull request. Mention the @near/nep-moderators in the comment and turn the PR into a "Ready for Review" state once you believe the NEP is ready for review. @@ -68,13 +68,36 @@ The NEP process begins when an author submits a [NEP draft](#submit-a-nep-draft) ![NEP Process](https://user-images.githubusercontent.com/110252255/201413632-f72743d6-593e-4747-9409-f56bc38de17b.png) - ### NEP Stages -- **Draft:** The first formally tracked stage of a new NEP. This process begins once an author submits a draft proposal and the NEP moderator merges it into the NEP repo when properly formatted. +- **Draft:** The first formally tracked stage of a new NEP. This process begins once an author submits a draft proposal and the NEP moderator merges it into the NEP repo when properly formatted. - **Review:** A NEP moderator marks a NEP as ready for Subject Matter Experts Review. If the NEP is not approved within two months, it is automatically rejected. - **Voting:** This is the final voting period for a NEP. The working group will vote on whether to accept or reject the NEP. This period is limited to two weeks. If during this period necessary normative changes are required, the NEP will revert to Review. +Moderator, when moving a NEP to review stage, should update the Pull Request description to include the +review summary, example: + +```markdown +--- + +## NEP Status _(Updated by NEP moderators)_ + +SME reviews: + +- [ ] Role1: @github-handle +- [ ] Role2: @github-handle + +Contract Standards WG voting indications (❔ | :+1: | :-1: ): + +- ❔ @github-handle +- ❔ ... + + voting indications: + +- ❔ +- ❔ +``` + ### NEP Outcomes - **Approved:** If the working group votes to approve, they will move the NEP to Approved. Once approved, Standards NEPs exist in a state of finality and should only be updated to correct errata and add non-normative clarifications. @@ -84,25 +107,25 @@ The NEP process begins when an author submits a [NEP draft](#submit-a-nep-draft) ![author](https://user-images.githubusercontent.com/110252255/181816534-2f92b073-79e2-4e8d-b5b9-b10824958acd.png) **Author**
-*Anyone can participate* +_Anyone can participate_ The NEP author (or champion) is responsible for creating a NEP draft that follows the guidelines. They drive the NEP forward by actively participating in discussions and incorporating feedback. During the voting stage, they may present the NEP to the working group and community, and provide a final implementation with thorough testing and documentation once approved. ![Moderator](https://user-images.githubusercontent.com/110252255/181816650-b1610c0e-6d32-4d2a-a34e-877c702139bd.png) **Moderator**
-*Assigned by the working group* +_Assigned by the working group_ -The moderator is responsible for facilitating the process and validating that the NEP follows the guidelines. They do not assess the technical feasibility or write any part of the proposal. They provide comments if revisions are necessary and ensure that all roles are working together to progress the NEP forward. They also schedule and facilitate public voting calls. +The moderator is responsible for facilitating the process and validating that the NEP follows the guidelines. They do not assess the technical feasibility or write any part of the proposal. They provide comments if revisions are necessary and ensure that all roles are working together to progress the NEP forward. They also schedule and facilitate public voting calls. ![Reviewer](https://user-images.githubusercontent.com/110252255/181816664-a9485ea6-e774-4999-b11d-dc8be6b08f87.png) -**NEP Reviewer** (Subject Matter Experts)
-*Assigned by the working group* +**NEP Reviewer** (Subject Matter Experts)
+_Assigned by the working group_ The reviewer is responsible for reviewing the technical feasibility of a NEP and giving feedback to the author. While they do not have voting power, they play a critical role in providing their voting recommendations along with a summary of the benefits and concerns that were raised in the discussion. Their inputs help everyone involved make a transparent and informed decision. ![Approver](https://user-images.githubusercontent.com/110252255/181816752-521dd147-f56f-4c5c-84de-567b109f21d6.png) **Approver** (Working Groups)
-*Selected by the Dev Gov DAO in the bootstrapping phase* +_Selected by the Dev Gov DAO in the bootstrapping phase_ The working group is a selected committee of 3-7 recognized experts who are responsible for coordinating the public review and making decisions on a NEP in a fair and timely manner. There are multiple working groups, each one focusing on a specific ecosystem area, such as the Protocol or Wallet Standards. They assign reviewers to proposals, provide feedback to the author, and attend public calls to vote to approve or reject the NEP. Learn more about the various working groups at [neardevgov.org](http://neardevgov.org/). @@ -116,7 +139,6 @@ When a NEP gets to the final voting stage, the moderator will schedule a public All participants in the NEP process should maintain a professional and respectful code of conduct in all interactions. This includes communicating clearly and promptly and refraining from disrespectful or offensive language. - ### NEP Playbook 1. Once an author [submits a NEP draft](#submit-a-nep-draft), the NEP moderators will review their pull request (PR) for structure, formatting, and other errors. Approval criteria are: @@ -124,7 +146,7 @@ All participants in the NEP process should maintain a professional and respectfu - The title accurately reflects the content. - The language, spelling, grammar, sentence structure, and code style are correct and conformant. 2. If the NEP is not ready for approval, the moderators will send it back to the author with specific instructions in the PR. The moderators must complete the review within one week. -3. Once the moderators agree that the PR is ready for review, they will ask the approvers (working group members) to nominate a team of at least two reviewers (subject matter experts) to review the NEP. At least one working group member must explicitly tag the reviewers and comment: `"As a working group member, I'd like to nominate @SME-username and @SME-username as the Subject Matter Experts to review this NEP."` If the assigned reviewers feel that they lack the relevant expertise to fully review the NEP, they can ask the working group to re-assign the reviewers for the NEP. +3. Once the moderators agree that the PR is ready for review, they will ask the approvers (working group members) to nominate a team of at least two reviewers (subject matter experts) to review the NEP. At least one working group member must explicitly tag the reviewers and comment: `"As a working group member, I'd like to nominate @SME-username and @SME-username as the Subject Matter Experts to review this NEP."` If the assigned reviewers feel that they lack the relevant expertise to fully review the NEP, they can ask the working group to re-assign the reviewers for the NEP. 4. The reviewers must finish the technical review within one week. Technical Review Guidelines: - First, review the technical details of the proposals and assess their merit. If you have feedback, explicitly tag the author and comment: `"As the assigned Reviewer, I request from @author-username to [ask clarifying questions, request changes, or provide suggestions that are actionable.]."` It may take a couple of iterations to resolve any open comments. - Second, once the reviewer believes that the NEP is close to the voting stage, explicitly tag the @near/nep-moderators and comment with your technical summary. The Technical Summary must include: @@ -164,11 +186,11 @@ When referring to a NEP by number, it should be written in the hyphenated form N NEPs are encouraged to follow [RFC 2119](https://www.ietf.org/rfc/rfc2119.txt) for terminology and to insert the following at the beginning of the Specification section: -The keywords "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in [RFC 2119](https://www.ietf.org/rfc/rfc2119.txt). +The keywords "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in [RFC 2119](https://www.ietf.org/rfc/rfc2119.txt). ## NEP Maintenance -Generally, NEPs are not modifiable after reaching their final state. However, there are occasions when updating a NEP is necessary, such as when discovering a security vulnerability or identifying misalignment with a widely-used implementation. In such cases, an author may submit a NEP extension in a pull request with the proposed changes to an existing NEP document. +Generally, NEPs are not modifiable after reaching their final state. However, there are occasions when updating a NEP is necessary, such as when discovering a security vulnerability or identifying misalignment with a widely-used implementation. In such cases, an author may submit a NEP extension in a pull request with the proposed changes to an existing NEP document. A NEP extension has a higher chance of approval if it introduces clear benefits to existing implementors and does not introduce breaking changes. From 4015509d535136ffdea93631b47c858ac0fa55be Mon Sep 17 00:00:00 2001 From: Akhilesh Singhania Date: Wed, 17 May 2023 22:13:46 +0200 Subject: [PATCH 122/150] chore: fix some typos and grammar in FinancialTransaction.md (#482) --- .../Scenarios/FinancialTransaction.md | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/specs/RuntimeSpec/Scenarios/FinancialTransaction.md b/specs/RuntimeSpec/Scenarios/FinancialTransaction.md index 997c30f93..634f12b1c 100644 --- a/specs/RuntimeSpec/Scenarios/FinancialTransaction.md +++ b/specs/RuntimeSpec/Scenarios/FinancialTransaction.md @@ -50,17 +50,17 @@ succession) which should be strictly increasing with each transaction. Unlike in the entire accounts, so several users using the same account through different access keys need not to worry about accidentally reusing each other's nonces. -The block hash is used to calculate the transaction "freshness". It -is used to make sure the transaction does not get lost (let's say -somewhere in the network) and then arrive days, weeks or years later -when it is not longer relevant or would be undesirable to execute. -The transaction does not need to arrive at the specific block, instead -it is required to arrive within certain number of blocks from the bock +The block hash is used to calculate a transaction's "freshness". It +is used to make sure a transaction does not get lost (let's say +somewhere in the network) and then arrive days, weeks, or years later +when it is not longer relevant and would be undesirable to execute. +A transaction does not need to arrive at a specific block, instead +it is required to arrive within a certain number of blocks from the block identified by the `block_hash`. Any transaction arriving outside this threshold is considered to be invalid. Allowed delay is defined by -`transaction_validity_period` option in chain’s genesis file. On -mainnet the value is 86400 (which corresponds to roughly a day) while -on testnet it’s 100. +`transaction_validity_period` option in the chain’s genesis file. On +mainnet, this value is 86400 (which corresponds to roughly a day) and +on testnet it is 100. near-shell or other tool that Alice uses then signs this transaction, by: computing the hash of the transaction and signing it with the secret key, resulting in a `SignedTransaction` object. From ce3e46d31803a3478c7eaba5a6d0180f7b8d3814 Mon Sep 17 00:00:00 2001 From: amirsaran3 <95852708+amirsaran3@users.noreply.github.com> Date: Fri, 19 May 2023 21:46:50 +0200 Subject: [PATCH 123/150] NEP: Add support for signing in to more than one contract at once to Injected Wallet Standard (#428) --- specs/Standards/Wallets/InjectedWallets.md | 158 ++++++++++++++------- 1 file changed, 104 insertions(+), 54 deletions(-) diff --git a/specs/Standards/Wallets/InjectedWallets.md b/specs/Standards/Wallets/InjectedWallets.md index e591395c6..afd7f0fcb 100644 --- a/specs/Standards/Wallets/InjectedWallets.md +++ b/specs/Standards/Wallets/InjectedWallets.md @@ -29,18 +29,18 @@ Almost every wallet implementation in NEAR used a single account model until we ### Storage of key pairs for FunctionCall access keys in dApp context vs. wallet context -- NEAR's unique concept of `FunctionCall` access keys allow for the concept of 'signing in' to a dApp using your wallet. 'Signing In' to a dApp is accomplished by adding `FunctionCall` type access key that the dApp owns to the account that the user is logging in as. -- Once a user has 'signed in' to a dApp, the dApp can then use the keypair that it owns to execute transactions without having to prompt the user to route and approve those transactions through their wallet. -- `FunctionCall` access keys have a limited quota that can only be used to pay for gas fees (typically 0.25 NEAR) and can further be restricted to only be allowed to call *specific methods* on one **specific** smart contract. -- This allows for an ideal user experience for dApps that require small gas-only transactions regularly while in use. Those transactions can be done without interrupting the user experience by requiring them to be approved through their wallet. A great example of this is evident in gaming use-cases -- take a gaming dApp where some interactions the user makes must write to the blockchain as they do common actions in the game world. Without the 'sign in' concept that provides the dApp with its own limited usage key, the user might be constantly interrupted by needing to approve transactions on their wallet as they perform common actions. If a player has their account secured with a ledger, the gameplay experience would be constantly interrupted by prompts to approve transactions on their ledger device! With the 'sign in' concept, the user will only intermittently need to approve transactions to re-sign-in, when the quota that they approved for gas usage during their last login has been used up. +- NEAR's unique concept of `FunctionCall` access keys allow for the concept of 'signing in' to a dApp using your wallet. 'Signing In' to a dApp is accomplished by adding `FunctionCall` type access key that the dApp owns to the account that the user is logging in as. +- Once a user has 'signed in' to a dApp, the dApp can then use the keypair that it owns to execute transactions without having to prompt the user to route and approve those transactions through their wallet. +- `FunctionCall` access keys have a limited quota that can only be used to pay for gas fees (typically 0.25 NEAR) and can further be restricted to only be allowed to call _specific methods_ on one **specific** smart contract. +- This allows for an ideal user experience for dApps that require small gas-only transactions regularly while in use. Those transactions can be done without interrupting the user experience by requiring them to be approved through their wallet. A great example of this is evident in gaming use-cases -- take a gaming dApp where some interactions the user makes must write to the blockchain as they do common actions in the game world. Without the 'sign in' concept that provides the dApp with its own limited usage key, the user might be constantly interrupted by needing to approve transactions on their wallet as they perform common actions. If a player has their account secured with a ledger, the gameplay experience would be constantly interrupted by prompts to approve transactions on their ledger device! With the 'sign in' concept, the user will only intermittently need to approve transactions to re-sign-in, when the quota that they approved for gas usage during their last login has been used up. - Generally, it is recommended to only keep `FullAccess` keys in wallet scope and hidden from the dApp consumer. `FunctionCall` type keys should be generated and owned by the dApp, and requested to be added using the `signIn` method. They should **not** be 'hidden' inside the wallet in the way that `FullAccess` type keys are. ## Specification -Injected wallets are typically browser extensions that implement the `Wallet` API (see below). References to the currently available wallets are tracked on the `window` object. To avoid namespace collisions and easily detect when they're available, wallets must mount under their own key of the object `window.near` (e.g. `window.near.sender`). +Injected wallets are typically browser extensions that implement the `Wallet` API (see below). References to the currently available wallets are tracked on the `window` object. To avoid namespace collisions and easily detect when they're available, wallets must mount under their own key of the object `window.near` (e.g. `window.near.sender`). **NOTE: Do not replace the entire `window.near` object with your wallet implementation, or add any objects as properties of the `window.near` object that do not conform to the Injected Wallet Standard** -At the core of a wallet are [`signTransaction`](#signtransaction) and [`signTransactions`](#signtransactions). These methods, when given a [`TransactionOptions`](#Wallet-API) instance, will prompt the user to sign with a key pair previously imported (with the assumption it has [`FullAccess`](https://nomicon.io/DataStructures/AccessKey) permission). +At the core of a wallet are [`signTransaction`](#signtransaction) and [`signTransactions`](#signtransactions). These methods, when given a [`TransactionOptions`](#wallet-api) instance, will prompt the user to sign with a key pair previously imported (with the assumption it has [`FullAccess`](https://nomicon.io/DataStructures/AccessKey) permission). In most cases, a dApp will need a reference to an account and associated public key to construct a [`Transaction`](https://nomicon.io/RuntimeSpec/Transactions). The [`connect`](#connect) method helps solve this issue by prompting the user to select one or more accounts they would like to make visible to the dApp. When at least one account is visible, the wallet considers the dApp [`connected`](#connected) and they can access a list of [`accounts`](#accounts) containing an `accountId` and `publicKey`. @@ -65,7 +65,12 @@ interface Network { interface SignInParams { permission: transactions.FunctionCallPermission; - accounts: Array; + account: Account; +} + +interface SignInMultiParams { + permissions: Array; + account: Account; } interface SignOutParams { @@ -73,9 +78,9 @@ interface SignOutParams { } interface TransactionOptions { - receiverId: string; - actions: Array; - signerId?: string; + receiverId: string; + actions: Array; + signerId?: string; } interface SignTransactionParams { @@ -91,7 +96,7 @@ interface Events { } interface ConnectParams { - networkId: string; + networkId: string; } type Unsubscribe = () => void; @@ -105,9 +110,14 @@ interface Wallet { supportsNetwork(networkId: string): Promise; connect(params: ConnectParams): Promise>; signIn(params: SignInParams): Promise; + signInMulti(params: SignInMultiParams): Promise; signOut(params: SignOutParams): Promise; - signTransaction(params: SignTransactionParams): Promise; - signTransactions(params: SignTransactionsParams): Promise>; + signTransaction( + params: SignTransactionParams + ): Promise; + signTransactions( + params: SignTransactionsParams + ): Promise>; disconnect(): Promise; on( event: EventName, @@ -129,7 +139,7 @@ Retrieve the wallet's unique identifier. ```ts const { id } = window.near.wallet; -console.log(id) // "wallet" +console.log(id); // "wallet" ``` ##### `connected` @@ -139,7 +149,7 @@ Determine whether we're already connected to the wallet and have visibility of a ```ts const { connected } = window.near.wallet; -console.log(connected) // true +console.log(connected); // true ``` ##### `network` @@ -149,7 +159,7 @@ Retrieve the currently selected network. ```ts const { network } = window.near.wallet; -console.log(network) // { networkId: "testnet", nodeUrl: "https://rpc.testnet.near.org" } +console.log(network); // { networkId: "testnet", nodeUrl: "https://rpc.testnet.near.org" } ``` ##### `accounts` @@ -159,7 +169,7 @@ Retrieve all accounts visible to the dApp. ```ts const { accounts } = window.near.wallet; -console.log(accounts) // [{ accountId: "test.testnet", publicKey: PublicKey }] +console.log(accounts); // [{ accountId: "test.testnet", publicKey: PublicKey }] ``` #### Methods @@ -191,13 +201,15 @@ const signedTx = await window.near.wallet.signTransaction({ transaction: { signerId: accounts[0].accountId, receiverId: "guest-book.testnet", - actions: [transactions.functionCall( - "addMessage", - { text: "Hello World!" }, - utils.format.parseNearAmount("0.00000000003"), - utils.format.parseNearAmount("0.01") - )] - } + actions: [ + transactions.functionCall( + "addMessage", + { text: "Hello World!" }, + utils.format.parseNearAmount("0.00000000003"), + utils.format.parseNearAmount("0.01") + ), + ], + }, }); // Send the transaction to the blockchain. await provider.sendTransaction(signedTx); @@ -219,31 +231,35 @@ const provider = new providers.JsonRpcProvider({ url: network.nodeUrl }); const signedTxs = await window.near.wallet.signTransactions({ transactions: [ { - signerId: accounts[0].accountId, - receiverId: "guest-book.testnet", - actions: [transactions.functionCall( - "addMessage", - { text: "Hello World! (1/2)" }, - utils.format.parseNearAmount("0.00000000003"), - utils.format.parseNearAmount("0.01") - )] + signerId: accounts[0].accountId, + receiverId: "guest-book.testnet", + actions: [ + transactions.functionCall( + "addMessage", + { text: "Hello World! (1/2)" }, + utils.format.parseNearAmount("0.00000000003"), + utils.format.parseNearAmount("0.01") + ), + ], }, { - signerId: accounts[0].accountId, - receiverId: "guest-book.testnet", - actions: [transactions.functionCall( - "addMessage", - { text: "Hello World! (2/2)" }, - utils.format.parseNearAmount("0.00000000003"), - utils.format.parseNearAmount("0.01") - )] - } - ] -}); + signerId: accounts[0].accountId, + receiverId: "guest-book.testnet", + actions: [ + transactions.functionCall( + "addMessage", + { text: "Hello World! (2/2)" }, + utils.format.parseNearAmount("0.00000000003"), + utils.format.parseNearAmount("0.01") + ), + ], + }, + ], +}); for (let i = 0; i < signedTxs.length; i += 1) { const signedTx = signedTxs[i]; - + // Send the transaction to the blockchain. await provider.sendTransaction(signedTx); } @@ -259,7 +275,7 @@ await window.near.wallet.disconnect(); ##### `signIn` -Add `FunctionCall` access key(s) for one or more accounts. This request should require explicit approval from the user. +Add one `FunctionCall` access key for one or more accounts. This request should require explicit approval from the user. ```ts import { utils } from "near-api-js"; @@ -273,17 +289,51 @@ await window.near.wallet.signIn({ receiverId: "guest-book.testnet", methodNames: [], }, - accounts: accounts.map(({ accountId }) => { - const keyPair = utils.KeyPair.fromRandom("ed25519"); - - return { - accountId, - publicKey: keyPair.getPublicKey() - }; - }), + account: { + accountId: accounts[0].accountId, + publicKey: utils.KeyPair.fromRandom("ed25519").getPublicKey(), + }, }); ``` +##### `signInMulti` + +Add multiple `FunctionCall` access keys for one or more accounts. This request should require explicit approval from the user. + +```ts +import { utils } from "near-api-js"; + +// Retrieve the list of accounts we have visibility of. +const { accounts } = window.near.wallet; + +// Request FunctionCall access to the 'guest-book.testnet' and 'guest-book2.testnet' smart contract for each account. +await window.near.wallet.signInMulti({ + permissions: [ + { + receiverId: "guest-book.testnet", + methodNames: [], + }, + { + receiverId: "guest-book2.testnet", + methodNames: [], + }, + ], + account: { + accountId: accounts[0].accountId, + publicKey: utils.KeyPair.fromRandom("ed25519").getPublicKey(), + }, +}); +``` + +##### Benefits + +This NEP will optimize UX for multi contract DApps and avoid multiple redirects. These are more and more common in the ecosystem and this NEP will benefit the UX for those DApps. + +##### Concerns + +- The currently available keystores will have to catch up in order to support multiple keys per account +- We should add the new method to the Wallet interface for clarity in the NEP doc + ##### `signOut` Delete `FunctionCall` access key(s) for one or more accounts. This request should require explicit approval from the user. @@ -305,7 +355,7 @@ await window.near.wallet.signOut({ return { accountId, - publicKey: keyPair.getPublicKey() + publicKey: keyPair.getPublicKey(), }; }) ), From 4886221074103d82c421555379c56d5cc1f7567b Mon Sep 17 00:00:00 2001 From: Jakob Meier Date: Fri, 2 Jun 2023 18:06:39 +0200 Subject: [PATCH 124/150] update NEP-455: storage compute costs for v61 (#477) Tracks the newly introduced compute costs for protocol version 61 --- neps/nep-0455.md | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/neps/nep-0455.md b/neps/nep-0455.md index 062589530..9699f1458 100644 --- a/neps/nep-0455.md +++ b/neps/nep-0455.md @@ -231,6 +231,31 @@ This NEP was approved by Protocol Working Group members on March 16, 2023 ([meet - [Marcelo's vote](https://github.com/near/NEPs/pull/455#pullrequestreview-1340887413) - [Marcin's vote](https://github.com/near/NEPs/pull/455#issuecomment-1471882639) +### 1.0.1 - Storage Related Compute Costs + +Add five compute cost values for protocol version 61 and above. + +- wasm_touching_trie_node +- wasm_storage_write_base +- wasm_storage_remove_base +- wasm_storage_read_base +- wasm_storage_has_key_base + +For the exact values, please refer to the table at the bottom. + +The intention behind these increased compute costs is to address the issue of +storage accesses taking longer than the allocated gas costs, particularly in +cases where RocksDB, the underlying storage system, is too slow. These values +have been chosen to ensure that validators with recommended hardware can meet +the required timing constraints. +([Analysis Report](https://github.com/near/nearcore/issues/8006)) + +The protocol team at Pagoda is actively working on optimizing the nearcore +client storage implementation. This should eventually allow to lower the compute +costs parameters again. + +Progress on this work is tracked here: https://github.com/near/nearcore/issues/8938. + #### Benefits - Among the alternatives, this is the easiest to implement. @@ -250,3 +275,13 @@ Copyright and related rights waived via [CC0](https://creativecommons.org/public - https://gov.near.org/t/proposal-gas-weights-to-fight-instability-to-due-to-undercharging/30919 - https://github.com/near/nearcore/issues/8032 + +## Live Compute Costs Tracking + +Parameter Name | Compute / Gas factor | First version | Last version | Tracking issue | +-------------- | -------------------- | ------------- | ------------ | -------------- | +wasm_touching_trie_node | 6.83 | 61 | *TBD* | [nearcore#8938](https://github.com/near/nearcore/issues/8938) +wasm_storage_write_base | 3.12 | 61 | *TBD* | [nearcore#8938](https://github.com/near/nearcore/issues/8938) +wasm_storage_remove_base | 3.74 | 61 | *TBD* | [nearcore#8938](https://github.com/near/nearcore/issues/8938) +wasm_storage_read_base | 3.55 | 61 | *TBD* | [nearcore#8938](https://github.com/near/nearcore/issues/8938) +wasm_storage_has_key_base | 3.70 | 61 | *TBD* | [nearcore#8938](https://github.com/near/nearcore/issues/8938) From 2e0a9298168c5a87a2a818513c1f0c436e0d36bc Mon Sep 17 00:00:00 2001 From: Jakob Meier Date: Sun, 30 Jul 2023 16:57:47 +0200 Subject: [PATCH 125/150] fix: Remove reference to storage rent (#489) Storage rent has been superseded by storage staking a long time ago. This commit updates the account specification accordingly. --- specs/DataStructures/Account.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/specs/DataStructures/Account.md b/specs/DataStructures/Account.md index a8cc3c2e8..91b0c537e 100644 --- a/specs/DataStructures/Account.md +++ b/specs/DataStructures/Account.md @@ -151,7 +151,9 @@ Every account has its own storage. It's a persistent key-value trie. Keys are or The storage can only be modified by the contract on the account. Current implementation on Runtime only allows your account's contract to read from the storage, but this might change in the future and other accounts's contracts will be able to read from your storage. -NOTE: Accounts are charged recurrent rent for the total storage. This includes storage of the account itself, contract code, contract storage and all access keys. +NOTE: To pay for blockchain storage, the protocol locks a token amount per account proportional to its state size. +This includes storage of the account itself, contract code, contract storage and all access keys. +See [Storage Staking](https://docs.near.org/concepts/storage/storage-staking) in the docs. #### Access Keys From ccbd94d8a978e8249723e2f0f8a775997631a0f5 Mon Sep 17 00:00:00 2001 From: Jakob Meier Date: Fri, 4 Aug 2023 18:46:25 +0200 Subject: [PATCH 126/150] fix: replace dead link with wayback machine link (#494) The link to FT docs on figment.io is dead, let's replace it with an archived version of the site. Also includes the following linter fixes in Core.md; - remove extra indentation of lists - add blank lines around lists - replace emphasis with real headings --- neps/nep-0141.md | 2 +- specs/Standards/Tokens/FungibleToken/Core.md | 34 ++++++++++++-------- 2 files changed, 21 insertions(+), 15 deletions(-) diff --git a/neps/nep-0141.md b/neps/nep-0141.md index 2cec6e96c..bdc5d35fb 100644 --- a/neps/nep-0141.md +++ b/neps/nep-0141.md @@ -38,7 +38,7 @@ Prior art: Learn about NEP-141: -- [Figment Learning Pathway](https://learn.figment.io/tutorials/stake-fungible-token) +- [Figment Learning Pathway](https://web.archive.org/web/20220621055335/https://learn.figment.io/tutorials/stake-fungible-token) ## Specification diff --git a/specs/Standards/Tokens/FungibleToken/Core.md b/specs/Standards/Tokens/FungibleToken/Core.md index 736633c7a..3d44307cf 100644 --- a/specs/Standards/Tokens/FungibleToken/Core.md +++ b/specs/Standards/Tokens/FungibleToken/Core.md @@ -12,8 +12,9 @@ The [fungible token metadata standard](Metadata.md) provides the fields needed f ## Motivation NEAR Protocol uses an asynchronous, sharded runtime. This means the following: - - Storage for different contracts and accounts can be located on the different shards. - - Two contracts can be executed at the same time in different shards. + +- Storage for different contracts and accounts can be located on the different shards. +- Two contracts can be executed at the same time in different shards. While this increases the transaction throughput linearly with the number of shards, it also creates some challenges for cross-contract development. For example, if one contract wants to query some information from the state of another contract (e.g. current balance), by the time the first contract receives the balance the real balance can change. In such an async system, a contract can't rely on the state of another contract and assume it's not going to change. @@ -30,11 +31,12 @@ Prior art: Learn about NEP-141: -- [Figment Learning Pathway](https://learn.figment.io/tutorials/stake-fungible-token) +- [Figment Learning Pathway](https://web.archive.org/web/20220621055335/https://learn.figment.io/tutorials/stake-fungible-token) ## Guide-level explanation We should be able to do the following: + - Initialize contract once. The given total supply will be owned by the given account ID. - Get the total supply. - Transfer tokens to a new user. @@ -43,6 +45,7 @@ We should be able to do the following: - Remove state for the key/value pair corresponding with a user's account, withdrawing a nominal balance of Ⓝ that was used for storage. There are a few concepts in the scenarios above: + - **Total supply**: the total number of tokens in circulation. - **Balance owner**: an account ID that owns some amount of tokens. - **Balance**: an amount of tokens. @@ -60,7 +63,7 @@ Given that multiple users will use a Fungible Token contract, and their activity Alice wants to send 5 wBTC tokens to Bob. -**Assumptions** +##### Assumptions - The wBTC token contract is `wbtc`. - Alice's account is `alice`. @@ -68,11 +71,11 @@ Alice wants to send 5 wBTC tokens to Bob. - The precision ("decimals" in the metadata standard) on wBTC contract is `10^8`. - The 5 tokens is `5 * 10^8` or as a number is `500000000`. -**High-level explanation** +##### High-level explanation Alice needs to issue one transaction to wBTC contract to transfer 5 tokens (multiplied by precision) to Bob. -**Technical calls** +##### Technical calls 1. `alice` calls `wbtc::ft_transfer({"receiver_id": "bob", "amount": "500000000"})`. @@ -80,7 +83,7 @@ Alice needs to issue one transaction to wBTC contract to transfer 5 tokens (mult Alice wants to deposit 1000 DAI tokens to a compound interest contract to earn extra tokens. -**Assumptions** +##### Assumptions - The DAI token contract is `dai`. - Alice's account is `alice`. @@ -92,14 +95,15 @@ Alice wants to deposit 1000 DAI tokens to a compound interest contract to earn e
For this example, you may expand this section to see how a previous fungible token standard using escrows would deal with the scenario. -**High-level explanation** (NEP-21 standard) +##### High-level explanation (NEP-21 standard) Alice needs to issue 2 transactions. The first one to `dai` to set an allowance for `compound` to be able to withdraw tokens from `alice`. The second transaction is to the `compound` to start the deposit process. Compound will check that the DAI tokens are supported and will try to withdraw the desired amount of DAI from `alice`. + - If transfer succeeded, `compound` can increase local ownership for `alice` to 1000 DAI - If transfer fails, `compound` doesn't need to do anything in current example, but maybe can notify `alice` of unsuccessful transfer. -**Technical calls** (NEP-21 standard) +##### Technical calls (NEP-21 standard) 1. `alice` calls `dai::set_allowance({"escrow_account_id": "compound", "allowance": "1000000000000000000000"})`. 2. `alice` calls `compound::deposit({"token_contract": "dai", "amount": "1000000000000000000000"})`. During the `deposit` call, `compound` does the following: @@ -108,11 +112,11 @@ The second transaction is to the `compound` to start the deposit process. Compou
-**High-level explanation** +##### High-level explanation Alice needs to issue 1 transaction, as opposed to 2 with a typical escrow workflow. -**Technical calls** +##### Technical calls 1. `alice` calls `dai::ft_transfer_call({"receiver_id": "compound", "amount": "1000000000000000000000", "msg": "invest"})`. During the `ft_transfer_call` call, `dai` does the following: 1. makes async call `compound::ft_on_transfer({"sender_id": "alice", "amount": "1000000000000000000000", "msg": "invest"})`. @@ -124,7 +128,7 @@ Alice needs to issue 1 transaction, as opposed to 2 with a typical escrow workfl Alice wants to swap 5 wrapped NEAR (wNEAR) for BNNA tokens at current market rate, with less than 2% slippage. -**Assumptions** +##### Assumptions - The wNEAR token contract is `wnear`. - Alice's account is `alice`. @@ -133,7 +137,7 @@ Alice wants to swap 5 wrapped NEAR (wNEAR) for BNNA tokens at current market rat - The precision ("decimals" in the metadata standard) on wNEAR contract is `10^24`. - The 5 tokens is `5 * 10^24` or as a number is `5000000000000000000000000`. -**High-level explanation** +##### High-level explanation Alice needs to issue one transaction to wNEAR contract to transfer 5 tokens (multiplied by precision) to `amm`, specifying her desired action (swap), her destination token (BNNA) & maximum slippage (<2%) in `msg`. @@ -143,7 +147,7 @@ Alice needs to attach one yoctoNEAR. This will result in her seeing a confirmati Altogether then, Alice may take two steps, though the first may be a background detail of the app she uses. -**Technical calls** +##### Technical calls 1. View `amm::ft_data_to_msg({ action: "swap", destination_token: "bnna", max_slip: 2 })`. Using [NEAR CLI](https://docs.near.org/docs/tools/near-cli): @@ -179,6 +183,7 @@ Altogether then, Alice may take two steps, though the first may be a background ## Reference-level explanation **NOTES**: + - All amounts, balances and allowance are limited by `U128` (max value `2**128 - 1`). - Token standard uses JSON for serialization of arguments and results. - Amounts in arguments and results have are serialized as Base-10 strings, e.g. `"100"`. This is done to avoid JSON limitation of max integer value of `2**53`. @@ -322,6 +327,7 @@ function ft_resolve_transfer( ## History See also the discussions: + - [Fungible token core](https://github.com/near/NEPs/discussions/146#discussioncomment-298943) - [Fungible token metadata](https://github.com/near/NEPs/discussions/148) - [Storage standard](https://github.com/near/NEPs/discussions/145) From c781b791aa0c95f369142e208a7c2e54098d5537 Mon Sep 17 00:00:00 2001 From: Jakob Meier Date: Fri, 4 Aug 2023 18:47:00 +0200 Subject: [PATCH 127/150] fix: linter issues in specs/DataStructures/Account (#493) - remove unused link declarations - surround titles and code with blank lines - give fenced code a language (using c to format comments) --- specs/DataStructures/Account.md | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/specs/DataStructures/Account.md b/specs/DataStructures/Account.md index 91b0c537e..b01306bbf 100644 --- a/specs/DataStructures/Account.md +++ b/specs/DataStructures/Account.md @@ -2,8 +2,6 @@ ## Account ID -[account_id]: #account_id - NEAR Protocol has an account names system. Account ID is similar to a username. Account IDs have to follow the rules. ### Account ID Rules @@ -26,6 +24,7 @@ Regex for a full account ID, without checking for length: ```regex ^(([a-z\d]+[\-_])*[a-z\d]+\.)*([a-z\d]+[\-_])*[a-z\d]+$ ``` + ### Top Level Accounts | Name | Value | @@ -52,7 +51,7 @@ def action_create_account(predecessor_id, account_id): Valid accounts: -``` +```c ok bowen ek-2 @@ -73,7 +72,7 @@ bro.a Invalid accounts: -``` +```c not ok // Whitespace characters are not allowed a // Too short 100- // Suffix separator @@ -91,6 +90,7 @@ abcdefghijklmnopqrstuvwxyz.abcdefghijklmnopqrstuvwxyz.abcdefghijklmnopqrstuvwxyz ``` ## System account + `system` is a special account that is only used to identify refund receipts. For refund receipts, we set the predecessor_id to be `system` to indicate that it is a refund receipt. Users cannot create or access the `system` account. In fact, this account does not exist as part of the state. ## Implicit account IDs @@ -107,6 +107,7 @@ The corresponding secret key allows you to sign transactions on behalf of this a ### Implicit account creation An account with implicit account ID can only be created by sending a transaction/receipt with a single `Transfer` action to the implicit account ID receiver: + - The account will be created with the account ID. - The account will have a new full access key with the ED25519-curve public key of `decode_hex(account_id)` and nonce `0`. - The account balance will have a transfer balance deposited to it. @@ -117,8 +118,6 @@ Once an implicit account is created it acts as a regular account until it's dele ## Account -[account]: #account - Data for an single account is collocated in one shard. The account data consists of the following: - Balance From 4290e6f76f112b68fa6ffddef4a85a3841e76533 Mon Sep 17 00:00:00 2001 From: Jakob Meier Date: Fri, 4 Aug 2023 18:48:45 +0200 Subject: [PATCH 128/150] doc: add delegate action to actions specification (#495) closes #486 --- specs/RuntimeSpec/Actions.md | 151 ++++++++++++++++++++++++++++++++++- 1 file changed, 149 insertions(+), 2 deletions(-) diff --git a/specs/RuntimeSpec/Actions.md b/specs/RuntimeSpec/Actions.md index 7c5622533..1c8cd58dd 100644 --- a/specs/RuntimeSpec/Actions.md +++ b/specs/RuntimeSpec/Actions.md @@ -12,6 +12,7 @@ pub enum Action { AddKey(AddKeyAction), DeleteKey(DeleteKeyAction), DeleteAccount(DeleteAccountAction), + Delegate(SignedDelegateAction), } ``` @@ -20,6 +21,7 @@ converted to receipts when they are processed, we will mostly concern ourselves processing. For the following actions, `predecessor_id` and `receiver_id` are required to be equal: + - `DeployContract` - `Stake` - `AddKey` @@ -38,14 +40,17 @@ pub struct CreateAccountAction {} If `receiver_id` has length == 64, this account id is considered to be `hex(public_key)`, meaning creation of account only succeeds if followed up with `AddKey(public_key)` action. **Outcome**: + - creates an account with `id` = `receiver_id` - sets Account `storage_usage` to `account_cost` (genesis config) ### Errors **Execution Error**: + - If the action tries to create a top level account whose length is no greater than 32 characters, and `predecessor_id` is not `registrar_account_id`, which is defined by the protocol, the following error will be returned + ```rust /// A top-level account ID can only be created by registrar. CreateAccountOnlyByRegistrar { @@ -57,6 +62,7 @@ CreateAccountOnlyByRegistrar { - If the action tries to create an account that is neither a top-level account or a subaccount of `predecessor_id`, the following error will be returned + ```rust /// A newly created account must be under a namespace of the creator account CreateAccountNotAllowed { account_id: AccountId, predecessor_id: AccountId }, @@ -71,18 +77,22 @@ pub struct DeployContractAction { ``` **Outcome**: + - sets the contract code for account ### Errors **Validation Error**: + - if the length of `code` exceeds `max_contract_size`, which is a genesis parameter, the following error will be returned: + ```rust /// The size of the contract code exceeded the limit in a DeployContract action. ContractSizeExceeded { size: u64, limit: u64 }, ``` **Execution Error**: + - If state or storage is corrupted, it may return `StorageError`. ## FunctionCallAction @@ -112,11 +122,13 @@ pub struct TransferAction { ``` **Outcome**: + - transfers amount specified in `deposit` from `predecessor_id` to a `receiver_id` account ### Errors **Execution Error**: + - If the deposit amount plus the existing amount on the receiver account exceeds `u128::MAX`, a `StorageInconsistentState("Account balance integer overflow")` error will be returned. @@ -132,26 +144,32 @@ pub struct StakeAction { ``` **Outcome**: + - A validator proposal that contains the staking public key and the staking amount is generated and will be included in the next block. ### Errors **Validation Error**: + - If the `public_key` is not an ristretto compatible ed25519 key, the following error will be returned: + ```rust /// An attempt to stake with a public key that is not convertible to ristretto. UnsuitableStakingKey { public_key: PublicKey }, ``` **Execution Error**: + - If an account has not staked but it tries to unstake, the following error will be returned: + ```rust /// Account is not yet staked, but tries to unstake TriesToUnstake { account_id: AccountId }, ``` - If an account tries to stake more than the amount of tokens it has, the following error will be returned: + ```rust /// The account doesn't have enough balance to increase the stake. TriesToStake { @@ -163,6 +181,7 @@ TriesToStake { ``` - If the staked amount is below the minimum stake threshold, the following error will be returned: + ```rust InsufficientStake { account_id: AccountId, @@ -170,6 +189,7 @@ InsufficientStake { minimum_stake: Balance, } ``` + The minimum stake is determined by `last_epoch_seat_price / minimum_stake_divisor` where `last_epoch_seat_price` is the seat price determined at the end of last epoch and `minimum_stake_divisor` is a genesis config parameter and its current value is 10. @@ -184,14 +204,17 @@ pub struct AddKeyAction { ``` **Outcome**: + - Adds a new [AccessKey](/DataStructures/AccessKey.md) to the receiver's account and associates it with a `public_key` provided. -### Errors: +### Errors **Validation Error**: If the access key is of type `FunctionCallPermission`, the following errors can happen + - If `receiver_id` in `access_key` is not a valid account id, the following error will be returned + ```rust /// Invalid account ID. InvalidAccountId { account_id: AccountId }, @@ -199,6 +222,7 @@ InvalidAccountId { account_id: AccountId }, - If the length of some method name exceed `max_length_method_name`, which is a genesis parameter (current value is 256), the following error will be returned + ```rust /// The length of some method name exceeded the limit in a Add Key action. AddKeyMethodNameLengthExceeded { length: u64, limit: u64 }, @@ -206,17 +230,21 @@ AddKeyMethodNameLengthExceeded { length: u64, limit: u64 }, - If the sum of length of method names (with 1 extra character for every method name) exceeds `max_number_bytes_method_names`, which is a genesis parameter (current value is 2000), the following error will be returned + ```rust /// The total number of bytes of the method names exceeded the limit in a Add Key action. AddKeyMethodNamesNumberOfBytesExceeded { total_number_of_bytes: u64, limit: u64 } ``` **Execution Error**: + - If an account tries to add an access key with a given public key, but an existing access key with this public key already exists, the following error will be returned + ```rust /// The public key is already used for an existing access key AddKeyAlreadyExists { account_id: AccountId, public_key: PublicKey } ``` + - If state or storage is corrupted, a `StorageError` will be returned. ## DeleteKeyAction @@ -228,6 +256,7 @@ pub struct DeleteKeyAction { ``` **Outcome**: + - Deletes the [AccessKey](/DataStructures/AccessKey.md) associated with `public_key`. ### Errors @@ -235,10 +264,12 @@ pub struct DeleteKeyAction { **Execution Error**: - When an account tries to delete an access key that doesn't exist, the following error is returned + ```rust /// Account tries to remove an access key that doesn't exist DeleteKeyDoesNotExist { account_id: AccountId, public_key: PublicKey } ``` + - `StorageError` is returned if state or storage is corrupted. ## DeleteAccountAction @@ -251,28 +282,144 @@ pub struct DeleteAccountAction { ``` **Outcomes**: + - The account, as well as all the data stored under the account, is deleted and the tokens are transferred to `beneficiary_id`. ### Errors -**Validation Error** +**Validation Error**: + - If `beneficiary_id` is not a valid account id, the following error will be returned + ```rust /// Invalid account ID. InvalidAccountId { account_id: AccountId }, ``` - If this action is not the last action in the action list of a receipt, the following error will be returned + ```rust /// The delete action must be a final action in transaction DeleteActionMustBeFinal ``` - If the account still has locked balance due to staking, the following error will be returned + ```rust /// Account is staking and can not be deleted DeleteAccountStaking { account_id: AccountId } ``` **Execution Error**: + - If state or storage is corrupted, a `StorageError` is returned. + +## Delegate Actions + +Introduced with [NEP-366](https://github.com/near/NEPs/blob/master/neps/nep-0366.md) to enable meta transactions. + +In summary, a delegate action is an indirect submission of a transaction. +It allows a relayer to do the payment (gas and token costs) for a transaction authored by a user. + +```rust +/// The struct contained in transactions and receipts, inside `Action::Delegate(_)``. +struct SignedDelegateAction { + /// The actual action, see below. + pub delegate_action: DelegateAction, + /// NEP-483 proposal compliant signature + pub signature: Signature, +} +``` + +Note that the signature follows a scheme which is proposed to be standardized in [NEP-483](https://github.com/near/NEPs/pull/483). + + +```rust +/// The struct a user creates and signs to create a meta transaction. +struct DelegateAction { + /// Signer of the delegated actions + pub sender_id: AccountId, + /// Receiver of the delegated actions. + pub receiver_id: AccountId, + /// List of actions to be executed. + /// + /// With the meta transactions MVP defined in NEP-366, nested + /// DelegateActions are not allowed. A separate type is used to enforce it. + pub actions: Vec, + /// Nonce to ensure that the same delegate action is not sent twice by a + /// relayer and should match for given account's `public_key`. + /// After this action is processed it will increment. + pub nonce: Nonce, + /// The maximal height of the block in the blockchain below which the given DelegateAction is valid. + pub max_block_height: BlockHeight, + /// Public key used to sign this delegated action. + pub public_key: PublicKey, +} +``` + +### Outcomes + +- All actions inside `delegate_action.actions` are submitted with the `delegate_action.sender_id` as the predecessor, `delegate_action.receiver_id` as the receiver, and the relayer (predecessor of `DelegateAction`) as the signer. +- All gas and balance costs for submitting `delegate_action.actions` are subtracted from the relayer. + +### Errors + +**Validation Error**: + +- If the list of Transaction actions contains several `DelegateAction` + +```rust +/// There should be the only one DelegateAction +DelegateActionMustBeOnlyOne +``` + +**Execution Error**: + +- If the Sender's account doesn't exist + +```rust +/// Happens when TX receiver_id doesn't exist +AccountDoesNotExist +``` + +- If the `signature` does not match the data and the `public_key` of the given key, then the following error will be returned + +```rust +/// Signature does not match the provided actions and given signer public key. +DelegateActionInvalidSignature +``` + +- If the `sender_id` doesn't match the `tx.receiver_id` + +```rust +/// Receiver of the transaction doesn't match Sender of the delegate action +DelegateActionSenderDoesNotMatchTxReceiver +``` + +- If the current block is equal or greater than `max_block_height` + +```rust +/// Delegate action has expired +DelegateActionExpired +``` + +- If the `public_key` does not exist for Sender account + +```rust +/// The given public key doesn't exist for Sender account +DelegateActionAccessKeyError +``` + +- If the `nonce` does match the `public_key` for the `sender_id` + +```rust +/// Nonce must be greater sender[public_key].nonce +DelegateActionInvalidNonce +``` + +- If `nonce` is too large + +```rust +/// DelegateAction nonce is larger than the upper bound given by the block height (block_height * 1e6) +DelegateActionNonceTooLarge +``` From 9cb94e0cc98f76549e6e814f008d9c4793135078 Mon Sep 17 00:00:00 2001 From: Jakob Meier Date: Fri, 4 Aug 2023 18:52:57 +0200 Subject: [PATCH 129/150] fix: inaccuracies in delegate action errors (#496) While updating the specs for delegate actions, I noticed that there are two small mistakes in the error description of the NEP. Or I guess it would be more accurate to say the nearcore implementation is not compliant with the NEP. 1) `DelegateActionCantContainNestedOne` is impossible to happen because the chosen serialization format does not allow nesting in the first place. 2) The name for `DelegateActionSenderDoesNotMatchReceiver` somehow managed to get even longer in the real implementation and now spells `DelegateActionSenderDoesNotMatchTxReceiver` I know this isn't ideal. But since this is now de-facto part of the protocol, I suggest we update the NEP to reflect it. Alternatively, we could change it in nearcore. This would be a breaking change in some primitives crates, so I tend towards the first option. --- neps/nep-0366.md | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/neps/nep-0366.md b/neps/nep-0366.md index e419c9851..5aada7b0a 100644 --- a/neps/nep-0366.md +++ b/neps/nep-0366.md @@ -3,10 +3,12 @@ NEP: 366 Title: Meta Transactions Author: Illia Polosukhin , Egor Uleyskiy (egor.ulieiskii@gmail.com), Alexander Fadeev (fadeevab.com@gmail.com) DiscussionsTo: https://github.com/nearprotocol/neps/pull/366 -Status: Draft +Status: Approved Type: Protocol Track Category: Runtime +Version: 1.1.0 Created: 19-Oct-2022 +LastUpdated: 03-Aug-2023 --- ## Summary @@ -149,7 +151,7 @@ DelegateActionInvalidSignature ```rust /// Receiver of the transaction doesn't match Sender of the delegate action -DelegateActionSenderDoesNotMatchReceiver +DelegateActionSenderDoesNotMatchTxReceiver ``` - If the current block is equal or greater than `max_block_height` @@ -180,13 +182,6 @@ DelegateActionInvalidNonce DelegateActionNonceTooLarge ``` -- If the list of delegated actions contains another `DelegateAction` - -```rust -/// DelegateAction actions contain another DelegateAction -DelegateActionCantContainNestedOne -``` - - If the list of Transaction actions contains several `DelegateAction` ```rust @@ -214,6 +209,13 @@ See the **_Validation_** section in [DelegateAction specification](/specs/Runtim Supporting ZK proofs instead of just signatures can allow for anonymous transactions, which pay fees to relayers anonymously. +## Changelog + +### 1.1.0 - Adjust errors to reflect deployed reality (03-Aug`2023) + +- Remove the error variant `DelegateActionCantContainNestedOne` because this would already fail in the parsing stage. +- Rename the error variant `DelegateActionSenderDoesNotMatchReceiver` to `DelegateActionSenderDoesNotMatchTxReceiver` to reflect published types in [near_primitives](https://docs.rs/near-primitives/0.17.0/near_primitives/errors/enum.ActionErrorKind.html#variant.DelegateActionSenderDoesNotMatchTxReceiver). + ## Copyright Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). From 3786d9b7e1c057b53b8a66fdd3f30880a2aa2695 Mon Sep 17 00:00:00 2001 From: Robert Zaremba Date: Tue, 12 Sep 2023 18:03:40 +0200 Subject: [PATCH 130/150] feat: adding soulbound token (#393) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Soulbound Tokens (SBT) are non transferrable NFTs. Even though tranferability is not available, we define a recoverability mechanism. SBTs are well suited of carrying proof-of-attendence NFTs, proof-of-unique-human "stamps" and other similar credibility-carriers. --- ## NEP Status *(Updated by NEP moderators)* SME reviews: * [x] @KazanderDad (NDC GWG): https://github.com/near/NEPs/pull/393#pullrequestreview-1380240545 * [x] @alexastrum (Tenamint): https://github.com/near/NEPs/pull/393/#issuecomment-1541004902 Contract Standards WG voting indications (❔ | 👍 | :-1: ): * 👍 @frol: https://github.com/near/NEPs/pull/393#pullrequestreview-1499578010 * 👍 @fadeevab: https://github.com/near/NEPs/pull/393#pullrequestreview-1506223006 * -- @robert-zaremba (can't vote myself) Wallet Standards WG voting indications: * ❔ @Cameron-Banyan * ❔ @MaximusHaximus * ❔ @esaminu ## Concerns | # | Concern | Resolution | Status | | --- | --- | -- | -- | | 1 | [Rober] Should we Emit NEP-171 Mint and NEP-171 Burn by the SBT contract (in addition to SBT native events emitted by the registry)? If the events will be emitted by registry, then we need new events to include the contract address. | [Robert] Don't emit NFT events. SBT is not NFT. Support: @alexastrum | open | | 2 | [Robert] remove `memo` in events. The `memo` is already part of the transaction, and should not be needed to identify transactions. Processes looking for events, can easily track transaction through event and recover `memo` if needed. | currently removed, consequently also removed from registry transactions . Support: @alexastrum | open | | 3 | [Token Spam](https://github.com/near/NEPs/pull/393/#discussion_r1163938750) | [Robert]: we have a `Burn` event. Added example `sbt_burn` function, but keeping it not as a part of required interface. Event should be enough. | open | | 4 | [Multiple registries](https://github.com/near/NEPs/pull/393/#discussion_r1163951624). Registry source of truth [comment](https://github.com/near/NEPs/pull/393/#issuecomment-1531766643) | Robert: this is a part of the design: permissionless approach. [Justification for registry](https://github.com/near/NEPs/pull/393/#issuecomment-1540621077) | open | | 5 | [Robert] Approve the proposed multi-token | Support: @alexastrum | open | | 6 | [Robert] Use of milliseconds as a time unit. | [Robert] Currently the standard uses milliseconds. | open | | 7 | Should a `burn` function be part of a standard or a recommendation? | [Robert] We already have the Burn event. IMHO a function should not be part of the standard inteface (similarly to FT and NFT). | open | | 8 | [Robert] Don't include `sbt_soul_transfer` in the standard interface, [comment](https://github.com/near/NEPs/pull/393#issuecomment-1506969996). | [Robert] moving outside of the required interface. | open | | 9 | [Privacy](https://github.com/near/NEPs/pull/393/#issuecomment-1504309947) | [Robert] Concerns have been addressed: [comment-1](https://github.com/near/NEPs/pull/393/#issuecomment-1504485420) and [comment2](https://github.com/near/NEPs/pull/393/#issuecomment-1505958549) | open | | 10 | x | resolution | open | --------- Co-authored-by: Vlad Frolov --- neps/nep-0393.md | 665 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 665 insertions(+) create mode 100644 neps/nep-0393.md diff --git a/neps/nep-0393.md b/neps/nep-0393.md new file mode 100644 index 000000000..67b3361c2 --- /dev/null +++ b/neps/nep-0393.md @@ -0,0 +1,665 @@ +--- +NEP: 393 +Title: Soulbound Token +Authors: Robert Zaremba <@robert-zaremba> +DiscussionsTo: +Status: Approved +Type: Standards Track +Category: Contract +Created: 12-Sep-2022 +Requires: +--- + +# NEP: Soulbound Token + +## Summary + +Soulbound Token (SBT) is a form of a non-fungible token which represents an aspect of an account: _soul_. [Transferability](#transferability) is limited only to a case of recoverability or a _soul transfer_. The latter must coordinate with a registry to transfer all SBTs from one account to another, and _banning_ the source account. + +SBTs are well suited for carrying proof-of-attendance, proof-of-unique-human "stamps" and other similar credibility-carriers. + +## Motivation + +Recent [Decentralized Society](https://www.bankless.com/decentralized-society-desoc-explained) trends open a new area of Web3 research to model various aspects of what characterizes humans. Economic and governance value is generated by humans and their relationship. SBTs can represent the commitments, credentials, and affiliations of “Souls” that encode the trust networks of the real economy to establish provenance and reputation. + +> More importantly, SBTs enable other applications of increasing ambition, such as community wallet recovery, Sybil-resistant governance, mechanisms for decentralization, and novel markets with decomposable, shared rights. We call this richer, pluralistic ecosystem “Decentralized Society” (DeSoc)—a co-determined sociality, where Souls and communities come together bottom-up, as emergent properties of each other to co-create plural network goods and intelligences, at a range of scales. + +Creating strong primitives is necessary to model new innovative systems and decentralized societies. Examples include reputation protocols, non-transferrable certificates, non-transferrable rights, undercollateralized lending, proof-of-personhood, proof-of-attendance, proof-of-skill, one-person-one-vote, fair airdrops & ICOs, universal basic income, non KYC identity systems, Human DAOs and methods for Sybil attack resistance. + +We propose an SBT standard to model protocols described above. + +_Verifiable Credentials_ (VC) could be seen as subset of SBT. However there is an important distinction: VC require set of claims and privacy protocols. It would make more sense to model VC with relation to W3 DID standard. SBT is different, it doesn't require a [resolver](https://www.w3.org/TR/did-core/#dfn-did-resolvers) nor [method](https://www.w3.org/TR/did-core/#dfn-did-methods) registry. For SBT, we need something more elastic than VC. + +## Specification + +Main requirement for Soulbound tokens is to bound an account to a human. A **Soul** is an account with SBTs, which are used to define account identity. +Often non transferrable NFT (an NFT token with a no-op transfer function) is used to implement SBTs. However, such model is rather shortsighted. Transferability is required to allow users to either recover their SBTs or merge between the accounts they own. At the same time, we need to limit transferability to assure that an SBTs is kept bound to the same _soul_. +We also need an efficient on way to make composed ownership queries (for example: check if an account owns SBT of class C1, C2 and C3 issued by issuer I1, I2 and I3 respectively) - this is needed to model emergent properties discussed above. + +We introduce a **soul transfer**: an ability for user to move ALL SBT tokens from one account to another in a [semi atomic](#soul-transfer) way, while keeping the SBT bounded to the same _soul_. This happens when a user needs to merge his accounts (e.g. they started with a few different accounts but later decides to merge them to increase an account reputation). Soul transfer is different than a token transfer. The standard forbids a traditional token transfer functionality, where a user can transfer individual tokens. That being said, a registry can have extension functions for more advanced scenarios, which could require a governance approval. + +SBT standard separates the token issuer concept from the token registry in order to meet the requirements listed above. +In the following sections we discuss the functionality of an issuer and registry. + +### SBT Registry + +Traditional Token model in NEAR blockchain assumes that each token has it's own balance book and implements the authorization and issuance mechanism in the same smart contract. Such model prevents atomic _soul transfer_ in the current NEAR runtime. When token balance is kept separately in each SBT smart contract, synchronizing transfer calls to all such contracts to assure atomicity is not possible at scale. We need an additional contract, the `SBT Registry`, to provide atomic transfer of all user SBTs and efficient way to ban accounts in relation to the Ban event discussed below. +This, and efficient cross-issuer queries are the main reasons SBT standards separates that token registry and token issuance concerns. + +Issuer is an entity which issues new tokens and potentially can update the tokens (for example execute renewal). All standard modification options are discussed in the sections below. + +Registry is a smart contract, where issuers register the tokens. Registry provides a balance book of all associated SBTs. Registry must ensure that each issuer has it's own "sandbox" and issuers won't overwrite each other. A registry provides an efficient way to query multiple tokens for a single user. This will allow implementation of use cases such us: + +- SBT based identities (main use case of the `i-am-human` protocol); +- SBT classes; +- decentralized societies. + +```mermaid +graph TB + Issuer1--uses--> Registry + Issuer2--uses--> Registry + Issuer3--uses--> Registry +``` + +We can have multiple competing registries (with different purpose or different management scheme). An SBT issuer SHOULD opt-in to a registry before being able to use registry. Registries may develop different opt-in mechanisms (they could differ by the approval mechanism, be fully permissioned etc..). One SBT smart contract can opt-in to: + +- many registries: it MUST relay all state change functions to all registries. +- or to no registry. We should think about it as a single token registry, and it MUST strictly implement all SBT Registry query functions by itself. The contract address must be part of the arguments, and it must check that it equals to the deployed account address (`require!(ctr == env::current_account_id())`). It also MUST emit related events by itself. + +We recommend that each issuer will use only one registry to avoid complex reconciliation and assure single source of truth. + +The registry fills a central and important role. But it is **not centralized**, as anyone can create their own registry and SBT issuers can choose which registry to use. It's also not too powerful, as almost all of the power (mint, revoke, burn, recover, etc) still remains with the SBT issuer and not with the registry. + +#### Issuer authorization + +A registry can limit which issuers can use registry to mint SBTs by implementing a custom issuer whitelist methods (for example simple access control list managed by a DAO) or keep it fully open (allowing any issuer minting withing the registry). + +Example: an `SBT_1 Issuer` wants to mint tokens using the `SBT_Registry`. The `SBT_Registry` has a DAO which votes on adding a new issuer: + +```mermaid +sequenceDiagram + actor Issuer1 as SBT_1 Issuer + actor DAO + + participant SBT_Registry + + Note over Issuer1,DAO: Issuer1 connects with the DAO
to be whitelisted. + + Issuer1-->>DAO: request whitelist + DAO->>SBT_Registry: whitelist(SBT_1 Issuer) +``` + +#### Personal Identifiable Information + +Issuers must not include any PII into any SBT. + +### Account Ban + +`Ban` is an event emitted by a registry signaling that the account is banned, and can't own any SBT. Registry must return zero for every SBT supply query of a banned account. Operations which trigger soul transfer must emit Ban. + +A registry can emit a `Ban` for use cases not discussed in this standard. Handling it depends on the registry governance. One example is to use social governance to identify fake accounts (like bots) - in that case the registry should allow to emit `Ban` and block a scam soul and block future transfers. +NOTE: an SBT Issuer can have it's own list of blocked accounts or allowed only accounts. + +### Minting + +Minting is done by issuer calling `registry.sbt_mint(tokens_to_mint)` method. Standard doesn't specify how a registry authorizes an issuer. A classical approach is a whitelist of issuers: any whitelisted issuer can mint any amount of new tokens. Registry must keep the balances and assign token IDs to newly minted tokens. + +Example: Alice has two accounts: `alice1` and `alice2` which she used to mint tokens. She is getting tokens from 2 issuers that use the same registry. Alice uses her `alice1` account to interact with `SBT_1 Issuer` and receives an SBT with token ID = 238: + +```mermaid +sequenceDiagram + actor Alice + actor Issuer1 as SBT_1 Issuer + + participant SBT1 as SBT_1 Contract + participant SBT_Registry + + Issuer1->>SBT1: sbt_mint(alice1, metadata) + activate SBT1 + SBT1-)SBT_Registry: sbt_mint([[alice1, [metadata]]]) + SBT_Registry->>SBT_Registry: emit Mint(SBT_1_Contract, alice1, [238]) + SBT_Registry-)SBT1: [238] + deactivate SBT1 + + Note over Alice,SBT_Registry: now Alice can query registry to check her SBT + + Alice-->>SBT_Registry: sbt(SBT_1_Contract, 238) + SBT_Registry-->>Alice: {token: 238, owner: alice1, metadata} +``` + +With `SBT_2 Issuer`, Alice uses her `alice2` account. Note that `SBT_2 Contract` has different mint function (can mint many tokens at once), and validates a proof prior to requesting the registry to mint the tokens. + +```mermaid +sequenceDiagram + actor Alice + actor Issuer2 as SBT_2 Issuer + + participant SBT2 as SBT_2 Contract + participant SBT_Registry + + Issuer2->>SBT2: sbt_mint_multi([[alice2, metadata2], [alice2, metadata3]], proof) + activate SBT2 + SBT2-)SBT_Registry: sbt_mint([[alice2, [metadata2, metadata3]]]) + SBT_Registry->>SBT_Registry: emit Mint(SBT_2_Contract, alice2, [7991, 7992]) + SBT_Registry-)SBT2: [7991, 1992] + deactivate SBT2 + + Note over Alice,SBT_Registry: Alice queries one of her new tokens + Alice-->>SBT_Registry: sbt(SBT_2_Contract, 7991) + SBT_Registry-->>Alice: {token: 7991, owner: alice2, metadata: metadata2} +``` + +### Transferability + +Safeguards are set against misuse of SBT transfer and keep the _soul bound_ property. SBT transfer from one account to another should be strictly limited to: + +- **revocation** allows issuer to invalidate or burn an SBT in case a token issuance should be reverted (for example the recipient is a Sybil account, that is an account controlled by an entity trying to create the false appearance); +- **recoverability** in case a user's private key is compromised due to extortion, loss, etc. Users cannot recover an SBT only by themselves. Users must connect with issuer to request recoverability or use more advanced mechanism (like social recoverability). The recovery function provides additional economical cost preventing account trading: user should always be able to recover his SBT, and move to another, not banned account. +- **soul transfer** - moving all SBT tokens from a source account (issued by all issuers) to a destination account. During such transfer, SBT registry emits `SoulTransfer` and `Ban` events. The latter signals that the account can't host nor receive any SBT in the future, effectively burning the identity of the source account. This creates an inherit cost for the source account: it's identity can't be used any more. Registry can have extension functions for more advanced scenarios, which could require a governance mechanism. `SoulTransfer` event can also trigger similar actions in other registries (specification for this is out of the scope of this NEP). + +This becomes especially important for proof-of-human stamps that can only be issued once per user. + +#### Revocation + +An issuer can revoke SBTs by calling `registry.sbt_revoke(tokens_to_revoke, burn)`. Example: when a related certificate or membership should be revoked, when an issuer finds out that there was an abuse or a scam, etc...). Registry, when receiving `sbt_revoke` request from an issuer must always emit the `Revoke` event. Registry must only accept revoke requests from a valid issuer, and only revoke tokens from that issuer. If `burn=true` is set in the request, then the token should be burned and `Burn` event must be emitted. Otherwise (when `burn=false`) the registry must update token metadata and set expire date to a time in the past. Registry must not ban nor emit `Ban` event when revoking a contract. That would create an attack vector, when a malicious registry would thread the registry by banning accounts. + +#### Recoverability + +Standard defines issuer recoverability. At minimum, the standard registry exposes `sbt_recover` method, which allows issuer to reassign a token issued by him from one account to another. + +SBT recovery MUST not trigger `SoulTransfer` nor `Ban` event: malicious issuer could compromise the system by faking the token recovery and take over all other SBTs from a user. Only the owner of the account can make a Soul Transfer transaction and merge 2 accounts they owns. + +#### Recoverability within an SBT Registry + +SBT registry can define it's own mechanism to atomically recover all tokens related to one account and execute soul transfer to another account, without going one by one through each SBT issuer (sometimes that might be even not possible). Below we list few ideas a Registry can use to implement recovery: + +- KYC based recovery +- Social recovery + +![Social Recovery, Image via “Decentralized Society”](https://bankless.ghost.io/content/images/public/images/cdb1fc23-6179-44f0-9bfe-e5e5831492f7_1399x680.png) + +SBT Registry based recovery is not part of this specification. + +#### Soul Transfer + +The basic use case is described above. Registry MUST provide a permissionless method to allow any user to execute soul transfer. It is essential part of the standard, but the exact interface of the method is not part of the standard, because registries may adopt different mechanism and require different arguments. + +Soul transfers must be _semi atomic_. That is, the holder account must be non operational (in terms of SBT supply) until the soul transfer is completed. Given the nature of NEAR blockchain, where transactions are limited by gas, big registries may require to implement the Soul Transfer operation in stages. Source and destination accounts should act as a non-soul accounts while the soul transfer operation is ongoing. For example, in the first call, contract can lock the account, and do maximum X amount of transfers. If the list of to be transferred SBTs has not been exhausted, the contract should keep locking the account and remember the last transferred SBT. Subsequent calls by the same user will resume the operation until the list is exhausted. +Soul Transfer must emit the `SoulTransfer` event. + +Example: Alice has two accounts: `alice1` and `alice2` which she used to mint tokens (see [mint diagram](#minting)). She decides to merge the accounts by doing Soul Transfer. + +```mermaid +sequenceDiagram + actor Alice + participant SBT_Registry + + Alice->>SBT_Registry: sbt_soul_transfer(alice1) --accountId alice2 + + Alice-->>+SBT_Registry: sbt_tokens_by_owner(alice2) + SBT_Registry-->>-Alice: [] + + Alice-->>+SBT_Registry: sbt_tokens_by_owner(alice1) + SBT_Registry-->>-Alice: [[SBT_1_Contract, [238]], [SBT_2_Contract, [7991, 7992]]]} +``` + +Implementation Notes: + +- There is a risk of conflict. The standard requires that one account can't have more than one SBT of the same (issuer, class) pair. +- When both `alice1` and `alice2` have SBT of the same (issuer, class) pair, then the transfer should fail. One of the accounts should burn conflicting tokens to be able to continue the soul transfer. +- Soul transfer may require extra confirmation before executing a transfer. For example, if `alice1` wants to do a soul transfer to `alice2`, the contract my require `alice2` approval before continuing the transfer. +- Other techniques may be used to enforce that the source account will be deleted. + +### Renewal + +Soulbound tokens can have an _expire date_. It is useful for tokens which are related to real world certificates with expire time, or social mechanisms (e.g. community membership). Such tokens SHOULD have an option to be renewable. Examples include mandatory renewal with a frequency to check that the owner is still alive, or renew membership to a DAO that uses SBTs as membership gating. +Registry defines `sbt_renew` method allowing issuers to update the token expire date. The issuer can set a the _expire date_ in the past. This is useful if an issuer wants to invalidate the token without removing it. + +### Burning tokens + +Registry MAY expose a mechanism to allow an account to burn an unwanted token. The exact mechanism is not part of the standard and it will depend on the registry implementation. We only define a standard `Burn` event, which must be emitted each time a token is removed from existence. Some registries may forbid accounts to burn their tokens in order to preserve specific claims. Ultimately, NEAR is a public blockchain, and even if a token is burned, it's trace will be preserved. + +### Token Class (multitoken approach) + +SBT tokens can't be fractionized. Also, by definition, there should be only one SBT per token class per user. Examples: user should not be able to receive few badges of the same class, or few proof of attendance to the same event. +However, we identify a need for having to support token classes (aka multitoken interface) in a single contract: + +- badges: one contract. Each badge will have a class (community lead, OG...), and each token will belong to a specific class; +- certificates: one issuer can create certificates of a different class (eg school department can create diplomas for each major and each graduation year). + +We also see a trend in the NFT community and demand for market places to support multi token contracts. + +- In Ethereum community many projects are using [ERC-1155 Multi Token Standard](https://eips.ethereum.org/EIPS/eip-1155). NFT projects are using it for fraction ownership: each token id can have many fungible fractions. +- NEAR [NEP-245](https://github.com/near/NEPs/blob/master/neps/nep-0245.md) has elaborated similar interface for both bridge compatibility with EVM chains as well as flexibility to define different token types with different behavior in a single contract. [DevGovGigs Board](https://near.social/#/mob.near/widget/MainPage.Post.Page?accountId=devgovgigs.near&blockHeight=87938945) recently also shows growing interest to move NEP-245 adoption forward. +- [NEP-454](https://github.com/near/NEPs/pull/454) proposes royalties support for multi token contracts. + +We propose that the SBT Standard will support the multi-token idea from the get go. This won't increase the complexity of the contract (in a traditional case, where one contract will only issue tokens of the single class, the `class` argument is simply ignored in the state, and in the functions it's required to be of a constant value, eg `1`) but will unify the interface. +It's up to the smart contract design how the token classes is managed. A smart contract can expose an admin function (example: `sbt_new_class() -> ClassId`) or hard code the pre-registered classes. + +Finally, we require that each token ID is unique within the smart contract. This will allow us to query token only by token ID, without knowing it's class. + +## Smart contract interface + +For the Token ID type we propose `u64` rather than `U128`. `u64` capacity is more than 1e19. If we will mint 10'000 SBTs per second, then it will take us 58'494'241 years to fill the capacity. +Today, the JS integer limit is `2^53-1 ~ 9e15`. Similarly, when minting 10'000 SBTs per second, it will take us 28'561 years to reach the limit. So, we don't need u128 nor the String type. However, if for some reason, we will need to get u64 support for JS, then we can always add another set of methods which will return String, so making it compatible with NFT standard (which is using `U128`, which is a string). Also, it's worth to note, that in 28'000 years JS (if it will still exists) will be completely different. +The number of combinations for a single issuer is much higher in fact: the token standard uses classes. So technically that makes the number of all possible combinations for a single issuer equal `(2^64)^2 ~ 1e38`. For "today" JS it is `(2^53-1)^2 ~ 1e31`. + +Token IDs MUST be created in a sequence to make sure the ID space is not exhausted locally (eg if a registry would decide to introduce segments, it would potentially get into a trap where one of the segments is filled up very quickly). + +```rust +// TokenId and ClassId must be positive (0 is not a valid ID) +pub type TokenId = u64; +pub type ClassId = u64; + +pub struct Token { + pub token: TokenId, + pub owner: AccountId, + pub metadata: TokenMetadata, +} +``` + +The Soulbound Token follows the NFT [NEP-171](https://github.com/near/NEPs/blob/master/neps/nep-0171.md) interface, with few differences: + +- token ID is `u64` (as discussed above). +- token class is `u64`, it's required when minting and it's part of the token metadata. +- `TokenMetadata` doesn't have `title`, `description`, `media`, `media_hash`, `copies`, `extra`, `starts_at` nor `updated_at`. All that attributes except the `updated_at` can be part of the document stored at `reference`. `updated_at` can be tracked easily by indexers. +- We don't have traditional transferability. +- We propose to use more targeted events, to better reflect the event nature. Moreover events are emitted by the registry, so we need to include issuer contract address in the event. + +All time related attributes are defined in milliseconds (as per NEP-171). + +```rust +/// ContractMetadata defines contract wide attributes, which describes the whole contract. +pub struct ContractMetadata { + /// Version with namespace, example: "sbt-1.0.0". Required. + pub spec: String, + /// Issuer Name, required, ex. "Mosaics" + pub name: String, + /// Issuer symbol which can be used as a token symbol, eg Ⓝ, ₿, BTC, MOSAIC ... + pub symbol: String, + /// Icon content (SVG) or a link to an Icon. If it doesn't start with a scheme (eg: https://) + /// then `base_uri` should be prepended. + pub icon: Option, + /// URI prefix which will be prepended to other links which don't start with a scheme + /// (eg: ipfs:// or https:// ...). + pub base_uri: Option, + /// JSON or an URL to a JSON file with more info. If it doesn't start with a scheme + /// (eg: https://) then base_uri should be prepended. + pub reference: Option, + /// Base64-encoded sha256 hash of JSON from reference field. Required if `reference` is included. + pub reference_hash: Option, +} + +/// TokenMetadata defines attributes for each SBT token. +pub struct TokenMetadata { + pub class: ClassId, // token class. Required. Must be non zero. + pub issued_at: Option, // When token was issued or minted, Unix time in milliseconds + pub expires_at: Option, // When token expires, Unix time in milliseconds + /// JSON or an URL to a JSON file with more info. If it doesn't start with a scheme + /// (eg: https://) then base_uri should be prepended. + pub reference: Option, + /// Base64-encoded sha256 hash of JSON from reference field. Required if `reference` is included. + pub reference_hash: Option, +} + + +trait SBTRegistry { + /********** + * QUERIES + **********/ + + /// Get the information about specific token ID issued by `issuer` SBT contract. + fn sbt(&self, issuer: AccountId, token: TokenId) -> Option; + + /// Get the information about list of token IDs issued by the `issuer` SBT contract. + /// If token ID is not found `None` is set in the specific return index. + fn sbts(&self, issuer: AccountId, token: Vec) -> Vec>; + + /// Query class ID for each token ID issued by the SBT `issuer`. + /// If token ID is not found, `None` is set in the specific return index. + fn sbt_classes(&self, issuer: AccountId, tokens: Vec) -> Vec>; + + /// Returns total amount of tokens issued by `issuer` SBT contract, including expired + /// tokens. If a revoke removes a token, it must not be included in the supply. + fn sbt_supply(&self, issuer: AccountId) -> u64; + + /// Returns total amount of tokens of given class minted by `issuer`. See `sbt_supply` for + /// information about revoked tokens. + fn sbt_supply_by_class(&self, issuer: AccountId, class: ClassId) -> u64; + + /// Returns total supply of SBTs for a given owner. See `sbt_supply` for information about + /// revoked tokens. + /// If `class` is specified, returns only owner supply of the given class (either 0 or 1). + fn sbt_supply_by_owner( + &self, + account: AccountId, + issuer: AccountId, + class: Option, + ) -> u64; + + /// Query sbt tokens issued by a given contract. + /// `limit` specifies the upper limit of how many tokens we want to return. + /// If `from_token` is not specified, then `from_token` should be assumed + /// to be the first valid token id. If `with_expired` is set to `true` then all the tokens are returned + /// including expired ones otherwise only non-expired tokens are returned. + fn sbt_tokens( + &self, + issuer: AccountId, + from_token: Option, + limit: Option, + with_expired: bool, + ) -> Vec; + + /// Query SBT tokens by owner. + /// `limit` specifies the upper limit of how many tokens we want to return. + /// If `from_class` is not specified, then `from_class` should be assumed to be the first + /// valid class id. If `with_expired` is set to `true` then all the tokens are returned + /// including expired ones otherwise only non-expired tokens are returned. + /// Returns list of pairs: `(Contract address, list of token IDs)`. + fn sbt_tokens_by_owner( + &self, + account: AccountId, + issuer: Option, + from_class: Option, + limit: Option, + with_expired: bool, + ) -> Vec<(AccountId, Vec)>; + + /// checks if an `account` was banned by the registry. + fn is_banned(&self, account: AccountId) -> bool; + + /************* + * Transactions + *************/ + + /// Creates a new, unique token and assigns it to the `receiver`. + /// `token_spec` is a vector of pairs: owner AccountId and TokenMetadata. + /// Each TokenMetadata must have non zero `class`. + /// Must be called by an SBT contract. + /// Must emit `Mint` event. + /// Must provide enough NEAR to cover registry storage cost. + // #[payable] + fn sbt_mint(&mut self, token_spec: Vec<(AccountId, Vec)>) -> Vec; + + /// sbt_recover reassigns all tokens issued by the caller, from the old owner to a new owner. + /// Must be called by a valid SBT issuer. + /// Must emit `Recover` event once all the tokens have been recovered. + /// Requires attaching enough tokens to cover the storage growth. + /// Returns the amount of tokens recovered and a boolean: `true` if the whole + /// process has finished, `false` when the process has not finished and should be + /// continued by a subsequent call. User must keep calling the `sbt_recover` until `true` + /// is returned. + // #[payable] + fn sbt_recover(&mut self, from: AccountId, to: AccountId) -> (u32, bool); + + /// sbt_renew will update the expire time of provided tokens. + /// `expires_at` is a unix timestamp (in miliseconds). + /// Must be called by an SBT contract. + /// Must emit `Renew` event. + fn sbt_renew(&mut self, tokens: Vec, expires_at: u64); + + /// Revokes SBT by burning the token or updating its expire time. + /// Must be called by an SBT contract. + /// Must emit `Revoke` event. + /// Must also emit `Burn` event if the SBT tokens are burned (removed). + fn sbt_revoke(&mut self, tokens: Vec, burn: bool); + + /// Similar to `sbt_revoke`, but revokes all `owner`s tokens issued by the caller. + fn sbt_revoke_by_owner(&mut self, owner: AccountId, burn: bool); + + /// Allows issuer to update token metadata reference and reference_hash. + /// * `updates` is a list of triples: (token ID, reference, reference base64-encoded sha256 hash). + /// Must emit `token_reference` event. + /// Panics if any of the token IDs don't exist. + fn sbt_update_token_references( + &mut self, + updates: Vec<(TokenId, Option, Option)>, + ); +} +``` + +Example **Soul Transfer** interface: + +```rust + /// Transfers atomically all SBT tokens from one account to another account. + /// The caller must be an SBT holder and the `recipient` must not be a banned account. + /// Returns the amount of tokens transferred and a boolean: `true` if the whole + /// process has finished, `false` when the process has not finished and should be + /// continued by a subsequent call. + /// Emits `Ban` event for the caller at the beginning of the process. + /// Emits `SoulTransfer` event only once all the tokens from the caller were transferred + /// and at least one token was trasnfered (caller had at least 1 sbt). + /// + User must keep calling the `sbt_soul_transfer` until `true` is returned. + /// + If caller does not have any tokens, nothing will be transfered, the caller + /// will be banned and `Ban` event will be emitted. + #[payable] + fn sbt_soul_transfer( + &mut self, + recipient: AccountId, + ) -> (u32, bool); +``` + +### SBT Issuer interface + +SBTContract is the minimum required interface to be implemented by issuer. Other methods, such as a mint function, which requests the registry to proceed with token minting, is specific to an Issuer implementation (similarly, mint is not part of the FT standard). + +```rust +pub trait SBTContract { + /// returns contract metadata + fn sbt_metadata(&self) -> ContractMetadata; +} +``` + +SBT issuer smart contracts may implement NFT query interface to make it compatible with NFT tools. In that case, the contract should proxy the calls to the related registry. Note, we use U64 type rather than U128. However, SBT issuer must not emit NFT related events. + +```rust +trait SBTNFT { + fn nft_total_supply(&self) -> U64; + // here we index by token id instead of by class id (as done in `sbt_tokens_by_owner`) + fn nft_tokens_for_owner(&self, account_id: AccountId, from_index: Option, limit: Option) -> Vec; + fn nft_supply_for_owner(&self, account_id: AccountId) -> U64; +} +``` + +### Events + +Event design principles: + +- Events don't need to repeat all function arguments - these are easy to retrieve by indexer (events are consumed by indexers anyway). +- Events must include fields necessary to identify subject matters related to use case. +- When possible, events should contain aggregated data, with respect to the standard function related to the event. + +```typescript +// only valid integer numbers (without rounding errors). +type u64 = number; + +type Nep393Event { + standard: "nep393"; + version: "1.0.0"; + event: "mint" | "recover" | "renew" | "revoke" | "burn" | "ban" | "soul_transfer" | "token_reference" ; + data: Mint | Recover | Renew | Revoke | Burn | Ban[] | SoulTransfer | TokenReference; +} + +/// An event emitted by the Registry when new SBT is created. +type Mint { + issuer: AccountId; // SBT Contract minting the tokens + tokens: (AccountId, u64[])[]; // list of pairs (token owner, TokenId[]) +} + +/// An event emitted when a recovery process succeeded to reassign SBTs, usually due to account +/// access loss. This action is usually requested by the owner, but executed by an issuer, +/// and doesn't trigger Soul Transfer. Registry reassigns all tokens assigned to `old_owner` +/// that were ONLY issued by the `ctr` SBT Contract (hence we don't need to enumerate the +/// token IDs). +/// Must be emitted by an SBT registry. +type Recover { + issuer: AccountId // SBT Contract recovering the tokens + old_owner: AccountId; // current holder of the SBT + new_owner: AccountId; // destination account. +} + +/// An event emitted when existing tokens are renewed. +/// Must be emitted by an SBT registry. +type Renew { + issuer: AccountId; // SBT Contract renewing the tokens + tokens: u64[]; // list of token ids. +} + +/// An event emitted when existing tokens are revoked. +/// Revoked tokens will continue to be listed by the registry but they should not be listed in +/// a wallet. See also `Burn` event. +/// Must be emitted by an SBT registry. +type Revoke { + issuer: AccountId; // SBT Contract revoking the tokens + tokens: u64[]; // list of token ids. +} + +/// An event emitted when existing tokens are burned and removed from the registry. +/// Must be emitted by an SBT registry. +type Burn { + issuer: AccountId; // SBT Contract burning the tokens + tokens: u64[]; // list of token ids. +} + +/// An event emitted when an account is banned within the emitting registry. +/// Registry must add the `account` to a list of accounts that are not allowed to get any SBT +/// in the future. +/// Must be emitted by an SBT registry. +type Ban = AccountId; + +/// An event emitted when soul transfer is happening: all SBTs owned by `from` are transferred +/// to `to`, and the `from` account is banned (can't receive any new SBT). +/// Must be emitted by an SBT registry. +/// Registry MUST also emit `Ban` whenever the soul transfer happens. +type SoulTransfer { + from: AccountId; + to: AccountId; +} + +/// An event emitted when an issuer updates token metadata reference of existing SBTs. +/// Must be emitted by an SBT registry. +type TokenReference { + issuer: AccountId; // Issuer account + tokens: u64[]; // list of token ids. +} + +/// An event emitted when existing token metadata references are updated. +type TokenReference = u64[]; // list of token ids. +``` + +Whenever a recovery is made in a way that an existing SBT is burned, the `Burn` event MUST be emitted. If `Revoke` burns token then `Burn` event MUST be emitted instead of `Revoke`. + +### Example SBT Contract functions + +Although the transaction functions below are not part of the SBT smart contract standard (depending on a use case, they may have different parameters), we present here an example interface for SBT issuance and we also provide a reference implementation. +These functions must relay calls to an SBT registry, which will emit appropriate events. +We recommend that all functions related to an event will take an optional `memo: Option` argument for accounting purposes. + +```rust +trait SBT { + /// Must provide enough NEAR to cover registry storage cost. + // #[payable] + fn sbt_mint( + &mut self, + account: AccountId, + metadata: TokenMetadata, + memo: Option, + ) -> TokenId; + + /// Creates a new, unique token and assigns it to the `receiver`. + /// `token_spec` is a vector of pairs: owner AccountId and TokenMetadata. + /// Must provide enough NEAR to cover registry storage cost. + // #[payable] + fn sbt_mint_multi( + &mut self, + token_spec: Vec<(AccountId, TokenMetadata)>, + memo: Option, + ) -> Vec; + + // #[payable] + fn sbt_recover(&mut self, from: AccountId, to: AccountId, memo: Option); + + fn sbt_renew(&mut self, tokens: Vec, expires_at: u64, memo: Option); + + fn sbt_revoke(token: Vec, memo: Option) -> bool; +} +``` + +## Reference Implementation + +- Common [type definitions](https://github.com/near-ndc/i-am-human/tree/main/contracts/sbt) (events, traits). +- [I Am Human](https://github.com/near-ndc/i-am-human) registry and issuers. + +## Consequences + +Being fully compatible with NFT standard is a desirable. However, given the requirements related to _soul transfer_ we didn't find an applaudable solution. Also we decided to use u64 as a Token ID, diverging further from the NFT NEP-171 standard. + +Given that our requirements are much striker, we had to reconsider the level of compatibility with NEP-171 NFT. +There are many examples where NFT standards are improperly implemented. Adding another standard with different functionality but equal naming will cause lots of problems and misclassifications between NFT and SBT. + +### Positive + +- Template and set of guidelines for creating SBT tokens. +- Ability to create SBT aggregators. +- An SBT standard with recoverability mechanism provides a unified model for multiple primitives such as non KYC identities, badges, certificates etc... +- SBT can be further used for "lego" protocols, like: Proof of Humanity (discussed for NDC Governance), undercollateralized lending, role based authentication systems, innovative economic and social applications... +- Standard recoverability mechanism. +- SBT are considered as a basic primitive for Decentralized Societies. +- new way to implement Sybil attack resistance. + +### Neutral + +- The API partially follows the NEP-171 (NFT) standard. The proposed design is to have native SBT API and make it possible for issuer contracts to support NFT based queries if needed (such contract will have a limitation of only issuing SBTs with one `ClassId` only). + +### Negative + +- New set of events to be handled by the indexer and wallets. +- Complexity of integration with a registry: all SBT related transactions must go through Registry. + +### Privacy Notes + +> Blockchain-based systems are public by default. Any relationship that is recorded on-chain is immediately visible not just to the participants, but also to anyone in the entire world. Some privacy can be retained by having multiple pseudonyms: a family Soul, a medical Soul, a professional Soul, a political Soul each carrying different SBTs. But done naively, it could be very easy to correlate these Souls to each other. +> The consequences of this lack of privacy are serious. Indeed, without explicit measures taken to protect privacy, the “naive” vision of simply putting all SBTs on-chain may well make too much information public for many applications. + +-- Decentralized Society + +There are multiple ways how an identity can be doxxed using chain data. SBT, indeed provides more data about account. +The standard allows for few anonymization methods: + +- not providing any data in the token metadata (reference...) or encrypt the reference. +- anonymize issuers (standard allows to have many issues for the same entity) and mix it with different class ids. These are just a numbers. + +Perfect privacy can only be done with solid ZKP, not off-chain walls. + +Implementations must not store any personal information on chain. + +## Changelog + +### v1.0.0 + +The Contract Standards Working Group members approved this NEP on June 30, 2023 ([meeting recording](https://youtu.be/S1An5CDG154)). + +#### Benefits + +- SBTs as any other kind of a token are essential primitive to represent real world use cases. This standards provides a model and a guideline for developers to build SBT based solutions. +- Token standards are key for composability. +- Wallet and tools needs a common interface to operate tokens. + +#### Concerns + +| # | Concern | Resolution | Status | +| --- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- | +| 1 | [Robert] Should we Emit NEP-171 Mint and NEP-171 Burn by the SBT contract (in addition to SBT native events emitted by the registry)? If the events will be emitted by registry, then we need new events to include the contract address. | Don't emit NFT events. SBT is not NFT. Support: @alexastrum | resolved | +| 2 | [Robert] remove `memo` in events. The `memo` is already part of the transaction, and should not be needed to identify transactions. Processes looking for events, can easily track transaction through event and recover `memo` if needed. | Removed, consequently also removed from registry transactions . Support: @alexastrum | resolved | +| 3 | [Token Spam](https://github.com/near/NEPs/pull/393/#discussion_r1163938750) | We have a `Burn` event. Added example `sbt_burn` function, but keeping it not as a part of required interface. Event should be enough. | resolved | +| 4 | [Multiple registries](https://github.com/near/NEPs/pull/393/#discussion_r1163951624). Registry source of truth [comment](https://github.com/near/NEPs/pull/393/#issuecomment-1531766643) | This is a part of the design: permissionless approach. [Justification for registry](https://github.com/near/NEPs/pull/393/#issuecomment-1540621077) | resolved | +| 5 | [Robert] Approve the proposed multi-token | Support: @alexastrum | resolved | +| 6 | [Robert] Use of milliseconds as a time unit. | Use milliseconds. | resolved | +| 7 | Should a `burn` function be part of a standard or a recommendation? | We already have the Burn event. A call method should not be part of the standard interface (similarly to FT and NFT). | resolved | +| 8 | [Robert] Don't include `sbt_soul_transfer` in the standard interface, [comment](https://github.com/near/NEPs/pull/393#issuecomment-1506969996). | Moved outside of the required interface. | resolved | +| 9 | [Privacy](https://github.com/near/NEPs/pull/393/#issuecomment-1504309947) | Concerns have been addressed: [comment-1](https://github.com/near/NEPs/pull/393/#issuecomment-1504485420) and [comment2](https://github.com/near/NEPs/pull/393/#issuecomment-1505958549) | resolved | +| 10 | @frol [suggested](https://github.com/near/NEPs/pull/393/#discussion_r1247879778) to use a struct in `sbt_recover` and `sbt_soul_transfer`. | Motivation to use pair `(number, bool)` rather than follow a common Iterator Pattern. Rust uses `Option` type for that, that works perfectly for languages with native Option type, but creates a "null" problem for anything else. Other common way to implement Iterator is the presented pair, which doesn't require extra type definition and reduces code size. | new | + +## Copyright + +[Creative Commons Attribution 4.0 International Public License (CC BY 4.0)](https://creativecommons.org/licenses/by/4.0/) From 6eee9dc14ff64dd2eac24e4ae704e0b8fbb18ba9 Mon Sep 17 00:00:00 2001 From: Robert Zaremba Date: Sun, 22 Oct 2023 16:13:21 +0300 Subject: [PATCH 131/150] nep-393: add bool return to sbt_revoke_by_owner (#510) In the [reference](https://github.com/near-ndc/i-am-human/blob/cfc92b1/contracts/registry/src/registry.rs#L362) implementation we return `bool` in the `registry.sbt_revoke_by_owner` to signal if the operation should continue or it's finished. We forgot to push this update to the standard. This update also makes the API consistent with `sbt_recover` and `sbt_soul_transfer` --- neps/nep-0393.md | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/neps/nep-0393.md b/neps/nep-0393.md index 67b3361c2..9c10b0469 100644 --- a/neps/nep-0393.md +++ b/neps/nep-0393.md @@ -404,8 +404,15 @@ trait SBTRegistry { /// Must also emit `Burn` event if the SBT tokens are burned (removed). fn sbt_revoke(&mut self, tokens: Vec, burn: bool); - /// Similar to `sbt_revoke`, but revokes all `owner`s tokens issued by the caller. - fn sbt_revoke_by_owner(&mut self, owner: AccountId, burn: bool); + /// Similar to `sbt_revoke`. Allows SBT issuer to revoke all tokens by holder either by + /// burning or updating their expire time. When an owner has many tokens from the issuer, + /// the issuer may need to call this function multiple times, until all tokens are revoked. + /// Retuns true if all the tokens were revoked, false otherwise. + /// If false is returned issuer must call the method until true is returned + /// Must be called by an SBT contract. + /// Must emit `Revoke` event. + /// Must also emit `Burn` event if the SBT tokens are burned (removed). + fn sbt_revoke_by_owner(&mut self, owner: AccountId, burn: bool) -> bool; /// Allows issuer to update token metadata reference and reference_hash. /// * `updates` is a list of triples: (token ID, reference, reference base64-encoded sha256 hash). From d49bf8fe0cd7813e76a3a08993c1213faacc07c4 Mon Sep 17 00:00:00 2001 From: Jakob Meier Date: Sun, 22 Oct 2023 18:25:34 +0200 Subject: [PATCH 132/150] chore: move nep-0264_promise_gas_ratio to NEPs (#506) --- README.md | 1 + .../nep-0264.md | 36 +++++++++++-------- 2 files changed, 23 insertions(+), 14 deletions(-) rename specs/Proposals/0264-promise_gas_ratio.md => neps/nep-0264.md (95%) diff --git a/README.md b/README.md index 6b81d1867..beb040f80 100644 --- a/README.md +++ b/README.md @@ -23,6 +23,7 @@ Changes to the protocol specification and standards are called NEAR Enhancement | [0181](https://github.com/near/NEPs/blob/master/neps/nep-0181.md) | Non Fungible Token Enumeration | @chadoh @thor314 | Final | | [0199](https://github.com/near/NEPs/blob/master/neps/nep-0199.md) | Non Fungible Token Royalties and Payouts | @thor314 @mattlockyer | Final | | [0245](https://github.com/near/NEPs/blob/master/neps/nep-0245.md) | Multi Token Standard | @zcstarr @riqi @jriemann @marcos.sun | Review | +| [0264](https://github.com/near/NEPs/blob/master/neps/nep-0264.md) | Promise Gas Weights | @austinabell | Final | | [0297](https://github.com/near/NEPs/blob/master/neps/nep-0297.md) | Events Standard | @telezhnaya | Final | | [0330](https://github.com/near/NEPs/blob/master/neps/nep-0330.md) | Source Metadata | @BenKurrek | Review | | [0366](https://github.com/near/NEPs/blob/master/neps/nep-0366.md) | Meta Transactions | @ilblackdragon @e-uleyskiy @fadeevab | Draft | diff --git a/specs/Proposals/0264-promise_gas_ratio.md b/neps/nep-0264.md similarity index 95% rename from specs/Proposals/0264-promise_gas_ratio.md rename to neps/nep-0264.md index 17306bbfa..e239a4b41 100644 --- a/specs/Proposals/0264-promise_gas_ratio.md +++ b/neps/nep-0264.md @@ -1,31 +1,35 @@ -- Proposal Name: `promise_gas_weight` -- Start Date: 2021-09-30 -- NEP PR: [nearprotocol/neps#264](https://github.com/nearprotocol/neps/pull/264) -- Issue(s): https://github.com/near/near-sdk-rs/issues/526 +--- +NEP: 264 +Title: Utilization of unspent gas for promise function calls +Authors: Austin Abell +DiscussionsTo: https://github.com/near/NEPs/pull/264 +Status: Approved +Type: Protocol +Version: 1.0.0 +Created: 2021-09-30 +LastUpdated: 2022-05-26 +--- # Summary -[summary]: #summary This proposal is to introduce a new host function on the NEAR runtime that allows for scheduling cross-contract function calls using a percentage/weight of the remaining gas in addition to the statically defined amount. This will enable async promise execution to use the remaining gas more efficiently by utilizing unspent gas from the current transaction. # Motivation -[motivation]: #motivation We are proposing this to be able to utilize gas more efficiently but also to improve the devX of cross-contract calls. Currently, developers must guess how much gas will remain after the current transaction finishes and if this value is too little, the transaction will fail, and if it is too large, gas will be wasted. Therefore, these cross-contract calls need a reasonable default of splitting unused gas efficiently for basic cases without sacrificing the ability to configure the gas amount attached at a granular level. Currently, gas is allocated very inefficiently, requiring more prepaid gas or failed transactions when the allocations are imprecise. # Guide-level explanation -[guide-level-explanation]: #guide-level-explanation This host function is similar to [`promise_batch_action_function_call`](https://github.com/near/nearcore/blob/7d15bbc996282c8ae8f15b8f49d110fc901b84d8/runtime/near-vm-logic/src/logic.rs#L1526), except with an additional parameter that lets you specify how much of the excess gas should be attached to the function call. This parameter is a weight value that determines how much of the excess gas is attached to each function. So, for example, if there is 40 gas leftover and three function calls that select weights of 1, 5, and 2, the runtime will add 5, 25, and 10 gas to each function call. A developer can specify whether they want to attach a fixed amount of gas, a weight of remaining gas, or both. If at least one function call uses a weight of remaining gas, then all excess gas will be attached to future calls. This proposal allows developers the ability to utilize prepaid gas more efficiently than currently possible. # Reference-level explanation -[reference-level-explanation]: #reference-level-explanation This host function would need to be implemented in `nearcore` and parallel [`promise_batch_action_function_call`](https://github.com/near/nearcore/blob/7d15bbc996282c8ae8f15b8f49d110fc901b84d8/runtime/near-vm-logic/src/logic.rs#L1526). Most details of these functions will be consistent, except that there will be additional bookkeeping for keeping track of which functions specified a weight for unused gas. This will not affect or replace any existing host functions, but this will likely require a slightly higher gas cost than the original `promise_batch_action_function_call` host function due to this additional overhead. This host function definition would look like this (as a Rust consumer): + ```rust /// Appends `FunctionCall` action to the batch of actions for the given promise pointed by /// `promise_idx`. This function allows not specifying a specific gas value and allowing the @@ -70,7 +74,8 @@ The only difference from the existing API is `gas_weight` added as another param As for calculations, the remaining gas at the end of the transaction can be floor divided by the sum of all the weights tracked. Then, after getting this value, just attach that value multiplied by the weight gas to each function call action. For example, if there are three weights, `a`, `b`, `c`: -``` + +```rust weight_sum = a + b + c a_gas += remaining_gas * a / weight_sum b_gas += remaining_gas * b / weight_sum @@ -84,6 +89,7 @@ Any remaining gas that is not allocated to any of these function calls will be a This protocol change will allow cross-contract calls to provide a fixed amount of gas and/or adjust the weight of unused gas to use. If neither is provided, it will default to using a weight of 1 for each and no static amount of gas. If no function modifies this weight, the runtime will split the unused gas evenly among all function calls. Currently, the API for a cross-contract call looks like: + ```rust let contract_account_id: AccountId = todo!(); ext::some_method(/* parameters */, contract_account_id, 0 /* deposit amount */, 5_000_000_000_000 /* static amount of gas to attach */) @@ -105,7 +111,6 @@ cross_contract::ext(contract_account_id) At a basic level, a developer has only to include the parameters for the function call and specify the account id of the contract being called. Currently, only the amount can be optional because there is no way to set a reasonable default for the amount of gas to use for each function call. # Drawbacks -[drawbacks]: #drawbacks - Complexity in refactoring to handle assigning remaining gas at the end of a transaction - Complexity in extra calculations for assigning gas will make the host function slightly more expensive than the base one. It is not easy to create an API on the SDK level that can decide which host function to call if dynamic gas assigning is needed or not. If both are used, the size of the wasm binary is trivially larger by including both host functions @@ -116,18 +121,19 @@ At a basic level, a developer has only to include the parameters for the functio - Keep in mind that it will also be positive because transactions will generally succeed more often due to gas more efficiently # Rationale and alternatives -[rationale-and-alternatives]: #rationale-and-alternatives Alternative 1 (fraction parameters): The primary alternative is using a numerator and denominator to represent a fraction instead of a weight. This alternative would be equivalent to the one listed above except for two u64 additional parameters instead of just the one for weight. I'll list the tradeoff as pros and cons: Pros: + - Can under-utilize the gas for the current transaction to limit gas allowed for certain functions - This could take responsibility away from DApp users because they would not have to worry less about attaching too much prepaid gas - Thinking in terms of fractions may be more intuitive for some developers - Might future proof better if we ever need this ability in the future, want to minimize the number of host functions created at all costs Cons: + - More complicated logic/edge cases to handle to make sure the percentages don't sum to greater than 100% (or adjusting if they do) - Precision loss from dividing integers may lead to unexpected results - To get closer to expected, we could use floats for the division, but this gets messy @@ -139,30 +145,32 @@ Alternative 2 (handle within contract/SDK): The other alternative is to handle all of this logic on the contract side, as seen by [this PR](https://github.com/near/near-sdk-rs/pull/523). This is much less feasible/accurate because there is only so much information available within the runtime, and gas costs and internal functionality may not always be the same. As discussed on [the respective issue](https://github.com/near/near-sdk-rs/issues/526), this alternative seems to be very infeasible. Pros: + - No protocol change is needed - Can still have improved API as with protocol change Cons: + - Additional bloat to every contract, even ones that don't use the pattern (~5kb in PoC, even with simple estimation logic) - Still inaccurate gas estimations, because at the point of calculation, we cannot know how much gas will be used for assigning gas values as well as gas consumed after the transaction ends - This leads to either underutilizing or having transactions fail when using too much gas if trying to estimate how much gas will be left - Prone to breaking existing contracts on protocol changes that affect gas usage or logic of runtime # Unresolved questions -[unresolved-questions]: #unresolved-questions What needs to be addressed before this gets merged: ~~- How much refactoring exactly is needed to handle this pattern?~~ ~~- Can we keep a queue of receipt and action indices with their respective weights and update their gas values after the current method is executed? Is there a cleaner way to handle this while keeping order?~~ ~~- Do we want to attach the gas lost due to precision on division to any function?~~ - - The remaining gas is now attached to the last function call + +- The remaining gas is now attached to the last function call What would be addressed in future independently of the solution: + - How many users would expect the ability to refund part of the gas after the initial transaction? (is this worth considering the API difference of using fractions rather than weights) - Will weights be an intuitive experience for developers? # Future possibilities -[future-possibilities]: #future-possibilities The future change that would extend from this being implemented is a much cleaner API for the SDKs. As mentioned previously in the alternatives section, the API changes from [the changes tested on the SDK](https://github.com/near/near-sdk-rs/pull/523) will remain, but without the overhead from implementing this on the contract level. Thus, not only can this be implemented in Rust, but it will also allow a consistent API for existing and future SDK languages to build on. From b9c3d15e70fe19ec23fe3aadbf323bbdd81fa069 Mon Sep 17 00:00:00 2001 From: nikurt <86772482+nikurt@users.noreply.github.com> Date: Fri, 3 Nov 2023 23:02:30 +0100 Subject: [PATCH 133/150] NEP-514: Reducing the number of Block Producer Seats in `testnet` (#514) --- README.md | 4 +- nep-0000-template.md | 26 +++---- neps/nep-0514.md | 166 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 182 insertions(+), 14 deletions(-) create mode 100644 neps/nep-0514.md diff --git a/README.md b/README.md index beb040f80..ecdaf7baa 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ Changes to the protocol specification and standards are called NEAR Enhancement ## NEPs | NEP # | Title | Author | Status | -| ----------------------------------------------------------------- | ---------------------------------------- | ------------------------------------------- | ------ | +| ----------------------------------------------------------------- |------------------------------------------|---------------------------------------------|--------| | [0001](https://github.com/near/NEPs/blob/master/neps/nep-0001.md) | NEP Purpose and Guidelines | @jlogelin | Living | | [0021](https://github.com/near/NEPs/blob/master/neps/nep-0021.md) | Fungible Token Standard (Deprecated) | @evgenykuzyakov | Final | | [0141](https://github.com/near/NEPs/blob/master/neps/nep-0141.md) | Fungible Token Standard | @evgenykuzyakov @oysterpack | Final | @@ -30,6 +30,8 @@ Changes to the protocol specification and standards are called NEAR Enhancement | [0399](https://github.com/near/NEPs/blob/master/neps/nep-0399.md) | Flat Storage | @Longarithm @mzhangmzz | Review | | [0448](https://github.com/near/NEPs/blob/master/neps/nep-0448.md) | Zero-balance Accounts | @bowenwang1996 | Final | | [0455](https://github.com/near/NEPs/blob/master/neps/nep-0455.md) | Parameter Compute Costs | @akashin @jakmeier | Final | +| [0514](https://github.com/near/NEPs/blob/master/neps/nep-0514.md) | Fewer Block Producer Seats in `testnet` | @nikurt | Final | + ## Specification diff --git a/nep-0000-template.md b/nep-0000-template.md index 772979545..47b65bdac 100644 --- a/nep-0000-template.md +++ b/nep-0000-template.md @@ -58,11 +58,11 @@ See example above --> [This technical section is required for Protocol proposals but optional for other categories. A draft implementation should demonstrate a minimal implementation that assists in understanding or implementing this proposal. Explain the design in sufficient detail that: -- Its interaction with other features is clear. -- Where possible, include a Minimum Viable Interface subsection expressing the required behavior and types in a target programming language. (ie. traits and structs for rust, interfaces and classes for javascript, function signatures and structs for c, etc.) -- It is reasonably clear how the feature would be implemented. -- Corner cases are dissected by example. -- For protocol changes: A link to a draft PR on nearcore that shows how it can be integrated in the current code. It should at least solve the key technical challenges. +* Its interaction with other features is clear. +* Where possible, include a Minimum Viable Interface subsection expressing the required behavior and types in a target programming language. (ie. traits and structs for rust, interfaces and classes for javascript, function signatures and structs for c, etc.) +* It is reasonably clear how the feature would be implemented. +* Corner cases are dissected by example. +* For protocol changes: A link to a draft PR on nearcore that shows how it can be integrated in the current code. It should at least solve the key technical challenges. The section should return to the examples given in the previous section, and explain more fully how the detailed proposal makes those examples work.] @@ -84,15 +84,15 @@ The section should return to the examples given in the previous section, and exp ### Positive -- p1 +* p1 ### Neutral -- n1 +* n1 ### Negative -- n1 +* n1 ### Backwards Compatibility @@ -102,9 +102,9 @@ The section should return to the examples given in the previous section, and exp [Explain any issues that warrant further discussion. Considerations -- What parts of the design do you expect to resolve through the NEP process before this gets merged? -- What parts of the design do you expect to resolve through the implementation of this feature before stabilization? -- What related issues do you consider out of scope for this NEP that could be addressed in the future independently of the solution that comes out of this NEP?] +* What parts of the design do you expect to resolve through the NEP process before this gets merged? +* What parts of the design do you expect to resolve through the implementation of this feature before stabilization? +* What related issues do you consider out of scope for this NEP that could be addressed in the future independently of the solution that comes out of this NEP?] ## Changelog @@ -118,8 +118,8 @@ The section should return to the examples given in the previous section, and exp > List of benefits filled by the Subject Matter Experts while reviewing this version: -- Benefit 1 -- Benefit 2 +* Benefit 1 +* Benefit 2 #### Concerns diff --git a/neps/nep-0514.md b/neps/nep-0514.md new file mode 100644 index 000000000..10a3bae80 --- /dev/null +++ b/neps/nep-0514.md @@ -0,0 +1,166 @@ +--- +NEP: 514 +Title: Reducing the number of Block Producer Seats in `testnet` +Authors: Nikolay Kurtov +Status: New +DiscussionsTo: https://github.com/nearprotocol/neps/pull/514 +Type: Protocol +Version: 1.0.0 +Created: 2023-10-25 +LastUpdated: 2023-10-25 +--- + + +## Summary + +This proposal aims to adjust the number of block producer seats on `testnet` in +order to ensure a positive number of chunk-only producers present in `testnet` +at all times. + +## Motivation + +The problem is that important code paths are not exercised in `testnet`. This +makes `mainnet` releases more risky than they have to be, and greatly slows +down development of features related to chunk-only producers, such as State +Sync. + +That is because `testnet` has fewer validating nodes than the number of block +producer seats configured. + +The number of validating nodes on `testnet` is somewhere in the range of +[26, 46], which means that all validating nodes are block producers and none of +them are chunk-only producers. [Grafana](https://nearinc.grafana.net/goto/7Kh81P7IR?orgId=1). + +`testnet` configuration is currently the following: + +* `"num_block_producer_seats": 100,` +* `"num_block_producer_seats_per_shard": [ 100, 100, 100, 100 ],` +* `"num_chunk_only_producer_seats": 200,` + +It's evident that the 100 block producer seats significantly outnumber the +validating nodes in `testnet`. + +An alternative solution to the problem stated above can be the following: + +1. Encourage the community to run more `testnet` validating nodes +1. Release owners or developers of features start a lot of validating nodes to +1. ensure `testnet` gets some chunk-only producing nodes. +1. Exercise the unique code paths in a separate chain, a-la `localnet`. + +Let's consider each of these options. + +### More community nodes + +This would be the ideal perfect situation. More nodes joining will make +`testnet` more similar to `mainnet`, which will have various positive effects +for protocol developers and dApp developers. + +However, this option is expensive, because running a validating node costs +money, and most community members can't afford spending that amount of money for +the good of the network. + +### More protocol developer nodes + +While this option may seem viable, it poses significant financial challenges for +protocol development. The associated computational expenses are exorbitantly +high, making it an impractical choice for sustainable development. + +### Test in separate chains + +That is the current solution, and it has significant drawbacks: + +* Separate chains are short-lived and may miss events critical to the unique + code paths of chunk-only producers +* Separate chains need special attention to be configured in a way that + accommodates for chunk-only producers. Most test cases are not concerned about + them, and don't exercise the unique code paths. +* Separate chains can't process real transaction traffic. The traffic must + either be synthetic or "inspired" by real traffic. +* Each such test has a significant cost of running multiple nodes, in some + cases, tens of nodes. + +## Specification + +The proposal suggests altering the number of block producer seats to ensure that +a portion of the `testnet` validating nodes become chunk-only producers. + +The desired `testnet` configuration is the following: + +* `"num_block_producer_seats": 20,` +* `"num_block_producer_seats_per_shard": [ 20, 20, 20, 20 ],` +* `"num_chunk_only_producer_seats": 100,` + +I suggest to implement the change for all networks that are not `mainnet` and +have `use_production_config` in the genesis file. `use_production_config` is a +sneaky parameter in `GenesisConfig` that lets protocol upgrades to change +network's `GenesisConfig`. + +I don't have a solid argument for lowering the number of chunk producer seats, +but that reflects the reality that we don't expect a lot of nodes joining +`testnet`. It also makes it easier to test the case of too many validating nodes +willing to join a network. + +## Reference Implementation + +[#9563](https://github.com/near/nearcore/pull/9563) + +If `use_production_config`, check whether `chain_id` is eligible, then change +the configuration as specified above. + +## Security Implications + +The block production in `testnet` becomes more centralized. It's not a new +concern as 50% of stake is already owned by nodes operated by the protocol +developers. + +## Alternatives + +See above. + +## Future possibilities + +Adjust the number of block and chunk producer seats according to the development +of the number of `testnet` validating nodes. + +## Consequences + +### Positive + +* Chunk-only production gets tested in `testnet` +* Development of State Sync and other features related to chunk-only producers accelerates + +### Neutral + +* `testnet` block production becomes more centralized + +### Negative + +* Any? + +### Backwards Compatibility + +During the protocol upgrade, some nodes will become chunk-only producers. + +The piece of code that updates `testnet` configuration value will need to be +kept in the database in case somebody wants to generate `EpochInfo` compatible +with the protocol versions containing the implementation of this NEP. + +## Changelog + +### 1.0.0 - Initial Version + +The Protocol Working Group members approved this NEP on Oct 26, 2023. + +[Zulip link](https://near.zulipchat.com/#narrow/stream/297873-pagoda.2Fnode/topic/How.20to.20test.20a.20chunk-only.20producer.20node.20in.20testnet.3F/near/396090090) + +#### Benefits + +See [Consequences](#consequences). + +#### Concerns + +See [Consequences](#consequences). + +## Copyright + +Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). From a5bb580a037cde12017d594a6fa0a817c748de32 Mon Sep 17 00:00:00 2001 From: Bowen Wang Date: Thu, 16 Nov 2023 22:51:48 +0300 Subject: [PATCH 134/150] NEP-0492: Restrict creation of Ethereum Addresses (#492) Proposal to restrict the creation of Ethereum addresses on NEAR to prevent loss of funds and enable future possibilities for Ethereum wallets to support NEAR transactions. Implementation: https://github.com/near/nearcore/pull/9365 --- neps/nep-0492.md | 74 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 74 insertions(+) create mode 100644 neps/nep-0492.md diff --git a/neps/nep-0492.md b/neps/nep-0492.md new file mode 100644 index 000000000..a6dfd434f --- /dev/null +++ b/neps/nep-0492.md @@ -0,0 +1,74 @@ +--- +NEP: 492 +Title: Restrict creation of Ethereum Addresses +Authors: Bowen Wang +Status: Final +DiscussionsTo: https://github.com/near/NEPs/pull/492 +Type: Protocol +Version: 0.0.0 +Created: 2023-07-27 +LastUpdated: 2023-07-27 +--- + +## Summary + +This proposal aims to restrict the creation of top level accounts (other than implicit accounts) on NEAR to both prevent loss of funds due to careless user behaviors and scams +and create possibilities for future interopability solutions. + +## Motivation + +Today an [Ethereum address](https://ethereum.org/en/developers/docs/accounts/) such as "0x32400084c286cf3e17e7b677ea9583e60a000324" is a valid account on NEAR and because it is longer than 32 characters, +anyone can create such an account. This has unfortunately caused a few incidents where users lose their funds due to either a scam or careless behaviors. +For example, when a user withdraw USDT from an exchange to their NEAR account, it is possible that they think they withdraw to Ethereum and therefore enter their Eth address. +If this address exists on NEAR, then the user would lose their fund. A malicious actor could exploit this can create known Eth smart contract addresses on NEAR to trick users to send tokens to those addresses. With the proliferation of BOS gateways, including Ethereum ones, such exploits may become more common as users switch between NEAR wallets and Ethereum wallets (mainly metamask). + +In addition to prevent loss of funds for users, this change allows the possibility of Ethereum wallets supporting NEAR transactions, which could enable much more adoption of NEAR. The exact details of how that would be done is outside the scope of this proposal. + +There are currently ~5000 Ethereum addresses already created on NEAR. It is also outside the scope of this proposal to discuss what to do with them. + +## Specification + +The proposed change is quite simple. Only the protocol registrar account can create top-level accounts that are not implicit accounts + +## Reference Implementation + +The implementation roughly looks as follows: + +```Rust +fn action_create_account(...) { + ... + if account_id.is_top_level() && !account_id.is_implicit() + && predecessor_id != &account_creation_config.registrar_account_id + { + // Top level accounts that are not implicit can only be created by registrar + result.result = Err(ActionErrorKind::CreateAccountOnlyByRegistrar { + account_id: account_id.clone(), + registrar_account_id: account_creation_config.registrar_account_id.clone(), + predecessor_id: predecessor_id.clone(), + } + .into()); + return; + } + ... +} +``` + +## Alternatives + +There does not appear to be a good alternative for this problem. + +## Future possibilities + +Ethereum wallets such as Metamask could potentially support NEAR transactions through meta transactions. + +## Consequences + +In the short term, no new top-level accounts would be allowed to be created, but this change would not create any problem for users. + +### Backwards Compatibility + +For Ethereum addresses specifically, there are ~5000 existing ones, but this proposal per se do not deal with existing accounts. + +## Copyright + +Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). From f2f981a8c22bde3b10df536e7e34ce9dc37a90b3 Mon Sep 17 00:00:00 2001 From: walnut-the-cat <122475853+walnut-the-cat@users.noreply.github.com> Date: Mon, 22 Jan 2024 10:53:55 -0800 Subject: [PATCH 135/150] NEP-508: Resharding v2 (#508) Draft for NEP-508, which introduces a new version of resharding implementation. --- neps/nep-0508.md | 267 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 267 insertions(+) create mode 100644 neps/nep-0508.md diff --git a/neps/nep-0508.md b/neps/nep-0508.md new file mode 100644 index 000000000..36fffe5ce --- /dev/null +++ b/neps/nep-0508.md @@ -0,0 +1,267 @@ +--- +NEP: 508 +Title: Resharding v2 +Authors: Waclaw Banasik, Shreyan Gupta, Yoon Hong +Status: Draft +DiscussionsTo: https://github.com/near/nearcore/issues/8992 +Type: Protocol +Version: 1.0.0 +Created: 2023-09-19 +LastUpdated: 2023-11-14 +--- + +## Summary + +This proposal introduces a new implementation for resharding and a new shard layout for the production networks. + +In essence, this NEP is an extension of [NEP-40](https://github.com/near/NEPs/blob/master/specs/Proposals/0040-split-states.md), which was focused on splitting one shard into multiple shards. + +We are introducing resharding v2, which supports one shard splitting into two within one epoch at a pre-determined split boundary. The NEP includes performance improvement to make resharding feasible under the current state as well as actual resharding in mainnet and testnet (To be specific, splitting the largest shard into two). + +While the new approach addresses critical limitations left unsolved in NEP-40 and is expected to remain valid for foreseeable future, it does not serve all use cases, such as dynamic resharding. + +## Motivation + +Currently, NEAR protocol has four shards. With more partners onboarding, we started seeing that some shards occasionally become over-crowded with respect to total state size and number of transactions. In addition, with state sync and stateless validation, validators will not need to track all shards and validator hardware requirements can be greatly reduced with smaller shard size. With future in-memory tries, it's also important to limit the size of individual shards. + +## Specification + +### High level assumptions + +* Flat storage is enabled. +* Shard split boundary is predetermined and hardcoded. In other words, necessity of shard splitting is manually decided. +* For the time being resharding as an event is only going to happen once but we would still like to have the infrastructure in place to handle future resharding events with ease. +* Merkle Patricia Trie is the underlying data structure for the protocol state. +* Epoch is at least 6 hrs long for resharding to complete. + +### High level requirements + +* Resharding must be fast enough so that both state sync and resharding can happen within one epoch. +* Resharding should work efficiently within the limits of the current hardware requirements for nodes. +* Potential failures in resharding may require intervention from node operator to recover. +* No transaction or receipt must be lost during resharding. +* Resharding must work regardless of number of existing shards. +* No apps, tools or code should hardcode the number of shards to 4. + +### Out of scope + +* Dynamic resharding + * automatically scheduling resharding based on shard usage/capacity + * automatically determining the shard layout +* Merging shards or boundary adjustments +* Shard reshuffling + +### Required protocol changes + +A new protocol version will be introduced specifying the new shard layout which would be picked up by the resharding logic to split the shard. + +### Required state changes + +* For the duration of the resharding the node will need to maintain a snapshot of the flat state and related columns. As the main database and the snapshot diverge this will cause some extent of storage overhead. +* For the duration of the epoch before the new shard layout takes effect, the node will need to maintain the state and flat state of shards in the old and new layout at the same time. The State and FlatState columns will grow up to approx 2x the size. The processing overhead should be minimal as the chunks will still be executed only on the parent shards. There will be increased load on the database while applying changes to both the parent and the children shards. +* The total storage overhead is estimated to be on the order of 100GB for mainnet RPC nodes and 2TB for mainnet archival nodes. For testnet the overhead is expected to be much smaller. + +### Resharding flow + +* The new shard layout will be agreed on offline by the protocol team and hardcoded in the reference implementation. + * The first resharding will be scheduled soon after this NEP is merged. The new shard layout boundary accounts will be: ```["aurora", "aurora-0", "kkuuue2akv_1630967379.near", "tge-lockup.sweat"]```. + * Subsequent reshardings will be scheduled as needed, without further NEPs, unless significant changes are introduced. +* In epoch T, past the protocol version upgrade date, nodes will vote to switch to the new protocol version. The new protocol version will contain the new shard layout. +* In epoch T, in the last block of the epoch, the EpochConfig for epoch T+2 will be set. The EpochConfig for epoch T+2 will have the new shard layout. +* In epoch T + 1, all nodes will perform the state split. The child shards will be kept up to date with the blockchain up until the epoch end first via catchup, and later as part of block postprocessing state application. +* In epoch T + 2, the chain will switch to the new shard layout. + +## Reference Implementation + +The implementation heavily re-uses the implementation from [NEP-40](https://github.com/near/NEPs/blob/master/specs/Proposals/0040-split-states.md). Below are listed the major differences and additions. + +### Code pointers to the proposed implementation + +* [new shard layout](https://github.com/near/nearcore/blob/c9836ab5b05c229da933d451fe8198d781f40509/core/primitives/src/shard_layout.rs#L161) +* [the main logic for splitting states](https://github.com/near/nearcore/blob/c9836ab5b05c229da933d451fe8198d781f40509/chain/chain/src/resharding.rs#L280) +* [the main logic for applying chunks to split states](https://github.com/near/nearcore/blob/c9836ab5b05c229da933d451fe8198d781f40509/chain/chain/src/update_shard.rs#L315) +* [the main logic for garbage collecting state from parent shard](https://github.com/near/nearcore/blob/c9836ab5b05c229da933d451fe8198d781f40509/chain/chain/src/store.rs#L2335) + +### Flat Storage + +The old implementation of resharding relied on iterating over the full trie state of the parent shard in order to build the state for the children shards. This implementation was suitable at the time but since then the state has grown considerably and this implementation is now too slow to fit within a single epoch. The new implementation relies on iterating through the flat storage in order to build the children shards quicker. Based on benchmarks, splitting the largest shard by using flat storage can take around 15 min without throttling and around 3 hours with throttling to maintain the block production rate. + +The new implementation will also propagate the flat storage for the children shards and keep it up to date with the chain until the switch to the new shard layout in the next epoch. The old implementation didn't handle this case because the flat storage didn't exist back then. + +In order to ensure consistent view of the flat storage while splitting the state the node will maintain a snapshot of the flat state and related columns as of the last block of the epoch prior to resharding. The existing implementation of flat state snapshots used in State Sync will be used for this purpose. + +### Handling receipts, gas burnt and balance burnt + +When resharding, extra care should be taken when handling receipts in order to ensure that no receipts are lost or duplicated. The gas burnt and balance burnt also need to be correctly handled. The old resharding implementation for handling receipts, gas burnt and balance burnt relied on the fact in the first resharding there was only a single parent shard to begin with. The new implementation will provide a more generic and robust way of reassigning the receipts to the child shards, gas burnt, and balance burnt, that works for arbitrary splitting of shards, regardless of the previous shard layout. + +### New shard layout + +The first release of the resharding v2 will contain a new shard layout where one of the existing shards will be split into two smaller shards. Furthermore additional reshardings can be scheduled in subsequent releases without additional NEPs unless the need for it arises. A new shard layout can be determined and will be scheduled and executed with the next protocol upgrade. Resharding will typically happen by splitting one of the existing shards into two smaller shards. The new shard layout will be created by adding a new boundary account that will be determined by analysing the storage and gas usage metrics within the shard and selecting a point that will divide the shard roughly in half in accordance to the mentioned metrics. Other metrics can also be used based on requirements. + +### Removal of Fixed shards + +Fixed shards was a feature of the protocol that allowed for assigning specific accounts and all of their recursive sub accounts to a predetermined shard. This feature was only used for testing and was never used in production. Fixed shards feature unfortunately breaks the contiguity of shards and is not compatible with the new resharding flow. A sub account of a fixed shard account can fall in the middle of account range that belongs to a different shard. This property of fixed shards made it particularly hard to reason about and implement efficient resharding. + +For example in a shard layout with boundary accounts [`b`, `d`] the account space is cleanly divided into three shards, each spanning a contiguous range and account ids: + +* 0 - `:b` +* 1 - `b:d` +* 2 - `d:` + +Now if we add a fixed shard `f` to the same shard layout, then any we'll have 4 shards but neither is contiguous. Accounts such as `aaa.f`, `ccc.f`, `eee.f` that would otherwise belong to shards 0, 1 and 2 respectively are now all assigned to the fixed shard and create holes in the shard account ranges. + +It's also worth noting that there is no benefit to having accounts colocated in the same shard. Any transaction or receipt is treated the same way regardless of crossing shard boundary. + +This was implemented ahead of this NEP and the fixed shards feature was **removed**. + +### Garbage collection + +In epoch T+2 once resharding is completed, we can delete the trie state and the flat state related to the parent shard. In practice, this is handled as part of the garbage collection code. While garbage collecting the last block of epoch T+1, we go ahead and clear all the data associated with the parent shard from the trie cache, flat storage, and RocksDB state associated with trie state and flat storage. + +### Transaction pool + +The transaction pool is sharded i.e. it groups transactions by the shard where each transaction should be converted to a receipt. The transaction pool was previously sharded by the ShardId. Unfortunately ShardId is insufficient to correctly identify a shard across a resharding event as ShardIds change domain. The transaction pool was migrated to group transactions by ShardUId instead, and a transaction pool resharding was implemented to reassign transaction from parent shard to children shards right before the new shard layout takes effect. The ShardUId contains the version of the shard layout which allows differentiating between shards in different shard layouts. + +This was implemented ahead of this NEP and the transaction pool is now fully **migrated** to ShardUId. + +## Alternatives + +### Why is this design the best in the space of possible designs? + +This design is simple, robust, safe, and meets all requirements. + +### What other designs have been considered and what is the rationale for not choosing them? + +#### Alternative implementations + +* Splitting the trie by iterating over the boundaries between children shards for each trie record type. This implementation has the potential to be faster but it is more complex and it would take longer to implement. We opted in for the much simpler one using flat storage given it is already quite performant. +* Changing the trie structure to have the account id first and type of record later. This change would allow for much faster resharding by only iterating over the nodes on the boundary. This approach has two major drawbacks without providing too many benefits over the previous approach of splitting by each trie record type. + 1) It would require a massive migration of trie. + 2) We would need to maintain the old and the new trie structure forever. +* Changing the storage structure by having the storage key to have the format of `account_id.node_hash`. This structure would make it much easier to split the trie on storage level because the children shards are simple sub-ranges of the parent shard. Unfortunately we found that the migration would not be feasible. +* Changing the storage structure by having the key format as only node_hash and dropping the ShardUId prefix. This is a feasible approach but it adds complexity to the garbage collection and data deletion, specially when nodes would start tracking only one shard. We opted in for the much simpler one by using the existing scheme of prefixing storage entries by shard uid. + +#### Other considerations + +* Dynamic Resharding - we have decided to not implement the full dynamic resharding at this time. Instead we hardcode the shard layout and schedule it manually. The reasons are as follows: + * We prefer incremental process of introducing resharding to make sure that it is robust and reliable, as well as give the community the time to adjust. + * Each resharding increases the potential total load on the system. We don't want to allow it to grow until full sharding is in place and we can handle that increase. +* Extended shard layout adjustments - we have decided to only implement shard splitting and not implement any other operations. The reasons are as follows: + * In this iteration we only want to perform splitting. + * The extended adjustments are currently not justified. Both merging and boundary moving may be useful in the future when the traffic patterns change and some shard become underutilized. In the nearest future we only predict needing to reduce the size of the heaviest shards. + +### What is the impact of not doing this? + +We need resharding in order to scale up the system. Without resharding eventually shards would grow so big (in either storage or cpu usage) that a single node would not be able to handle it. Additionally, this clears up the path to implement in-memory tries as we need to store the whole trie structure in limited RAM. In the future smaller shard size would lead to faster syncing of shard data when nodes start tracking just one shard. + +## Integration with State Sync + +There are two known issues in the integration of resharding and state sync: + +* When syncing the state for the first epoch where the new shard layout is used. In this case the node would need to apply the last block of the previous epoch. It cannot be done on the children shard as on chain the block was applied on the parent shards and the trie related gas costs would be different. +* When generating proofs for incoming receipts. The proof for each of the children shards contains only the receipts of the shard but it's generated on the parent shard layout and so may not be verified. + +In this NEP we propose that resharding should be rolled out first, before any real dependency on state sync is added. We can then safely roll out the resharding logic and solve the above mentioned issues separately. We believe at least some of the issues can be mitigated by the implementation of new pre-state root and chunk execution design. + +## Integration with Stateless Validation + +The Stateless Validation requires that chunk producers provide proof of correctness of the transition function from one state root to another. That proof for the first block after the new shard layout takes place will need to prove that the entire state split was correct as well as the state transition. + +In this NEP we propose that resharding should be rolled out first, before stateless validation. We can then safely roll out the resharding logic and solve the above mentioned issues separately. This issue was discussed with the stateless validation experts and we are cautiously optimistic that the integration will be possible. The most concerning part is the proof size and we believe that it should be small enough thanks to the resharding touching relatively small number of trie nodes - on the order of the depth of the trie. + +## Future fast-followups + +### Resharding should work even when validators stop tracking all shards + +As mentioned above under 'Integration with State Sync' section, initial release of resharding v2 will happen before the full implementation of state sync and we plan to tackle the integration between resharding and state sync after the next shard split (Won't need a separate NEP as the integration does not require protocol change.) + +### Resharding should work after stateless validation is enabled + +As mentioned above under 'Integration with Stateless Validation' section, the initial release of resharding v2 will happen before the full implementation of stateless validation and we plan to tackle the integration between resharding and stateless validation after the next shard split (May need a separate NEP depending on implementation detail.) + +## Future possibilities + +### Further reshardings + +This NEP introduces both an implementation of resharding and an actual resharding to be done in the production networks. Further reshardings can also be performed in the future by adding a new shard layout and setting the shard layout for the desired protocol version in the `AllEpochConfig`. + +### Dynamic resharding + +As noted above, dynamic resharding is out of scope for this NEP and should be implemented in the future. Dynamic resharding includes the following but not limited to: + +* Automatic determination of split boundary based on parameters like traffic, gas usage, state size, etc. +* Automatic scheduling of resharding events + +### Extended shard layout adjustments + +In this NEP we only propose supporting splitting shards. This operation should be more than sufficient for the near future but eventually we may want to add support for more sophisticated adjustments such as: + +* Merging shards together +* Moving the boundary account between two shards + +### Localization of resharding event to specific shard + +As of today, at the RocksDB storage layer, we have the ShardUId, i.e. the ShardId along with the ShardVersion, as a prefix in the key of trie state and flat state. During a resharding event, we increment the ShardVersion by one, and effectively remap all the current parent shards to new child shards. This implies we can't use the same underlying key value pairs for store and instead would need to duplicate the values with the new ShardUId prefix, even if a shard is unaffected and not split. + +In the future, we would like to potentially change the schema in a way such that only the shard that is splitting is impacted by a resharding event, so as to avoid additonal work done by nodes tracking other shards. + +### Other useful features + +* Removal of shard uids and introducing globally unique shard ids +* Account colocation for low latency across account call - In case we start considering synchronous execution environment, colocating associated accounts (e.g. cross contract call between them) in the same shard can increase the efficiency +* Shard purchase/reservation - When someone wants to secure entirety of limitation on a single shard (e.g. state size limit), they can 'purchase/reserve' a shard so it can be dedicated for them (similar to how Aurora is set up) + +## Consequences + +### Positive + +* Workload across shards will be more evenly distributed. +* Required space to maintain state (either in memory or in persistent disk) will be smaller. This is useful for in-memory tries. +* State sync overhead will be smaller with smaller state size. + +### Neutral + +* Number of shards would increase. +* Underlying trie structure and data structure are not going to change. +* Resharding will create dependency on flat state snapshots. +* The resharding process, as of now, is not fully automated. Analyzing shard data, determining the split boundary, and triggering an actual shard split all need to be manually curated and tracked. + +### Negative + +* During resharding, a node is expected to require more resources as it will first need to copy state data from the parent shard to the child shard, and then will have to apply trie and flat state changes twice, once for the parent shard and once for the child shards. +* Increased potential for apps and tools to break without proper shard layout change handling. + +### Backwards Compatibility + +Any light clients, tooling or frameworks external to nearcore that have the current shard layout or the current number of shards hardcoded may break and will need to be adjusted in advance. The recommended way for fixing it is querying an RPC node for the shard layout of the relevant epoch and using that information in place of the previously hardcoded shard layout or number of shards. The shard layout can be queried by using the `EXPERIMENTAL_protocol_config` rpc endpoint and reading the `shard_layout` field from the result. A dedicated endpoint may be added in the future as well. + +Within nearcore we do not expect anything to break with this change. Yet, shard splitting can introduce additional complexity on replayability. For instance, as target shard of a receipt and belonging shard of an account can change with shard splitting, shard splitting must be replayed along with transactions at the exact epoch boundary. + +## Changelog + +[The changelog section provides historical context for how the NEP developed over time. Initial NEP submission should start with version 1.0.0, and all subsequent NEP extensions must follow [Semantic Versioning](https://semver.org/). Every version should have the benefits and concerns raised during the review. The author does not need to fill out this section for the initial draft. Instead, the assigned reviewers (Subject Matter Experts) should create the first version during the first technical review. After the final public call, the author should then finalize the last version of the decision context.] + +### 1.0.0 - Initial Version + +> Placeholder for the context about when and who approved this NEP version. + +#### Benefits + +> List of benefits filled by the Subject Matter Experts while reviewing this version: + +* Benefit 1 +* Benefit 2 + +#### Concerns + +> Template for Subject Matter Experts review for this version: +> Status: New | Ongoing | Resolved + +| # | Concern | Resolution | Status | +| --: | :------ | :--------- | -----: | +| 1 | | | | +| 2 | | | | + +## Copyright + +Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). From 1208e4c31039d95e0facacf2d5ff7d300ec519c4 Mon Sep 17 00:00:00 2001 From: Benjamin Kurrek <57506486+BenKurrek@users.noreply.github.com> Date: Sat, 27 Jan 2024 13:18:07 -0500 Subject: [PATCH 136/150] NEP-452 Linkdrop Standard (#452) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Discussions found [here](https://gov.near.org/t/official-linkdrop-standard/32463/1). --- ## NEP Status *(Updated by NEP moderators)* SME reviews: * [x] Wallet Standards SME: @joe-rlo https://github.com/near/NEPs/pull/452#issuecomment-1411440556 * [x] Contract Standards SME: @frol https://github.com/near/NEPs/pull/452#issuecomment-1446770345 Contract Standards WG voting indications: * 👍 @frol https://github.com/near/NEPs/pull/452#issuecomment-1446770345 * 👍 @abacabadabacaba https://github.com/near/NEPs/pull/452#issuecomment-1568711368 * 👍 @fadeevab https://github.com/near/NEPs/pull/452#issuecomment-1511883507 * "so so" @robert-zaremba, small bits to update: https://github.com/near/NEPs/pull/452#pullrequestreview-1391472044 Wallet Standards WG voting indications: * 👍 @Cameron-Banyan https://github.com/near/NEPs/pull/452#issuecomment-1511632168 * ❔ @MaximusHaximus * ❔ @esaminu --------- Co-authored-by: Marcelo Fornet Co-authored-by: kenobijon <108417131+kenobijon@users.noreply.github.com> Co-authored-by: Vlad Frolov Co-authored-by: Robert Zaremba Co-authored-by: Alexander Fadeev Co-authored-by: gagdiez Co-authored-by: Noah Jelich <12912633+njelich@users.noreply.github.com> --- neps/nep-0452.md | 243 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 243 insertions(+) create mode 100644 neps/nep-0452.md diff --git a/neps/nep-0452.md b/neps/nep-0452.md new file mode 100644 index 000000000..3fb1c6472 --- /dev/null +++ b/neps/nep-0452.md @@ -0,0 +1,243 @@ +--- +NEP: 452 +Title: Linkdrop Standard +Author: Ben Kurrek , Ken Miyachi +DiscussionsTo: https://gov.near.org/t/official-linkdrop-standard/32463/1 +Status: Draft +Type: Standards Track +Category: Contract +Version: 1.0.0 +Created: 24-Jan-2023 +Updated: 19-Apr-2023 +--- + +## Summary + +A standard interface for linkdrops that support $NEAR, fungible tokens, non-fungible tokens, and is extensible to support new types in the future. + +Linkdrops are a simple way to send assets to someone by providing them with a link. This link can be embedded into a QR code, sent via email, text or any other means. Within the link, there is a private key that allows the holder to call a method that can create an account and send it assets. Alternatively, if the holder has an account, the assets can be sent there as well. + +By definition, anyone with an access key can interact with the blockchain and since there is a private key embedded in the link, this removes the need for the end-user to have a wallet. + +## Motivation + +Linkdrops are an extremely powerful tool that enable seamless onboarding and instant crypto experiences with the click of a link. The original [near-linkdrop](https://github.com/near/near-linkdrop) contract provides a minimal interface allowing users to embed $NEAR within an access key and create a simple Web2 style link that can then be used as a means of onboarding. This simple $NEAR linkdrop is not enough as many artists, developers, event coordinators, and applications want to drop more digital assets such as NFTs, FTs, tickets etc. + +As linkdrop implementations start to push the boundaries of what’s possible, new data structures, methods, and interfaces are being developed. There needs to be a standard data model and interface put into place to ensure assets can be claimed independent of the contract they came from. If not, integrating any application with linkdrops will require customized solutions, which would become cumbersome for the developer and deteriorate the user onboarding experience. The linkdrop standard addresses these issues by providing a simple and extensible standard data model and interface. + +The initial discussion can be found [here](https://gov.near.org/t/official-linkdrop-standard/32463/1). + +## Specification + +### Example Scenarios + +_Pre-requisite Steps_: Linkdrop creation: +The linkdrop creator that has an account with some $NEAR: + +- creates a keypair locally (`pubKey1`, `privKey1`). (The keypair is not written to chain at this time) +- calls a method on a contract that implements the linkdrop standard in order to create the drop. The `pubKey1` and desired $NEAR amount are both passed in as arguments. +- The contract maps the `pubKey1` to the desired balance for the linkdrop (`KeyInfo` record). +- The contract then adds the `pubKey1` as a function call access key with the ability to call `claim` and `create_account_and_claim`. This means that anyone with the `privKey1` (see above), can sign a transaction on behalf of the contract (signer id set to contract id) with a function call to call one of the mentioned functions to claim the assets. + +#### Claiming a linkdrop without a NEAR Account + +A user with _no_ account can claim the assets associated with an existing public key, already registered in the linkdrop contract: + +- generates a new keypair (`pubKey2`, `privKey2`) locally. (This new keypair is not written to chain) +- chooses a new account ID such as benji.near. +- calls `create_account_and_claim`. The transaction is signed on behalf of the linkdrop contract (`signer_id` is set to the contract address) using `privKey1`. + - the args of this function call will contain both `pubKey2` (which will be used to create a full access key for the new account) and the account ID itself. + - the linkdrop contract will delete the access key associated with `pubKey1` so that it cannot be used again. + - the linkdrop contract will create the new account and transfer the funds to it alongside any other assets. +- the user will be able to sign transactions on behalf of the new account using `privKey2`. + +#### Claiming a linkdrop with a NEAR Account + +A user with an _existing_ account can claim the assets with an existing public key, already registered in the linkdrop contract: + +- calls `claim`. The transaction is signed on behalf of the linkdrop contract (`signer_id` is set to the contract address) using `privKey1`. + - the args of this function call will simply contain the user's existing account ID. + - the linkdrop contract will delete the access key associated with `pubKey1` so that it cannot be used again. + - the linkdrop contract will transfer the funds to that account alongside any other assets. + +```ts +/// Information about a specific public key. +type KeyInfo = { + /// How much Gas should be attached when the key is used to call `claim` or `create_account_and_claim`. + /// It is up to the smart contract developer to calculate the required gas (which can be done either automatically on the contract or on the client-side). + required_gas: string, + + /// yoctoNEAR$ amount that will be sent to the account that claims the linkdrop (either new or existing) + /// when the key is successfully used. + yoctonear: string, + + /// If using the NFT standard extension, a set of NFTData can be linked to the public key + /// indicating that all those assets will be sent to the account that claims the linkdrop (either new or + /// existing) when the key is successfully used. + nft_list: NFTData[] | null, + + /// If using the FT standard extension, a set of FTData can be linked to the public key + /// indicating that all those assets will be sent to the account that claims the linkdrop (either new or + /// existing) when the key is successfully used. + ft_list: FTData[] | null + + /// ... other types can be introduced and the standard is easily extendable. +} + + +/// Data outlining a specific Non-Fungible Token that should be sent to the claiming account +/// (either new or existing) when a key is successfully used. +type NFTData = { + /// the id of the token to transfer + token_id: string, + + /// The valid NEAR account indicating the Non-Fungible Token contract. + contract_id: string +} + + +/// Data outlining Fungible Tokens that should be sent to the claiming account +/// (either new or existing) when a key is successfully used. +type FTData = { + /// The number of tokens to transfer, wrapped in quotes and treated + /// like a string, although the number will be stored as an unsigned integer + /// with 128 bits. + amount: string, + + /// The valid NEAR account indicating the Fungible Token contract. + contract_id: string +} + +/****************/ +/* VIEW METHODS */ +/****************/ + +/// Allows you to query for the amount of $NEAR tokens contained in a linkdrop corresponding to a given public key. +/// +/// Requirements: +/// * Panics if the key does not exist. +/// +/// Arguments: +/// * `key` the public counterpart of the key used to sign, expressed as a string with format ":" (e.g. "ed25519:6TupyNrcHGTt5XRLmHTc2KGaiSbjhQi1KHtCXTgbcr4Y") +/// +/// Returns a string representing the $yoctoNEAR amount associated with a given public key +function get_key_balance(key: string) -> string; + +/// Allows you to query for the `KeyInfo` corresponding to a given public key. This method is preferred over `get_key_balance` as it provides more information about the key. +/// +/// Requirements: +/// * Panics if the key does not exist. +/// +/// Arguments: +/// * `key` the public counterpart of the key used to sign, expressed as a string with format ":" (e.g. "ed25519:6TupyNrcHGTt5XRLmHTc2KGaiSbjhQi1KHtCXTgbcr4Y") +/// +/// Returns `KeyInfo` associated with a given public key +function get_key_information(key: string) -> KeyInfo; + +/******************/ +/* CHANGE METHODS */ +/******************/ + +/// Transfer all assets linked to the signer’s public key to an `account_id`. +/// If the transfer fails for whatever reason, it is up to the smart contract developer to +/// choose what should happen. For example, the contract can choose to keep the assets +/// or send them back to the original linkdrop creator. +/// +/// Requirements: +/// * The predecessor account *MUST* be the current contract ID. +/// * The `account_id` MUST be an *initialized* NEAR account. +/// * The assets being sent *MUST* be associated with the signer’s public key. +/// * The assets *MUST* be sent to the `account_id` passed in. +/// +/// Arguments: +/// * `account_id` the account that should receive the linkdrop assets. +/// +/// Returns `true` if the claim was successful meaning all assets were sent to the `account_id`. +function claim(account_id: string) -> Promise; + +/// Creates a new NEAR account and transfers all assets linked to the signer’s public key to +/// the *newly created account*. If the transfer fails for whatever reason, it is up to the +/// smart contract developer to choose what should happen. For example, the contract can +/// choose to keep the assets or return them to the original linkdrop creator. +/// +/// Requirements: +/// * The predecessor account *MUST* be the current contract ID. +/// * The assets being sent *MUST* be associated with the signer’s public key. +/// * The assets *MUST* be sent to the `new_account_id` passed in. +/// * The newly created account *MUST* have a new access key added to its account (either +/// full or limited access) in the same receipt that the account was created in. +/// * The Public key must be in a binary format with base58 string serialization with human-readable curve. +/// The key types currently supported are secp256k1 and ed25519. Ed25519 public keys accepted are 32 bytes +/// and secp256k1 keys are the uncompressed 64 format. +/// +/// Arguments: +/// * `new_account_id`: the valid NEAR account which is being created and should +/// receive the linkdrop assets +/// * `new_public_key`: the valid public key that should be used for the access key added to the newly created account (serialized with borsh). +/// +/// Returns `true` if the claim was successful meaning the `new_account_id` was created and all assets were sent to it. +function create_account_and_claim(new_account_id: string, new_public_key: string) -> Promise; +``` + +## Reference Implementation + +Below are some references for linkdrop contracts. + +- [Link Drop Contract](https://github.com/near/near-linkdrop) + +- [Keypom Contract](https://github.com/keypom/keypom) + +## Security Implications + +1. Linkdrop Creation + Linkdrop creation involves creating keypairs that, when used, have access to assets such as $NEAR, FTs, NFTs, etc. These keys should be limited access and restricted to specific functionality. For example, they should only have permission to call `claim` and `create_account_and_claim`. Since the keys allow the holder to sign transactions on behalf of the linkdrop contract, without the proper security measures, they could be used in a malicious manner (for example executing private methods or owner-only functions). + + Another important security implication of linkdrop creation is to ensure that only one key is mapped to a set of assets at any given time. Externally, assets such as FTs, and NFTs belong to the overall linkdrop contract account rather than a specific access key. It is important to ensure that specific keys can only claim assets that they are mapped to. + +2. Linkdrop Key Management + Key management is a critical safety component of linkdrops. The linkdrop contract should implement a key management strategy for keys such that a reentrancy attack does not occur. For example, one strategy may be to "lock" or mark a key as "in transfer" such that it cannot be used again until the transfer is complete. + +3. Asset Refunds & Failed Claims + Given that linkdrops could contain multiple different assets such as NFTs, or fungible tokens, sending assets might happen across multiple blocks. If the claim was unsuccessful (such as passing in an invalid account ID), it is important to ensure that all state is properly managed and assets are optionally refunded depending on the linkdrop contract's implementation. + +4. Fungible Tokens & Future Data + Fungible token contracts require that anyone receiving tokens must be registered. For this reason, it is important to ensure that storage for accounts claiming linkdrops is paid for. This concept can be extended to any future data types that may be added. You must ensure that all the pre-requisite conditions have been met for the asset that is being transferred. + +5. Tokens Properly Sent to Linkdrop Contract + Since the linkdrop contract facilitates the transfer of assets including NFTs, and FTs, it is important to ensure that those tokens have been properly sent to the linkdrop contract prior to claiming. In addition, since all the tokens are in a shared pool, you must ensure that the linkdrop contract cannot claim assets that do not belong to the key that is being used to claim. + +It is also important to note that not every linkdrop is valid. Drops can expire, funds can be lazily sent to the contract (as seen in the case of fungible and non-fungible tokens) and the supply can be limited. + +## Alternatives + +#### Why is this design the best in the space of possible designs? + +This design allows for flexibility and extensibility of the standard while providing a set of criteria that cover the majority of current linkdrop use cases. The design was heavily inspired by current, functional NEPs such as the Fungible Token and Non-Fungible Token standards. + +#### What other designs have been considered and what is the rationale for not choosing them? + +A generic data struct that all drop types needed to inherit from. This struct contained a name and some metadata in the form of stringified JSON. This made it easily extensible for any new types down the road. The rationale for not choosing this design was both simplicity and flexibility. Having one data struct requires keys to be of one type only. In reality, there can be many at once. In addition, having a generic, open-ended metadata field could lead to many interpretations and different designs. We chose to use a KeyInfo struct that can be easily extensible and can cover all use-cases by having optional vectors of different data types. The proposed standard is simple, supports drops with multiple assets, and is backwards compatible with all previous linkdrops, and can be extended very easily. + +A standard linkdrop creation interface. A standardized linkdrop creation interface would provide data models and functions to ensure linkdrops were created and stored in a specific format. The rationale for not choosing this design was that is was too restrictive. Standardizing linkdrop creation adds complexity and reduces flexibility by restricting linkdrop creators in the process in which linkdrops are created, and potentially limiting linkdrop functionality. The functionality of the linkdrop creation, such as refunding of assets, access keys, and batch creation, should be chosen by the linkdrop creator and live within the linkdrop creator platform. Further, linkdrop creation is often not displayed to end users and there is not an inherent value proposition for a standardized linkdrop creation interface from a client perspective. + +#### What is the impact of not doing this? + +The impact of not doing this is creating a fragmented ecosystem of linkdrops, increasing the friction for user onboarding. Linkdrop claim pages (e.g. wallet providers) would have to implement custom integrations for every linkdrop provider platform. Inherently this would lead to a bad user experience when new users are onboarding and interacting with linkdrops in general. + +## Future possibilities + +- Linkdrop creation interface + +- Bulk linkdrop management (create, update, claim) + +- Function call data types (allowing for funder defined functions to be executed when a linkdrop is claimed) + +- Optional configurations added to KeyInfo which can include multi-usekeys, time-based claiming etc… + +- Standard process for how links connect to claim pages (i.e a standardized URL such as an app’s baseUrl/contractId= [LINKDROP_CONTRACT]&secretKey=[SECRET_KEY] + +- Standard for deleting keys and refunding assets. + +## Copyright + +Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). From 747a55f2b9b6e1f47ba9bfe5ddf18ebfaa70340b Mon Sep 17 00:00:00 2001 From: Robert Zaremba Date: Fri, 23 Feb 2024 15:59:07 +0100 Subject: [PATCH 137/150] nep-393: add class metadata interface (#528) In https://github.com/near/NEPs/pull/393 we defined Issuer (an entity authorized to mint SBTs in the registry) and SBT Class. We also defined Issuer Metadata and Token Metadata, but we didn't provide interface for class metadata. This was implemented in the reference implementation (in one of the subsequent revisions), but was not backported to the NEP. In this PR * we fix the name of the issuer interface from `SBTContract` to `SBTIssuer`. The original name is wrong and we oversight it in reviews. We talk everywhere about the issuer entity and issuer contract (even the header is _SBT Issuer interface_). * Renames `ContractMetadata` to `IssuerMetadata`. * added `ClassMetadata` struct and `sbt_class_metadata` function to the `SBTIssuer`. --------- Co-authored-by: Alexander Fadeev --- neps/nep-0393.md | 58 ++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 51 insertions(+), 7 deletions(-) diff --git a/neps/nep-0393.md b/neps/nep-0393.md index 9c10b0469..567a3ebe6 100644 --- a/neps/nep-0393.md +++ b/neps/nep-0393.md @@ -269,8 +269,9 @@ The Soulbound Token follows the NFT [NEP-171](https://github.com/near/NEPs/blob/ All time related attributes are defined in milliseconds (as per NEP-171). ```rust -/// ContractMetadata defines contract wide attributes, which describes the whole contract. -pub struct ContractMetadata { +/// IssuerMetadata defines contract wide attributes, which describes the whole contract. +/// Must be provided by the Issuer contract. See the `SBTIssuer` trait. +pub struct IssuerMetadata { /// Version with namespace, example: "sbt-1.0.0". Required. pub spec: String, /// Issuer Name, required, ex. "Mosaics" @@ -290,6 +291,25 @@ pub struct ContractMetadata { pub reference_hash: Option, } +/// ClassMetadata defines SBT class wide attributes, which are shared and default to all SBTs of +/// the given class. Must be provided by the Issuer contract. See the `SBTIssuer` trait. +pub struct ClassMetadata { + /// Issuer class name. Required to be not empty. + pub name: String, + /// If defined, should be used instead of `IssuerMetadata::symbol`. + pub symbol: Option, + /// An URL to an Icon. To protect fellow developers from unintentionally triggering any + /// SSRF vulnerabilities with URL parsers, we don't allow to set an image bytes here. + /// If it doesn't start with a scheme (eg: https://) then `IssuerMetadata::base_uri` + /// should be prepended. + pub icon: Option, + /// JSON or an URL to a JSON file with more info. If it doesn't start with a scheme + /// (eg: https://) then base_uri should be prepended. + pub reference: Option, + /// Base64-encoded sha256 hash of JSON from reference field. Required if `reference` is included. + pub reference_hash: Option, +} + /// TokenMetadata defines attributes for each SBT token. pub struct TokenMetadata { pub class: ClassId, // token class. Required. Must be non zero. @@ -448,12 +468,18 @@ Example **Soul Transfer** interface: ### SBT Issuer interface -SBTContract is the minimum required interface to be implemented by issuer. Other methods, such as a mint function, which requests the registry to proceed with token minting, is specific to an Issuer implementation (similarly, mint is not part of the FT standard). +SBTIssuer is the minimum required interface to be implemented by issuer. Other methods, such as a mint function, which requests the registry to proceed with token minting, is specific to an Issuer implementation (similarly, mint is not part of the FT standard). + +The issuer must provide metadata object of the Issuer. Optionally, Issuer can also provide metadata object for each token class. +Issuer level (contract) metadata, must provide information common to all tokens and all classes defined by the issuer. Class level metadata, must provide information common to all tokens of a given class. Information should be deduplicated and denormalized whenever possible. +Example: The issuer can set a default icon for all tokens (SBT) using `IssuerMetadata::icon` and additionally it can customize an icon of a particular token via `TokenMetadata::icon`. ```rust -pub trait SBTContract { - /// returns contract metadata - fn sbt_metadata(&self) -> ContractMetadata; +pub trait SBTIssuer { + /// Returns contract metadata. + fn sbt_metadata(&self) -> IssuerMetadata; + /// Returns SBT class metadata, or `None` if the class is not found. + fn sbt_class_metadata(&self, class: ClassId) -> Option; } ``` @@ -594,7 +620,7 @@ trait SBT { ## Reference Implementation -- Common [type definitions](https://github.com/near-ndc/i-am-human/tree/main/contracts/sbt) (events, traits). +- Common [type definitions](https://github.com/near-ndc/i-am-human/tree/master/contracts/sbt) (events, traits). - [I Am Human](https://github.com/near-ndc/i-am-human) registry and issuers. ## Consequences @@ -667,6 +693,24 @@ The Contract Standards Working Group members approved this NEP on June 30, 2023 | 9 | [Privacy](https://github.com/near/NEPs/pull/393/#issuecomment-1504309947) | Concerns have been addressed: [comment-1](https://github.com/near/NEPs/pull/393/#issuecomment-1504485420) and [comment2](https://github.com/near/NEPs/pull/393/#issuecomment-1505958549) | resolved | | 10 | @frol [suggested](https://github.com/near/NEPs/pull/393/#discussion_r1247879778) to use a struct in `sbt_recover` and `sbt_soul_transfer`. | Motivation to use pair `(number, bool)` rather than follow a common Iterator Pattern. Rust uses `Option` type for that, that works perfectly for languages with native Option type, but creates a "null" problem for anything else. Other common way to implement Iterator is the presented pair, which doesn't require extra type definition and reduces code size. | new | + +### v1.1.0 + + +In v1.0.0 we defined Issuer (an entity authorized to mint SBTs in the registry) and SBT Class. We also defined Issuer Metadata and Token Metadata, but we didn't provide interface for class metadata. This was implemented in the reference implementation (in one of the subsequent revisions), but was not backported to the NEP. This update: + +- Fixes the name of the issuer interface from `SBTContract` to `SBTIssuer`. The original name is wrong and we oversight it in reviews. We talk everywhere about the issuer entity and issuer contract (even the header is SBT Issuer interface). +- Renames `ContractMetadata` to `IssuerMetadata`. +- Adds `ClassMetadata` struct and `sbt_class_metadata` function to the `SBTIssuer` interface. + +Reference implementation: [ContractMetadata, ClassMetadata, TokenMetadata](https://github.com/near-ndc/i-am-human/blob/registry/v1.8.0/contracts/sbt/src/metadata.rs#L18) and [SBTIssuer interface](https://github.com/near-ndc/i-am-human/blob/registry/v1.8.0/contracts/sbt/src/lib.rs#L49). + +#### Benefits + +- Improves the documentation and meaning of the issuer entity. +- Adds missing `ClassMetadata`. +- Improves issuer, class and token metadata documentation. + ## Copyright [Creative Commons Attribution 4.0 International Public License (CC BY 4.0)](https://creativecommons.org/licenses/by/4.0/) From 27e975ae12b56c8879c24d430153a08fb7588a9e Mon Sep 17 00:00:00 2001 From: gagdiez Date: Mon, 26 Feb 2024 23:47:55 +0100 Subject: [PATCH 138/150] fix: Fixed links to examples for NEP413 (#535) The links to the working example were broken, this commit fixes it --- neps/nep-0413.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/neps/nep-0413.md b/neps/nep-0413.md index 54da3906e..ef6230fc5 100644 --- a/neps/nep-0413.md +++ b/neps/nep-0413.md @@ -159,7 +159,7 @@ Non-web Wallets, such as [Ledger](https://www.ledger.com) can directly return th ## References -A full example on how to implement the `signMessage` method can be [found here](https://github.com/gagdiez/near-login/blob/main/tests/authentication/auth.ava.ts#L27-#L65). +A full example on how to implement the `signMessage` method can be [found here](https://github.com/gagdiez/near-login/blob/1650e25080ab2e8a8c508638a9ba9e9732e76036/server/tests/wallet.ts#L60-L77). ## Drawbacks From 30f3f18833440e712a71334e3796670e00e0d711 Mon Sep 17 00:00:00 2001 From: Andrey Gruzdev <44225021+Canvinus@users.noreply.github.com> Date: Thu, 18 Apr 2024 20:23:01 +0200 Subject: [PATCH 139/150] NEP-330 extension: Build details extension (#533) ## NEP-330: Source Metadata ## 1.2.0 - Build Details Extension ### Overview This update introduces build details to the contract metadata, containing necessary information about how the contract was built. This makes it possible for others to reproduce the same WASM of this contract. The idea first appeared in the [cargo-near SourceScan integration thread](https://github.com/near/cargo-near/issues/131). ### Benefits This NEP extension gives developers the capability to save all the required build details, making it possible to reproduce the same WASM code in the future. This ensures greater consistency in contracts and the ability to verify source code. With the assistance of tools like SourceScan and cargo-near, the development process on NEAR becomes significantly easier. --------- Co-authored-by: ztsalexey Co-authored-by: Alexander Fadeev Co-authored-by: Robert Zaremba Co-authored-by: Vlad Frolov --- neps/nep-0330.md | 137 +++++++++++++++++++++++++++++++---------------- 1 file changed, 91 insertions(+), 46 deletions(-) diff --git a/neps/nep-0330.md b/neps/nep-0330.md index 0d56e4018..6615165c4 100644 --- a/neps/nep-0330.md +++ b/neps/nep-0330.md @@ -1,25 +1,29 @@ --- NEP: 330 Title: Source Metadata -Author: Ben Kurrek , Osman Abdelnasir +Author: Ben Kurrek , Osman Abdelnasir , Andrey Gruzdev <@canvi>, Alexey Zenin <@alexthebuildr> DiscussionsTo: https://github.com/near/NEPs/discussions/329 Status: Approved Type: Standards Track Category: Contract -Version: 1.1.0 +Version: 1.2.0 Created: 27-Feb-2022 -Updated: 13-Jan-2023 +Updated: 19-Feb-2023 --- ## Summary -The contract source metadata is a standard interface that allows auditing and viewing source code for a deployed smart contract. Implementation of this standard is purely optional but is recommended for developers whose contracts are open source. +The contract source metadata represents a standardized interface designed to facilitate the auditing and inspection of source code associated with a deployed smart contract. Adoption of this standard remains discretionary; however, it is strongly advocated for developers who maintain an open-source approach to their contracts. This initiative promotes greater accountability and transparency within the ecosystem, encouraging best practices in contract development and deployment. ## Motivation -There is no trivial way of finding the source code or author of a deployed smart contract. Having a standard that outlines how to view the source code of an arbitrary smart contract creates an environment of openness and collaboration. +The incorporation of metadata facilitates the discovery and validation of deployed source code, thereby significantly reducing the requisite level of trust during code integration or interaction processes. -Additionally, we would like for wallets and dApps to be able to parse this information and determine which methods they are able to call and render UIs that provide that functionality. +The absence of an accepted protocol for identifying the source code or author contact details of a deployed smart contract presents a challenge. Establishing a standardized framework for accessing the source code of any given smart contract would foster a culture of transparency and collaborative engagement. + +Moreover, the current landscape does not offer a straightforward mechanism to verify the authenticity of a smart contract's deployed source code against its deployed version. To address this issue, it is imperative that metadata includes specific details that enable contract verification through reproducible builds. + +Furthermore, it is desirable for users and dApps to possess the capability to interpret this metadata, thereby identifying executable methods and generating UIs that facilitate such functionalities. This also extends to acquiring comprehensive insights into potential future modifications by the contract or its developers, enhancing overall system transparency and user trust. The initial discussion can be found [here](https://github.com/near/NEPs/discussions/329). @@ -31,22 +35,31 @@ There is a lot of information that can be held about a contract. Ultimately, we Successful implementations of this standard will introduce a new (`ContractSourceMetadata`) struct that will hold all the necessary information to be queried for. This struct will be kept on the contract level. -The metadata will include three optional fields: +The metadata will include optional fields: -- `version`: a string that references the specific commit hash or version of the code that is currently deployed on-chain. This can be included regardless of whether or not the contract is open-sourced and can also be used for organizational purposes. -- `link`: a string that references the link to the open-source code. This can be anything such as Github or a CID to somewhere on IPFS. +- `version`: a string that references the specific commit ID or a tag of the code currently deployed on-chain. Examples: `"v0.8.1"`, `"a80bc29"`. +- `link`: an URL to the currently deployed code. It must include version or a tag if using a GitHub or a GitLab link. Examples: "https://github.com/near/near-cli-rs/releases/tag/v0.8.1", "https://github.com/near/cargo-near-new-project-template/tree/9c16aaff3c0fe5bda4d8ffb418c4bb2b535eb420" or an IPFS CID. - `standards`: a list of objects (see type definition below) that enumerates the NEPs supported by the contract. If this extension is supported, it is advised to also include NEP-330 version 1.1.0 in the list (`{standard: "nep330", version: "1.1.0"}`). +- `build_info`: a build details object (see type definition below) that contains all the necessary information about how the contract was built, making it possible for others to reproduce the same WASM of this contract. ```ts type ContractSourceMetadata = { - version: string|null, // optional, commit hash being used for the currently deployed wasm. If the contract is not open-sourced, this could also be a numbering system for internal organization / tracking such as "1.0.0" and "2.1.0". - link: string|null, // optional, link to open source code such as a Github repository or a CID to somewhere on IPFS. - standards: Standard[]|null, // optional, standards and extensions implemented in the currently deployed wasm e.g. [{standard: "nep330", version: "1.1.0"},{standard: "nep141", version: "1.0.0"}]. + version: string|null, // optional, commit hash being used for the currently deployed WASM. If the contract is not open-sourced, this could also be a numbering system for internal organization / tracking such as "1.0.0" and "2.1.0". + link: string|null, // optional, link to open source code such as a Github repository or a CID to somewhere on IPFS, e.g., "https://github.com/near/cargo-near-new-project-template/tree/9c16aaff3c0fe5bda4d8ffb418c4bb2b535eb420" + standards: Standard[]|null, // optional, standards and extensions implemented in the currently deployed WASM, e.g., [{standard: "nep330", version: "1.1.0"},{standard: "nep141", version: "1.0.0"}]. + build_info: BuildInfo|null, // optional, details that are required for contract WASM reproducibility. } type Standard { - standard: string, // standard name e.g. "nep141" - version: string, // semantic version number of the Standard e.g. "1.0.0" + standard: string, // standard name, e.g., "nep141" + version: string, // semantic version number of the Standard, e.g., "1.0.0" +} + +type BuildInfo { + build_environment: string, // reference to a reproducible build environment docker image, e.g., "docker.io/sourcescan/cargo-near@sha256:bf488476d9c4e49e36862bbdef2c595f88d34a295fd551cc65dc291553849471" or something else pointing to the build environment. + source_code_snapshot: string, // reference to the source code snapshot that was used to build the contract, e.g., "git+https://github.com/near/cargo-near-new-project-template.git#9c16aaff3c0fe5bda4d8ffb418c4bb2b535eb420" or "ipfs://". + contract_path: string|null, // relative path to contract crate within the source code, e.g., "contracts/contract-one". Often, it is the root of the repository, so can be omitted. + build_command: string[], // the exact command that was used to build the contract, with all the flags, e.g., ["cargo", "near", "build", "--no-abi"]. } ``` @@ -56,54 +69,70 @@ In order to view this information, contracts must include a getter which will re function contract_source_metadata(): ContractSourceMetadata {} ``` +### Ensuring WASM Reproducibility + +#### Build Environment Docker Image + +When using a Docker image as a reference, it's important to specify the digest of the image to ensure reproducibility, since a tag could be reassigned to a different image. + +### Paths Inside Docker Image + +During the build, paths from the source of the build as well as the location of the cargo registry could be saved into WASM, which affects reproducibility. Therefore, we need to ensure that everyone uses the same paths inside the Docker image. We propose using the following paths: + +- `/home/near/code` - Mounting volume from the host system containing the source code. +- `/home/near/.cargo` - Cargo registry. + +#### Cargo.lock + +It is important to have `Cargo.lock` inside the source code snapshot to ensure reproducibility. Example: https://github.com/near/core-contracts. + ## Reference Implementation -As an example, say there was an NFT contract deployed on-chain which was currently using the commit hash `39f2d2646f2f60e18ab53337501370dc02a5661c` and had its open source code located at `https://github.com/near-examples/nft-tutorial`. This contract would then include a struct which has the following fields: +As an example, consider a contract located at the root path of the repository, which was deployed using the `cargo near deploy --no-abi` and environment docker image `sourcescan/cargo-near@sha256:bf488476d9c4e49e36862bbdef2c595f88d34a295fd551cc65dc291553849471`. Its latest commit hash is `9c16aaff3c0fe5bda4d8ffb418c4bb2b535eb420`, and its open-source code can be found at `https://github.com/near/cargo-near-new-project-template`. This contract would then include a struct with the following fields: ```ts type ContractSourceMetadata = { - version: "39f2d2646f2f60e18ab53337501370dc02a5661c" - link: "https://github.com/near-examples/nft-tutorial", - standards: [ - { - standard: "nep330", - version: "1.1.0" - }, - { - standard: "nep171", - version: "1.0.0" - }, - { - standard: "nep177", - version: "2.0.0" + version: "1.0.0", + link: "https://github.com/near/cargo-near-new-project-template/tree/9c16aaff3c0fe5bda4d8ffb418c4bb2b535eb420", + standards: [ + { + standard: "nep330", + version: "1.1.0" + } + ], + build_info: { + build_environment: "docker.io/sourcescan/cargo-near@sha256:bf488476d9c4e49e36862bbdef2c595f88d34a295fd551cc65dc291553849471", + source_code_snapshot: "git+https://github.com/near/cargo-near-new-project-template.git#9c16aaff3c0fe5bda4d8ffb418c4bb2b535eb420", + contract_path: ".", + build_command: ["cargo", "near", "deploy", "--no-abi"] } - ] } + ``` -If someone were to call the view function `contract_metadata`, the contract would return: +Calling the view function `contract_source_metadata`, the contract would return: ```bash { - version: "39f2d2646f2f60e18ab53337501370dc02a5661c" - link: "https://github.com/near-examples/nft-tutorial", + version: "1.0.0" + link: "https://github.com/near/cargo-near-new-project-template/tree/9c16aaff3c0fe5bda4d8ffb418c4bb2b535eb420", standards: [ { standard: "nep330", version: "1.1.0" - }, - { - standard: "nep171", - version: "1.0.0" - }, - { - standard: "nep177", - version: "2.0.0" } - ] + ], + build_info: { + build_environment: "docker.io/sourcescan/cargo-near@sha256:bf488476d9c4e49e36862bbdef2c595f88d34a295fd551cc65dc291553849471", + source_code_snapshot: "git+https://github.com/near/cargo-near-new-project-template.git#9c16aaff3c0fe5bda4d8ffb418c4bb2b535eb420", + contract_path: ".", + build_command: ["cargo", "near", "deploy", "--no-abi"] + } } ``` +This could be used by SourceScan to reproduce the same WASM using the build details and to verify the on-chain WASM code with the reproduced one. + An example implementation can be seen below. ```rust @@ -113,17 +142,26 @@ pub struct Contract { pub contract_metadata: ContractSourceMetadata } -// Standard structure +/// NEP supported by the contract. pub struct Standard { pub standard: String, pub version: String } +/// BuildInfo structure +pub struct BuildInfo { + pub build_environment: String, + pub source_code_snapshot: String, + pub contract_path: Option, + pub build_command: Vec, +} + /// Contract metadata structure pub struct ContractSourceMetadata { - pub version: String, - pub link: String, - pub standards: Vec + pub version: Option, + pub link: Option, + pub standards: Option>, + pub build_info: Option, } /// Minimum Viable Interface @@ -168,6 +206,13 @@ The extension NEP-351 that added Contract Metadata to this NEP-330 was approved | 2 | NEP-330 and NEP-351 should be included in the list of the supported NEPs | There seems to be a general agreement that it is a good default, so NEP was updated | Resolved | | 3 | JSON Event could be beneficial, so tooling can react to the changes in the supported standards | It is outside the scope of this NEP. Also, list of supported standards only changes with contract re-deployment, so tooling can track DEPLOY_CODE events and check the list of supported standards when new code is deployed | Won’t fix | +### 1.2.0 - Build Details Extension + +The NEP extension adds build details to the contract metadata, containing necessary information about how the contract was built. This makes it possible for others to reproduce the same WASM of this contract. The idea first appeared in the [cargo-near SourceScan integration thread](https://github.com/near/cargo-near/issues/131). + +#### Benefits + +- This NEP extension gives developers the capability to save all the required build details, making it possible to reproduce the same WASM code in the future. This ensures greater consistency in contracts and the ability to verify source code. With the assistance of tools like SourceScan and cargo-near, the development process on NEAR becomes significantly easier ## Copyright From fa9a6524a6e4507a3339c01cc62f3efee9afa962 Mon Sep 17 00:00:00 2001 From: Robert Zaremba Date: Fri, 19 Apr 2024 15:27:54 +0200 Subject: [PATCH 140/150] readme: update list of token standards (#537) * added nep-393 to the list. * nep-141 token concept was mainly driven by my design (as documented in the past PRs), so adding myself. --- README.md | 44 ++++++++++++++++++++++---------------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/README.md b/README.md index ecdaf7baa..2095cf988 100644 --- a/README.md +++ b/README.md @@ -10,28 +10,28 @@ Changes to the protocol specification and standards are called NEAR Enhancement ## NEPs -| NEP # | Title | Author | Status | -| ----------------------------------------------------------------- |------------------------------------------|---------------------------------------------|--------| -| [0001](https://github.com/near/NEPs/blob/master/neps/nep-0001.md) | NEP Purpose and Guidelines | @jlogelin | Living | -| [0021](https://github.com/near/NEPs/blob/master/neps/nep-0021.md) | Fungible Token Standard (Deprecated) | @evgenykuzyakov | Final | -| [0141](https://github.com/near/NEPs/blob/master/neps/nep-0141.md) | Fungible Token Standard | @evgenykuzyakov @oysterpack | Final | -| [0145](https://github.com/near/NEPs/blob/master/neps/nep-0145.md) | Storage Management | @evgenykuzyakov | Final | -| [0148](https://github.com/near/NEPs/blob/master/neps/nep-0148.md) | Fungible Token Metadata | @robert-zaremba @evgenykuzyakov @oysterpack | Final | -| [0171](https://github.com/near/NEPs/blob/master/neps/nep-0171.md) | Non Fungible Token Standard | @mikedotexe @evgenykuzyakov @oysterpack | Final | -| [0177](https://github.com/near/NEPs/blob/master/neps/nep-0177.md) | Non Fungible Token Metadata | @chadoh @mikedotexe | Final | -| [0178](https://github.com/near/NEPs/blob/master/neps/nep-0178.md) | Non Fungible Token Approval Management | @chadoh @thor314 | Final | -| [0181](https://github.com/near/NEPs/blob/master/neps/nep-0181.md) | Non Fungible Token Enumeration | @chadoh @thor314 | Final | -| [0199](https://github.com/near/NEPs/blob/master/neps/nep-0199.md) | Non Fungible Token Royalties and Payouts | @thor314 @mattlockyer | Final | -| [0245](https://github.com/near/NEPs/blob/master/neps/nep-0245.md) | Multi Token Standard | @zcstarr @riqi @jriemann @marcos.sun | Review | -| [0264](https://github.com/near/NEPs/blob/master/neps/nep-0264.md) | Promise Gas Weights | @austinabell | Final | -| [0297](https://github.com/near/NEPs/blob/master/neps/nep-0297.md) | Events Standard | @telezhnaya | Final | -| [0330](https://github.com/near/NEPs/blob/master/neps/nep-0330.md) | Source Metadata | @BenKurrek | Review | -| [0366](https://github.com/near/NEPs/blob/master/neps/nep-0366.md) | Meta Transactions | @ilblackdragon @e-uleyskiy @fadeevab | Draft | -| [0399](https://github.com/near/NEPs/blob/master/neps/nep-0399.md) | Flat Storage | @Longarithm @mzhangmzz | Review | -| [0448](https://github.com/near/NEPs/blob/master/neps/nep-0448.md) | Zero-balance Accounts | @bowenwang1996 | Final | -| [0455](https://github.com/near/NEPs/blob/master/neps/nep-0455.md) | Parameter Compute Costs | @akashin @jakmeier | Final | -| [0514](https://github.com/near/NEPs/blob/master/neps/nep-0514.md) | Fewer Block Producer Seats in `testnet` | @nikurt | Final | - +| NEP # | Title | Author | Status | +| ----------------------------------------------------------------- | ---------------------------------------- | -------------------------------------------- | ---------- | +| [0001](https://github.com/near/NEPs/blob/master/neps/nep-0001.md) | NEP Purpose and Guidelines | @jlogelin | Living | +| [0021](https://github.com/near/NEPs/blob/master/neps/nep-0021.md) | Fungible Token Standard (Deprecated) | @evgenykuzyakov | Deprecated | +| [0141](https://github.com/near/NEPs/blob/master/neps/nep-0141.md) | Fungible Token Standard | @evgenykuzyakov @oysterpack, @robert-zaremba | Final | +| [0145](https://github.com/near/NEPs/blob/master/neps/nep-0145.md) | Storage Management | @evgenykuzyakov | Final | +| [0148](https://github.com/near/NEPs/blob/master/neps/nep-0148.md) | Fungible Token Metadata | @robert-zaremba @evgenykuzyakov @oysterpack | Final | +| [0171](https://github.com/near/NEPs/blob/master/neps/nep-0171.md) | Non Fungible Token Standard | @mikedotexe @evgenykuzyakov @oysterpack | Final | +| [0177](https://github.com/near/NEPs/blob/master/neps/nep-0177.md) | Non Fungible Token Metadata | @chadoh @mikedotexe | Final | +| [0178](https://github.com/near/NEPs/blob/master/neps/nep-0178.md) | Non Fungible Token Approval Management | @chadoh @thor314 | Final | +| [0181](https://github.com/near/NEPs/blob/master/neps/nep-0181.md) | Non Fungible Token Enumeration | @chadoh @thor314 | Final | +| [0199](https://github.com/near/NEPs/blob/master/neps/nep-0199.md) | Non Fungible Token Royalties and Payouts | @thor314 @mattlockyer | Final | +| [0245](https://github.com/near/NEPs/blob/master/neps/nep-0245.md) | Multi Token Standard | @zcstarr @riqi @jriemann @marcos.sun | Review | +| [0264](https://github.com/near/NEPs/blob/master/neps/nep-0264.md) | Promise Gas Weights | @austinabell | Final | +| [0297](https://github.com/near/NEPs/blob/master/neps/nep-0297.md) | Events Standard | @telezhnaya | Final | +| [0330](https://github.com/near/NEPs/blob/master/neps/nep-0330.md) | Source Metadata | @BenKurrek | Review | +| [0366](https://github.com/near/NEPs/blob/master/neps/nep-0366.md) | Meta Transactions | @ilblackdragon @e-uleyskiy @fadeevab | Final | +| [0393](https://github.com/near/NEPs/blob/master/neps/nep-0393.md) | Sould Bound Token (SBT) | @robert-zaremba | Final | +| [0399](https://github.com/near/NEPs/blob/master/neps/nep-0399.md) | Flat Storage | @Longarithm @mzhangmzz | Final | +| [0448](https://github.com/near/NEPs/blob/master/neps/nep-0448.md) | Zero-balance Accounts | @bowenwang1996 | Final | +| [0455](https://github.com/near/NEPs/blob/master/neps/nep-0455.md) | Parameter Compute Costs | @akashin @jakmeier | Final | +| [0514](https://github.com/near/NEPs/blob/master/neps/nep-0514.md) | Fewer Block Producer Seats in `testnet` | @nikurt | Final | ## Specification From ab03f1241b58785d68e664b724466a8780b6dfe0 Mon Sep 17 00:00:00 2001 From: Alexander Fadeev Date: Mon, 22 Apr 2024 15:24:18 +0300 Subject: [PATCH 141/150] NEP-452 (linkdrop): Change status to "final" + add it to README.md. (#543) Make the NEP-452 present in the NEPs list. Change its status to "final". --- README.md | 1 + neps/nep-0452.md | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 2095cf988..2ac517436 100644 --- a/README.md +++ b/README.md @@ -30,6 +30,7 @@ Changes to the protocol specification and standards are called NEAR Enhancement | [0393](https://github.com/near/NEPs/blob/master/neps/nep-0393.md) | Sould Bound Token (SBT) | @robert-zaremba | Final | | [0399](https://github.com/near/NEPs/blob/master/neps/nep-0399.md) | Flat Storage | @Longarithm @mzhangmzz | Final | | [0448](https://github.com/near/NEPs/blob/master/neps/nep-0448.md) | Zero-balance Accounts | @bowenwang1996 | Final | +| [0452](https://github.com/near/NEPs/blob/master/neps/nep-0452.md) | Linkdrop Standard | @benkurrek @miyachi | Final | | [0455](https://github.com/near/NEPs/blob/master/neps/nep-0455.md) | Parameter Compute Costs | @akashin @jakmeier | Final | | [0514](https://github.com/near/NEPs/blob/master/neps/nep-0514.md) | Fewer Block Producer Seats in `testnet` | @nikurt | Final | diff --git a/neps/nep-0452.md b/neps/nep-0452.md index 3fb1c6472..c5df9f258 100644 --- a/neps/nep-0452.md +++ b/neps/nep-0452.md @@ -3,7 +3,7 @@ NEP: 452 Title: Linkdrop Standard Author: Ben Kurrek , Ken Miyachi DiscussionsTo: https://gov.near.org/t/official-linkdrop-standard/32463/1 -Status: Draft +Status: Final Type: Standards Track Category: Contract Version: 1.0.0 @@ -194,7 +194,7 @@ Below are some references for linkdrop contracts. Another important security implication of linkdrop creation is to ensure that only one key is mapped to a set of assets at any given time. Externally, assets such as FTs, and NFTs belong to the overall linkdrop contract account rather than a specific access key. It is important to ensure that specific keys can only claim assets that they are mapped to. -2. Linkdrop Key Management +2. Linkdrop Key Management Key management is a critical safety component of linkdrops. The linkdrop contract should implement a key management strategy for keys such that a reentrancy attack does not occur. For example, one strategy may be to "lock" or mark a key as "in transfer" such that it cannot be used again until the transfer is complete. 3. Asset Refunds & Failed Claims From 8bcc82a66858060d63b8155d6f45f931c4f5498b Mon Sep 17 00:00:00 2001 From: Robert Zaremba Date: Mon, 22 Apr 2024 19:27:22 +0200 Subject: [PATCH 142/150] fix: dead links (#542) --- specs/ChainSpec/Consensus.md | 4 +- specs/ChainSpec/SelectingBlockProducers.md | 122 +++++++++++---------- specs/Proposals/0033-economics.md | 14 ++- 3 files changed, 80 insertions(+), 60 deletions(-) diff --git a/specs/ChainSpec/Consensus.md b/specs/ChainSpec/Consensus.md index 8651d49dd..5daa2d3e1 100644 --- a/specs/ChainSpec/Consensus.md +++ b/specs/ChainSpec/Consensus.md @@ -195,7 +195,9 @@ Now back to the theorem. Without loss of generality, assume that $\operatorname{ ## Liveness -See the proof of liveness in [near.ai/doomslug](https://near.ai/doomslug). The consensus in this section differs in that it requires two consecutive blocks with endorsements. The proof in the linked paper trivially extends, by observing that once the delay is sufficiently long for a honest block producer to collect enough endorsements, the next block producer ought to have enough time to collect all the endorsements too. +See the proof of liveness in [Doomslug Whitepaper](https://discovery-domain.org/papers/doomslug.pdf) and the recent [Nightshade](https://discovery-domain.org/papers/nightshade.pdf) sharding protocol. + +The consensus in this section differs in that it requires two consecutive blocks with endorsements. The proof in the linked paper trivially extends, by observing that once the delay is sufficiently long for a honest block producer to collect enough endorsements, the next block producer ought to have enough time to collect all the endorsements too. ## Approval condition diff --git a/specs/ChainSpec/SelectingBlockProducers.md b/specs/ChainSpec/SelectingBlockProducers.md index 875ac9fa9..a8711e92f 100644 --- a/specs/ChainSpec/SelectingBlockProducers.md +++ b/specs/ChainSpec/SelectingBlockProducers.md @@ -25,17 +25,18 @@ block producers to be the one responsible for producing the chunk/block at each shard. There are several desiderata for these algorithms: -* Larger stakes should be preferred (more staked tokens means more security) -* The frequency with which a given participant is selected to produce a particular chunk/block is + +- Larger stakes should be preferred (more staked tokens means more security) +- The frequency with which a given participant is selected to produce a particular chunk/block is proportional to that participant's stake -* All participants selected as chunk/block producers should be selected to produce at least one +- All participants selected as chunk/block producers should be selected to produce at least one chunk/block during the epoch -* It should be possible to determine which chunk/block producer is supposed to produce the +- It should be possible to determine which chunk/block producer is supposed to produce the chunk/block at height $h$, for any $h$ within the epoch, in constant time -* The block producer chosen at height $h$ should have been a chunk producer for some shard at +- The block producer chosen at height $h$ should have been a chunk producer for some shard at height $h - 1$, this minimizes network communication between chunk producers and block producers -* The number of distinct chunk-only/block producers should be as large as is allowed by the +- The number of distinct chunk-only/block producers should be as large as is allowed by the scalability in the consensus algorithm (too large and the system would be too slow, too small and the system would be too centralized) $^{\dagger}$ @@ -46,16 +47,16 @@ There are several desiderata for these algorithms: ## Assumptions -* The maximum number of distinct chunk-only producers and block producers supported by the consensus +- The maximum number of distinct chunk-only producers and block producers supported by the consensus algorithm is a fixed constant. This will be a parameter of the protocol itself (i.e. all nodes must agree on the constant). In this document, we will denote the maximum number of chunk-only producers as `MAX_NUM_CP` and the maximum number of block producers by `MAX_NUM_BP`. -* The minimum number of blocks in the epoch is known at the time of block producer selection. This +- The minimum number of blocks in the epoch is known at the time of block producer selection. This minimum does not need to be incredibly accurate, but we will assume it is within a factor of 2 of the actual number of blocks in the epoch. In this document we will refer to this as the "length of the epoch", denoted by `epoch_length`. -* To meet the requirement that any chosen validator will be selected to produce at least one - chunk/block in the epoch, we assume it is acceptable for the probability of this *not* happening +- To meet the requirement that any chosen validator will be selected to produce at least one + chunk/block in the epoch, we assume it is acceptable for the probability of this _not_ happening to be sufficiently low. Let `PROBABILITY_NEVER_SELECTED` be a protocol constant which gives the maximum allowable probability that the chunk-only/block producer with the least stake will never be selected to produce a chunk/block during the epoch. We will additionally assume the chunk/block @@ -66,27 +67,30 @@ There are several desiderata for these algorithms: stake (what stake is "relevant" depends on whether the validator is a chunk-only producer or a block producer; more details below). Hence, the algorithm will enforce the condition $(1 - (s_\text{min} / S))^\text{epoch\_length} < \text{PROBABILITY\_NEVER\_SELECTED}$. - -In mainnet and testnet, `epoch_length` is set to `43200`. Let $\text{PROBABILITY\_NEVER\_SELECTED}=0.001$, + +In mainnet and testnet, `epoch_length` is set to `43200`. Let $\text{PROBABILITY\_NEVER\_SELECTED}=0.001$, we obtain, $s_\text{min} / S = 160/1000,000$. ## Algorithm for selecting block and chunk producers -A potential validator cannot specify whether they want to become a block producer or a chunk-only producer. -There is only one type of proposal. The same algorithm is used for selecting block producers and chunk producers, -but with different thresholds. The threshold for becoming block producers is higher, so if a node is selected as a block + +A potential validator cannot specify whether they want to become a block producer or a chunk-only producer. +There is only one type of proposal. The same algorithm is used for selecting block producers and chunk producers, +but with different thresholds. The threshold for becoming block producers is higher, so if a node is selected as a block producer, it will also be a chunk producer, but not the other way around. Validators who are selected as chunk producers but not block producers are chunk-only producers. ### select_validators + ### Input -* `max_num_validators: u16` max number of validators to be selected -* `min_stake_fraction: Ratio` minimum stake ratio for selected validator -* `validator_proposals: Vec` (proposed stakes for the next epoch from nodes sending + +- `max_num_validators: u16` max number of validators to be selected +- `min_stake_fraction: Ratio` minimum stake ratio for selected validator +- `validator_proposals: Vec` (proposed stakes for the next epoch from nodes sending staking transactions) ### Output -* `(validators: Vec, sampler: WeightedIndex)` +- `(validators: Vec, sampler: WeightedIndex)` ### Steps @@ -110,10 +114,12 @@ return (validators, validator_sampler) ``` ### Algorithm for selecting block producers + ### Input -* `MAX_NUM_BP: u16` Max number of block producers, see Assumptions -* `min_stake_fraction: Ratio` $s_\text{min} / S$, see Assumptions -* `validator_proposals: Vec` (proposed stakes for the next epoch from nodes sending + +- `MAX_NUM_BP: u16` Max number of block producers, see Assumptions +- `min_stake_fraction: Ratio` $s_\text{min} / S$, see Assumptions +- `validator_proposals: Vec` (proposed stakes for the next epoch from nodes sending staking transactions) ```python @@ -121,42 +127,46 @@ select_validators(MAX_NUM_BP, min_stake_fraction, validator_proposals) ``` ### Algorithm for selecting chunk producers + ### Input -* `MAX_NUM_CP: u16` max number of chunk producers, see Assumptions` -* `min_stake_fraction: Ratio` $s_\text{min} / S$, see Assumptions -* `num_shards: u64` number of shards -* `validator_proposals: Vec` (proposed stakes for the next epoch from nodes sending + +- `MAX_NUM_CP: u16` max number of chunk producers, see Assumptions` +- `min_stake_fraction: Ratio` $s_\text{min} / S$, see Assumptions +- `num_shards: u64` number of shards +- `validator_proposals: Vec` (proposed stakes for the next epoch from nodes sending staking transactions) ```python select_validators(MAX_NUM_CP, min_stake_fraction/num_shards, validator_proposals) ``` -The reasoning for using `min_stake_fraction/num_shards` as the threshold here is that -we will assign chunk producers to shards later and the algorithm (described below) will try to assign + +The reasoning for using `min_stake_fraction/num_shards` as the threshold here is that +we will assign chunk producers to shards later and the algorithm (described below) will try to assign them in a way that the total stake in each shard is distributed as evenly as possible. So the total stake in each shard will be roughly be `total_stake_all_chunk_producers / num_shards`. ## Algorithm for assigning chunk producers to shards + Note that block producers are a subset of chunk producers, so this algorithm will also assign block producers -to shards. This also means that a block producer may only be assigned to a subset of shards. For the security of -the protocol, all block producers must track all shards, even if they are not assigned to produce chunks for all shards. -We enforce that in the implementation level, not the protocol level. A validator node will panic if it doesn't track all -shards. +to shards. This also means that a block producer may only be assigned to a subset of shards. For the security of +the protocol, all block producers must track all shards, even if they are not assigned to produce chunks for all shards. +We enforce that in the implementation level, not the protocol level. A validator node will panic if it doesn't track all +shards. ### Input -* `chunk_producers: Vec` -* `num_shards: usize` -* `min_validators_per_shard: usize` +- `chunk_producers: Vec` +- `num_shards: usize` +- `min_validators_per_shard: usize` ### Output -* `validator_shard_assignments: Vec>` +- `validator_shard_assignments: Vec>` - $i$-th element gives the validators assigned to shard $i$ ### Steps -* While any shard has fewer than `min_validators_per_shard` validators assigned to it: +- While any shard has fewer than `min_validators_per_shard` validators assigned to it: - Let `cp_i` be the next element of `chunk_producers` (cycle back to the beginning as needed) - Note: if there are more shards than chunk producers, then some chunk producers will be assigned to multiple shards. This is undesirable because we want each chunk-only producer @@ -167,12 +177,12 @@ shards. - Let `shard_id` be the shard with the fewest number of assigned validators such that `cp_i` has not been assigned to `shard_id` - Assign `cp_i` to `shard_id` -* While there are any validators which have not been assigned to any shard: +- While there are any validators which have not been assigned to any shard: - Let `cp_i` be the next validator not assigned to any shard - Let `shard_id` be the shard with the least total stake (total stake = sum of stakes of all validators assigned to that shard) - Assign `cp_i` to `shard_id` -* Return the shard assignments +- Return the shard assignments In addition to the above description, we have a [proof-of-concept (PoC) on GitHub](https://github.com/birchmd/bp-shard-assign-poc). Note: this PoC has not been updated since @@ -181,11 +191,13 @@ the same algorithm works to assign chunk producers to shards; it is only a matte variables referencing "block producers" to reference "chunk producers" instead. ## Algorithm for sampling validators proportional to stake + We sample validators with probability proportional to their stake using the following data structure. -* `weighted_sampler: WeightedIndex` + +- `weighted_sampler: WeightedIndex` - Allow $O(1)$ sampling - This structure will be based on the - [WeightedIndex](https://rust-random.github.io/rand/rand/distributions/weighted/alias_method/struct.WeightedIndex.html) + [WeightedIndex](https://rust-random.github.io/rand/rand/distributions/struct.WeightedIndex.html) implementation (see a description of [Vose's Alias Method](https://en.wikipedia.org/wiki/Alias_method) for details) @@ -194,14 +206,14 @@ algorithms for selecting a specific block producer and chunk producer at each he ### Input -* `rng_seed: [u8; 32]` +- `rng_seed: [u8; 32]` - See usages of this algorithm below to see how this seed is generated -* `validators: Vec` -* `sampler: WeightedIndex` +- `validators: Vec` +- `sampler: WeightedIndex` ### Output -* `selection: ValidatorStake` +- `selection: ValidatorStake` ### Steps @@ -228,18 +240,18 @@ return validators[index] ### Input -* `h: BlockHeight` +- `h: BlockHeight` - Height to compute the block producer for - Only heights within the epoch corresponding to the given block producers make sense as input -* `block_producers: Vec` (output from above) -* `block_producer_sampler: WeightedIndex` -* `epoch_rng_seed: [u8; 32]` +- `block_producers: Vec` (output from above) +- `block_producer_sampler: WeightedIndex` +- `epoch_rng_seed: [u8; 32]` - Fixed seed for the epoch determined from Verified Random Function (VRF) output of last block in the previous epoch ### Output -* `block_producer: ValidatorStake` +- `block_producer: ValidatorStake` ### Steps @@ -256,14 +268,14 @@ return select_validator(rng_seed=block_seed, validators=block_producers, sampler ### Input -* (same inputs as selection of block producer at height h) -* `num_shards: usize` -* `chunk_producer_sampler: Vec` (outputs from chunk-only producer selection) -* `validator_shard_assignments: Vec>` +- (same inputs as selection of block producer at height h) +- `num_shards: usize` +- `chunk_producer_sampler: Vec` (outputs from chunk-only producer selection) +- `validator_shard_assignments: Vec>` ### Output -* `chunk_producers: Vec` +- `chunk_producers: Vec` - `i`th element gives the validator that will produce the chunk for shard `i`. Note: at least one of these will be a block producer, while others will be chunk-only producers. diff --git a/specs/Proposals/0033-economics.md b/specs/Proposals/0033-economics.md index 349628f85..d70e727cb 100644 --- a/specs/Proposals/0033-economics.md +++ b/specs/Proposals/0033-economics.md @@ -4,40 +4,46 @@ - Issue(s): link to relevant issues in relevant repos (not required). # Summary + [summary]: #summary -Adding economics specification for NEAR Protocol based on the economics paper - https://near.org/papers/economics-in-sharded-blockchain/ +Adding economics specification for NEAR Protocol based on the NEAR whitepaper - https://pages.near.org/papers/the-official-near-white-paper/#economics # Motivation + [motivation]: #motivation Currently, the specification is defined by the implementation in https://github.com/near/nearcore. This codifies all the parameters and formulas and defines main concepts. # Guide-level explanation + [guide-level-explanation]: #guide-level-explanation The goal is to build a set of specs about NEAR token economics, for analysts and adopters, to simplify their understanding of the protocol and its game-theoretical dynamics. This initial release will be oriented to validators and staking in general. # Reference-level explanation + [reference-level-explanation]: #reference-level-explanation This part of the documentation is self-contained. It may provide material for third-party research papers, and spreadsheet analysis. # Drawbacks + [drawbacks]: #drawbacks We might just put this in the NEAR docs. # Rationale and alternatives -[rationale-and-alternatives]: #rationale-and-alternatives +[rationale-and-alternatives]: #rationale-and-alternatives # Unresolved questions -[unresolved-questions]: #unresolved-questions +[unresolved-questions]: #unresolved-questions # Future possibilities + [future-possibilities]: #future-possibilities -This is an open document which may be used by NEAR's community to pull request a new economic policy. Having a formal document also for non-technical aspects opens new opportunities for the governance. +This is an open document which may be used by NEAR's community to pull request a new economic policy. Having a formal document also for non-technical aspects opens new opportunities for the governance. From 5b22428c0325dafd7023b5e81471b467db79cc71 Mon Sep 17 00:00:00 2001 From: Andrei Kashin Date: Wed, 24 Apr 2024 11:50:37 +0200 Subject: [PATCH 143/150] Fix GitHub links in nep-0455.md (#538) The links to "cs.github.com" are now broken as it was removed. So we replace them with the usual GitHub links. --- neps/nep-0455.md | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/neps/nep-0455.md b/neps/nep-0455.md index 9699f1458..5cd9bddfc 100644 --- a/neps/nep-0455.md +++ b/neps/nep-0455.md @@ -155,24 +155,24 @@ By default, the parameter compute cost matches the corresponding gas cost. Compute costs should be applicable to all gas parameters, specifically including: -- [`ExtCosts`](https://cs.github.com/near/nearcore/blob/6e08a41084c632010b1d4c42132ad58ecf1398a2/core/primitives-core/src/config.rs#L377) -- [`ActionCosts`](https://cs.github.com/near/nearcore/blob/6e08a41084c632010b1d4c42132ad58ecf1398a2/core/primitives-core/src/config.rs#L456) +- [`ExtCosts`](https://github.com/near/nearcore/blob/6e08a41084c632010b1d4c42132ad58ecf1398a2/core/primitives-core/src/config.rs#L377) +- [`ActionCosts`](https://github.com/near/nearcore/blob/6e08a41084c632010b1d4c42132ad58ecf1398a2/core/primitives-core/src/config.rs#L456) Changes necessary to support `ExtCosts`: -1. Track compute usage in [`GasCounter`](https://cs.github.com/near/nearcore/blob/51670e593a3741342a1abc40bb65e29ba0e1b026/runtime/near-vm-logic/src/gas_counter.rs#L47) struct -2. Track compute usage in [`VMOutcome`](https://cs.github.com/near/nearcore/blob/056c62183e31e64cd6cacfc923a357775bc2b5c9/runtime/near-vm-logic/src/logic.rs#L2868) struct (alongside `burnt_gas` and `used_gas`) -3. Store compute usage in [`ActionResult`](https://cs.github.com/near/nearcore/blob/6d2f3fcdd8512e0071847b9d2ca10fb0268f469e/runtime/runtime/src/lib.rs#L129) and aggregate it across multiple actions by modifying [`ActionResult::merge`](https://cs.github.com/near/nearcore/blob/6d2f3fcdd8512e0071847b9d2ca10fb0268f469e/runtime/runtime/src/lib.rs#L141) -4. Store compute costs in [`ExecutionOutcome`](https://cs.github.com/near/nearcore/blob/578983c8df9cc36508da2fb4a205c852e92b211a/runtime/runtime/src/lib.rs#L266) and [aggregate them across all transactions](https://cs.github.com/near/nearcore/blob/578983c8df9cc36508da2fb4a205c852e92b211a/runtime/runtime/src/lib.rs#L1279) -5. Enforce the chunk compute limit when the chunk is [applied](https://cs.github.com/near/nearcore/blob/6d2f3fcdd8512e0071847b9d2ca10fb0268f469e/runtime/runtime/src/lib.rs#L1325) +1. Track compute usage in [`GasCounter`](https://github.com/near/nearcore/blob/51670e593a3741342a1abc40bb65e29ba0e1b026/runtime/near-vm-logic/src/gas_counter.rs#L47) struct +2. Track compute usage in [`VMOutcome`](https://github.com/near/nearcore/blob/056c62183e31e64cd6cacfc923a357775bc2b5c9/runtime/near-vm-logic/src/logic.rs#L2868) struct (alongside `burnt_gas` and `used_gas`) +3. Store compute usage in [`ActionResult`](https://github.com/near/nearcore/blob/6d2f3fcdd8512e0071847b9d2ca10fb0268f469e/runtime/runtime/src/lib.rs#L129) and aggregate it across multiple actions by modifying [`ActionResult::merge`](https://github.com/near/nearcore/blob/6d2f3fcdd8512e0071847b9d2ca10fb0268f469e/runtime/runtime/src/lib.rs#L141) +4. Store compute costs in [`ExecutionOutcome`](https://github.com/near/nearcore/blob/578983c8df9cc36508da2fb4a205c852e92b211a/runtime/runtime/src/lib.rs#L266) and [aggregate them across all transactions](https://github.com/near/nearcore/blob/578983c8df9cc36508da2fb4a205c852e92b211a/runtime/runtime/src/lib.rs#L1279) +5. Enforce the chunk compute limit when the chunk is [applied](https://github.com/near/nearcore/blob/6d2f3fcdd8512e0071847b9d2ca10fb0268f469e/runtime/runtime/src/lib.rs#L1325) Additional changes necessary to support `ActionCosts`: -1. Return compute costs from [`total_send_fees`](https://cs.github.com/near/nearcore/blob/578983c8df9cc36508da2fb4a205c852e92b211a/runtime/runtime/src/config.rs#L71) -2. Store aggregate compute cost in [`TransactionCost`](https://cs.github.com/near/nearcore/blob/578983c8df9cc36508da2fb4a205c852e92b211a/runtime/runtime/src/config.rs#L22) struct -3. Propagate compute costs to [`VerificationResult`](https://cs.github.com/near/nearcore/blob/578983c8df9cc36508da2fb4a205c852e92b211a/runtime/runtime/src/verifier.rs#L330) +1. Return compute costs from [`total_send_fees`](https://github.com/near/nearcore/blob/578983c8df9cc36508da2fb4a205c852e92b211a/runtime/runtime/src/config.rs#L71) +2. Store aggregate compute cost in [`TransactionCost`](https://github.com/near/nearcore/blob/578983c8df9cc36508da2fb4a205c852e92b211a/runtime/runtime/src/config.rs#L22) struct +3. Propagate compute costs to [`VerificationResult`](https://github.com/near/nearcore/blob/578983c8df9cc36508da2fb4a205c852e92b211a/runtime/runtime/src/verifier.rs#L330) -Additionaly, the gas price computation will need to be adjusted in [`compute_new_gas_price`](https://cs.github.com/near/nearcore/blob/578983c8df9cc36508da2fb4a205c852e92b211a/core/primitives/src/block.rs#L328) to use compute cost instead of gas cost. +Additionaly, the gas price computation will need to be adjusted in [`compute_new_gas_price`](https://github.com/near/nearcore/blob/578983c8df9cc36508da2fb4a205c852e92b211a/core/primitives/src/block.rs#L328) to use compute cost instead of gas cost. ## Security Implications From 2741beccabc2af3f08d3b76dbe7b5b8b1e6619d2 Mon Sep 17 00:00:00 2001 From: Eric Winer Date: Tue, 14 May 2024 17:42:28 +0100 Subject: [PATCH 144/150] Transactions.md redirect (#545) https://nomicon.io/DataStructures/Transaction is blank. I'm adding a link to the Transactions spec page. We also could delete this page but I'm choosing not to because: 1. There might be links to this page that would break. 2. Many chains consider a Transaction to be a core data structure - so this blank page is the first place I looked to learn about the NEAR tx format. I think having a link here that points people in the right direction could be nice for people new to NEAR. --- specs/DataStructures/Transaction.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/specs/DataStructures/Transaction.md b/specs/DataStructures/Transaction.md index 13ebed4bd..692147a5b 100644 --- a/specs/DataStructures/Transaction.md +++ b/specs/DataStructures/Transaction.md @@ -1 +1,3 @@ # Transaction + +See [Transactions](../RuntimeSpec/Transactions.md) documentation in the [Runtime Specification](../RuntimeSpec) section. From 7afe60624e8e7d8e0404ac7e02cbccdf10d193ce Mon Sep 17 00:00:00 2001 From: Jan Ciolek <149345204+jancionear@users.noreply.github.com> Date: Tue, 4 Jun 2024 11:33:05 +0200 Subject: [PATCH 145/150] Improve the description of epoch end (#534) The previous description of when an epoch ends was a bit confusing. It mentioned that two conditions are needed for a block to be the last block of an epoch, but in reality only one of them matters, as one condition is implied by the other. This makes the descripion harder to parse - why are there two conditions, if only one of them matters? It can lead to some confusion. Let's improve the description to make it clearer and easier to understand. A diagram is also added for clarity. Refs: [zulip discussion](https://near.zulipchat.com/#narrow/stream/295558-pagoda.2Fcore/topic/When.20does.20an.20Epoch.20end.3F/near/422463251) --------- Co-authored-by: Marcelo Fornet --- specs/BlockchainLayer/EpochManager/Epoch.md | 21 ++++++++++++++---- .../EpochManager/epoch_end_diagram.png | Bin 0 -> 57826 bytes 2 files changed, 17 insertions(+), 4 deletions(-) create mode 100644 specs/BlockchainLayer/EpochManager/epoch_end_diagram.png diff --git a/specs/BlockchainLayer/EpochManager/Epoch.md b/specs/BlockchainLayer/EpochManager/Epoch.md index 371e81e5a..bab363b5c 100644 --- a/specs/BlockchainLayer/EpochManager/Epoch.md +++ b/specs/BlockchainLayer/EpochManager/Epoch.md @@ -10,29 +10,42 @@ Within one epoch, validator assignment is based on block height: each height has each height and shard have a chunk producer. ### End of an epoch -A block is defined to be the last block in its epoch if it's the genesis block or if the following conditions are met: -- Let `estimated_next_epoch_start = first_block_in_epoch.height + epoch_length` -- `block.height + 1 >= estimated_next_epoch_start` + +Let `estimated_next_epoch_start = first_block_in_epoch.height + epoch_length` + +A `block` is defined to be the last block in its epoch if it's the genesis block or if the following condition is met: + - `block.last_finalized_height + 3 >= estimated_next_epoch_start` `epoch_length` is defined in `genesis_config` and has a value of `43200` height delta on mainnet (12 hours at 1 block per second). +Since every final block must have two more blocks on top of it, it means that the last block in an epoch will have a height of at least `block.last_finalized_height + 2`, so for the last block it holds that `block.height + 1 >= estimated_next_epoch_start`. Its height will be at least `estimated_next_epoch_start - 1`. + +Note that an epoch only ends when there is a final block above a certain height. If there are no final blocks, the epoch will be stretched until the required final block appears. An epoch can potentially be longer than `epoch_length`. + +![Diagram of epoch end](epoch_end_diagram.png) + ### EpochHeight + Epochs on one chain can be identified by height, which is defined the following way: + - Special epoch that contains genesis block only: undefined - Epoch starting from the block that's after genesis: `0` (NOTE: in current implementation it's `1` due to a bug, so there are two epochs with height `1`) - Following epochs: height of the parent epoch plus one ### Epoch id + Every block stores the id of its epoch - `epoch_id`. Epoch id is defined as + - For special genesis block epoch it's `0` - For epoch with height `0` it's `0` (NOTE: the first two epochs use the same epoch id) - For epoch with height `1` it's the hash of genesis block - For epoch with height `T+2` it's the hash of the last block in epoch `T` -### End of an epoch +### Epoch end + - After processing the last block of epoch `T`, `EpochManager` aggregates information from block of the epoch, and computes validator set for epoch `T+2`. This process is described in [EpochManager](EpochManager.md). - After that, the validator set rotates to epoch `T+1`, and the next block is produced by the validator from the new set diff --git a/specs/BlockchainLayer/EpochManager/epoch_end_diagram.png b/specs/BlockchainLayer/EpochManager/epoch_end_diagram.png new file mode 100644 index 0000000000000000000000000000000000000000..c02f9f3cc9c117a28136319e8521a7a68ecff727 GIT binary patch literal 57826 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 Date: Tue, 18 Jun 2024 16:29:11 +0200 Subject: [PATCH 146/150] Support for yielded execution (#519) Co-authored-by: DavidM-D Co-authored-by: Michael Birch Co-authored-by: Simonas Kazlauskas --- neps/nep-519-yield-execution.md | 191 ++++++++++++++++++++++++++++++++ 1 file changed, 191 insertions(+) create mode 100644 neps/nep-519-yield-execution.md diff --git a/neps/nep-519-yield-execution.md b/neps/nep-519-yield-execution.md new file mode 100644 index 000000000..e636d0df3 --- /dev/null +++ b/neps/nep-519-yield-execution.md @@ -0,0 +1,191 @@ +--- +NEP: 519 +Title: Yield Execution +Authors: Akhi Singhania ; Saketh Are +Status: Draft +DiscussionsTo: https://github.com/near/NEPs/pull/519 +Type: Protocol +Version: 0.0.0 +Created: 2023-11-17 +LastUpdated: 2023-11-20 +--- + +## Summary + +Today, when a smart contract is called by a user or another contract, it has no sensible way to delay responding to the caller till it has observed another future transaction. This proposal introduces this possibility into the NEAR protocol. + +## Motivation + +There exist some situations where when a smart contract on NEAR is called, it will only be able to provide an answer at some time in the future. The callee needs a way to defer replying to the caller while the response is being prepared. + +Examples include a smart contract (`S`) that provides the MPC signing capability. It relies on indexers external to the NEAR protocol for computing the signatures. The rough steps are: + +1. Signer contract provides a function `fn sign_payload(Payload, ...)`. +2. When called, the contract defers replying to the caller. +3. External indexers are monitoring the transactions on the contract; they observe the new signing request, compute a signature, and call another function `fn signature_available(Signature, ...)` on the signer contract. +4. The signer contract validates the signature and replies to the original caller. + +Today, the NEAR protocol has no sensible way to defer replying to the caller in step 2 above. This proposal proposes adding two following new host functions to the NEAR protocol: + +- `promise_yield_create`: allows setting up a continuation function that should only be executed after `promise_yield_resume` is invoked. Together with `promise_return` this allows delaying the reply to the caller; +- `promise_yield_resume`: indicates to the protocol that the continuation to the yield may now be executed. + +If these two host functions were available, then `promise_yield_create` would be used to implement step 2 above and `promise_yield_resume` would be used for step 3 of the motivating example above. + +## Specification + +The proposal is to add the following host functions to the NEAR protocol: + + +```rust +/// Smart contracts can use this host function along with +/// `promise_yield_resume()` to delay replying to their caller for up to 200 +/// blocks. This host function allows the contract to provide a callback to the +/// protocol that will be executed after either contract calls +/// `promise_yield_resume()` or after 200 blocks have been executed. The +/// callback then has the opportunity to either reply to the caller or to delay +/// replying again. +/// +/// `method_name_len` and `method_name_ptr`: Identify the callback method that +/// should be executed either after the contract calls `promise_yield_resume()` +/// or after 200 blocks have been executed. +/// +/// `arguments_len` and `arguments_ptr` provide an initial blob of arguments +/// that will be passed to the callback. These will be available via the +/// `input` host function. +/// +/// `gas`: Similar to the `gas` parameter in +/// [promise_create](https://github.com/near/nearcore/blob/a908de36ab6f75eb130447a5788007e26d05f93e/runtime/near-vm-runner/src/logic/logic.rs#L1281), +/// the `gas` parameter is a prepayment for the gas that would be used to +/// execute the callback. +/// +/// `gas_weight`: Similar to the `gas_weight` parameter in +/// [promise_batch_action_function_call_weight](https://github.com/near/nearcore/blob/a908de36ab6f75eb130447a5788007e26d05f93e/runtime/near-vm-runner/src/logic/logic.rs#L1699), +/// this improves the devX for the smart contract. It allows a contract to +/// specify a portion of the remaining gas for executing the callback instead of +/// specifying a precise amount. +/// +/// `register_id`: is used to identify the register that will be filled with a +/// unique resumption token. This token is used with `promise_yield_resume` to +/// resolve the continuation receipt set up by this function. +/// +/// Return value: u64: Similar to the +/// [promise_create](https://github.com/near/nearcore/blob/a908de36ab6f75eb130447a5788007e26d05f93e/runtime/near-vm-runner/src/logic/logic.rs#L1281) +/// host function, this function also create a promise and returns an index to +/// the promise. This index can be used to create a chain of promises. +pub fn promise_yield_create( + method_name_len: u64, + method_name_ptr: u64, + arguments_len: u64, + arguments_ptr: u64, + gas: u64, + gas_weight: u64, + register_id: u64, +) -> u64; + +/// See `promise_yield_create()` for more details. This host function can be +/// used to resolve the continuation that was set up by +/// `promise_yield_create()`. The contract calling this function must be the +/// same contract that called `promise_yield_create()` earlier. This host +/// function cannot be called for the same resumption token twice or if the +/// callback specified in `promise_yield_create()` has already executed. +/// +/// `data_id_len` and `data_it_ptr`: Used to pass the unique resumption token +/// that was returned to the smart contract in the `promise_yield_create()` +/// function (via the register). +/// +/// `payload_len` and `payload_ptr`: the smart contract can provide an +/// additional optional blob of arguments that should be passed to the callback +/// that will be resumed. These are available via the `promise_result` host +/// function. +/// +/// This function can be called multiple times with the same data id. If it is +/// called successfully multiple times, then the implementation guarantees that +/// the yielded callback will execute with one of the successfully submitted +/// payloads. If submission was successful, then `1` is returned. Otherwise +/// (e.g. if the yield receipt has already timed out or the yielded callback has +/// already been executed) `0` will be returned, indicating that this payload +/// could not be submitted successfully. +pub fn promise_yield_resume( + data_id_len: u64, + data_id_ptr: u64, + payload_len: u64, + payload_ptr: u64, +) -> u32; +``` + +## Reference Implementation + +The reference implementation against the nearcore repository can be found in this [PR](https://github.com/near/nearcore/pull/10415). + +## Security Implications + +Some potential security issues have been identified and are covered below: + +- Smart contracts using this functionality have to be careful not to let just any party trigger a call to `promise_yield_resume`. In the example above, it is possible that a malicious actor may pretend to be an external signer and call the `signature_available()` function with an incorrect signature. Hence contracts should be taking precautions by only letting select callers call the function (by using [this](https://github.com/aurora-is-near/near-plugins/blob/master/near-plugins/src/access_controllable.rs) service for example) and validating the payload before acting upon it. +- This mechanism introduces a new way to create delayed receipts in the protocol. When the protocol is under conditions of congestion, this mechanism could be used to further aggravate the situation. This is deemed as not a terrible issue as the existing mechanisms of using promises and etc. can also be used to further exacerbate the situation. + +## Alternatives + +Two alternatives have been identified. + +### Self calls to delay replying + +In the `fn sign_payload(Payload, ...)` function, instead of calling `yield`, the contract can keep calling itself in a loop till external indexer replies with the signature. This would work but would be very fragile and expensive. The contract would have to pay for all the calls and function executions while it is waiting for the response. Also depending on the congestion on the network; if the shard is not busy at all, some self calls could happen within the same block meaning that the contract might not actually wait for as long as it hoped for and if the network is very busy then the call from the external indexer might be arbitrarily delayed. + +### Change the flow of calls + +The general flow of cross contract calls in NEAR is that a contract `A` sends a request to another contract `B` to perform a service and `B` replies to `A` with the response. This flow could be altered. When a contract `A` calls `B` to perform a service, `B` could respond with a "promise to call it later with the answer". Then when the signature is eventually available, `B` can then send `A` a request with the signature. + +There are some problems with this approach though. After the change of flow of calls; `B` is now going to be paying for gas for various executions that `A` should have been paying for. Due to bugs or malicious intent, `B` could forget to call `A` with the signature. If `A` is calling `B` deep in a call tree and `B` replies to it without actually providing an answer, then `A` would need a mechanism to keep the call tree alive while it waits for `B` to call it with the signature in effect running into the same problem that this NEP is attempting to solve. + +## Future possibilities + +One potential future possibility is to allow contracts to specify how long the protocol should wait (up to a certain limit) for the contract to call `promise_yield_resume`. If contracts specify a smaller value, they would potentially be charged a smaller gas fee. This would make contracts more efficient. This enhancement does lead to a more complex implementation and could even allow malicious contracts to more easily concentrate a lot of callbacks to occur at the same time increasing the congestion on the network. Hence, we decided not to include this feature for the time being. + +## Consequences + +[This section describes the consequences, after applying the decision. All consequences should be summarized here, not just the "positive" ones. Record any concerns raised throughout the NEP discussion.] + +### Positive + +- p1 + +### Neutral + +- n1 + +### Negative + +- n1 + +### Backwards Compatibility + +We believe this can be implemented with full backwards compatibility. + +## Changelog + +### 1.0.0 - Initial Version + +> Placeholder for the context about when and who approved this NEP version. + +#### Benefits + +> List of benefits filled by the Subject Matter Experts while reviewing this version: + +- Benefit 1 +- Benefit 2 + +#### Concerns + +> Template for Subject Matter Experts review for this version: +> Status: New | Ongoing | Resolved + +| # | Concern | Resolution | Status | +| --: | :------ | :--------- | -----: | +| 1 | | | | +| 2 | | | | + +## Copyright + +Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). From 99cade9c653355113a9f64b0bec25c4eb0872c94 Mon Sep 17 00:00:00 2001 From: hatti Date: Tue, 23 Jul 2024 00:03:35 +0800 Subject: [PATCH 147/150] chore: remove duplicate words (#554) remove duplicate words to enhance readability. --- neps/nep-0145.md | 2 +- neps/nep-0393.md | 2 +- specs/NetworkSpec/NetworkSpec.md | 2 +- specs/Proposals/0005-access-keys.md | 2 +- specs/RuntimeSpec/Components/BindingsSpec/TrieAPI.md | 6 +++--- specs/RuntimeSpec/Components/RuntimeCrate.md | 2 +- specs/RuntimeSpec/Fees/Fees.md | 2 +- specs/RuntimeSpec/FunctionCall.md | 2 +- specs/RuntimeSpec/Receipts.md | 2 +- specs/Standards/StorageManagement.md | 2 +- 10 files changed, 12 insertions(+), 12 deletions(-) diff --git a/neps/nep-0145.md b/neps/nep-0145.md index 88b77ef32..c6fd70f74 100644 --- a/neps/nep-0145.md +++ b/neps/nep-0145.md @@ -207,7 +207,7 @@ Bob wants to close his account, but has a non-zero balance of `ft` tokens. ### Example 2: Social Media Contract -Imagine a social media smart contract which passes storage costs onto users for posts and follower data. Let's say this this contract is deployed at account `social`. Like the Fungible Token contract example above, the `storage_balance_bounds.min` is 0.00235, because this contract will likewise add a newly-registered user to an internal Map. However, this contract sets no `storage_balance_bounds.max`, since users can add more data to the contract over time and must cover the cost for this storage. +Imagine a social media smart contract which passes storage costs onto users for posts and follower data. Let's say this contract is deployed at account `social`. Like the Fungible Token contract example above, the `storage_balance_bounds.min` is 0.00235, because this contract will likewise add a newly-registered user to an internal Map. However, this contract sets no `storage_balance_bounds.max`, since users can add more data to the contract over time and must cover the cost for this storage. So for this contract, `storage_balance_bounds` will return: diff --git a/neps/nep-0393.md b/neps/nep-0393.md index 567a3ebe6..c414405ba 100644 --- a/neps/nep-0393.md +++ b/neps/nep-0393.md @@ -213,7 +213,7 @@ Implementation Notes: ### Renewal Soulbound tokens can have an _expire date_. It is useful for tokens which are related to real world certificates with expire time, or social mechanisms (e.g. community membership). Such tokens SHOULD have an option to be renewable. Examples include mandatory renewal with a frequency to check that the owner is still alive, or renew membership to a DAO that uses SBTs as membership gating. -Registry defines `sbt_renew` method allowing issuers to update the token expire date. The issuer can set a the _expire date_ in the past. This is useful if an issuer wants to invalidate the token without removing it. +Registry defines `sbt_renew` method allowing issuers to update the token expire date. The issuer can set the _expire date_ in the past. This is useful if an issuer wants to invalidate the token without removing it. ### Burning tokens diff --git a/specs/NetworkSpec/NetworkSpec.md b/specs/NetworkSpec/NetworkSpec.md index dd15c3cfa..442de7d70 100644 --- a/specs/NetworkSpec/NetworkSpec.md +++ b/specs/NetworkSpec/NetworkSpec.md @@ -124,7 +124,7 @@ def on_announce_accounts_received(self, announcements): When a node needs to send a message to another peer, it checks in the routing table if it is connected to that peer, possibly not directly but through several hops. Then it select one of the shortest path to the target peer and sends a [`RoutedMessage`](Messages.md#routedmessage) to the first peer in the path. -When it receives a [`RoutedMessage`](Messages.md#routedmessage), it check if it is the target, in that case consume the body of the message, otherwise it finds a route to the target following described approach and sends the message again. Is is important that before routing a message each peer check signature from original author of the message, passing a message with invalid signature can result in ban for the sender. It is not required however checking the content of the message itself. +When it receives a [`RoutedMessage`](Messages.md#routedmessage), it check if it is the target, in that case consume the body of the message, otherwise it finds a route to the target following described approach and sends the message again. It is important that before routing a message each peer check signature from original author of the message, passing a message with invalid signature can result in ban for the sender. It is not required however checking the content of the message itself. Each [`RoutedMessage`](Messages.md#routedmessage) is equipped with a time-to-live integer. If this message is not for the node processing it, it decrement the field by one before routing it; if the value is 0, the node drops the message instead of routing it. diff --git a/specs/Proposals/0005-access-keys.md b/specs/Proposals/0005-access-keys.md index 982435538..e8d8de487 100644 --- a/specs/Proposals/0005-access-keys.md +++ b/specs/Proposals/0005-access-keys.md @@ -267,7 +267,7 @@ When some amount is spent, it's subtracted from both the allowance of the access If in some case the user wants to have unlimited allowance for this key, then we have a `None` allowance option. NOTE: In the previous iteration of access keys, we used balance instead of the allowance. -But it required to sum up all access keys balances to get the the total account balance. +But it required to sum up all access keys balances to get the total account balance. It also prevented sharing of the account balance between access keys. #### Permissions diff --git a/specs/RuntimeSpec/Components/BindingsSpec/TrieAPI.md b/specs/RuntimeSpec/Components/BindingsSpec/TrieAPI.md index ccb4745ca..4a9dd7bb4 100644 --- a/specs/RuntimeSpec/Components/BindingsSpec/TrieAPI.md +++ b/specs/RuntimeSpec/Components/BindingsSpec/TrieAPI.md @@ -115,7 +115,7 @@ Checks if there is a key-value pair. storage_iter_prefix(prefix_len: u64, prefix_ptr: u64) -> u64 ``` -DEPRECATED, calling it will result result in `HostError::Deprecated` error. +DEPRECATED, calling it will result in `HostError::Deprecated` error. Creates an iterator object inside the host. Returns the identifier that uniquely differentiates the given iterator from other iterators that can be simultaneously created. @@ -135,7 +135,7 @@ created. storage_iter_range(start_len: u64, start_ptr: u64, end_len: u64, end_ptr: u64) -> u64 ``` -DEPRECATED, calling it will result result in `HostError::Deprecated` error. +DEPRECATED, calling it will result in `HostError::Deprecated` error. Similarly to `storage_iter_prefix` creates an iterator object inside the host. @@ -156,7 +156,7 @@ Note, this definition allows for `start` or `end` keys to not actually exist on storage_iter_next(iterator_id: u64, key_register_id: u64, value_register_id: u64) -> u64 ``` -DEPRECATED, calling it will result result in `HostError::Deprecated` error. +DEPRECATED, calling it will result in `HostError::Deprecated` error. Advances iterator and saves the next key and value in the register. ###### Normal operation diff --git a/specs/RuntimeSpec/Components/RuntimeCrate.md b/specs/RuntimeSpec/Components/RuntimeCrate.md index 66e990f62..2535e2a85 100644 --- a/specs/RuntimeSpec/Components/RuntimeCrate.md +++ b/specs/RuntimeSpec/Components/RuntimeCrate.md @@ -58,7 +58,7 @@ Runtime does validation again for the following reasons: - to compute burnt gas; - to validate transactions again, in case the chunk producer was malicious. -If the transaction has the the same `signer_id` and `receiver_id`, then the new receipt is added to the list of new local receipts, +If the transaction has the same `signer_id` and `receiver_id`, then the new receipt is added to the list of new local receipts, otherwise it's added to the list of new outgoing receipts. ## Receipt processing diff --git a/specs/RuntimeSpec/Fees/Fees.md b/specs/RuntimeSpec/Fees/Fees.md index 67b279652..5f2ee01d0 100644 --- a/specs/RuntimeSpec/Fees/Fees.md +++ b/specs/RuntimeSpec/Fees/Fees.md @@ -136,7 +136,7 @@ It contains 4 actions with 2 actions that requires to compute number of bytes. We assume `code` in `DeployContractAction` contains `128000` bytes. And `FunctionCallAction` has `method_name` with length of `3` and `args` length of `26`, so total of `29`. -First let's compute the the amount that will be burned immediately for sending a receipt. +First let's compute the amount that will be burned immediately for sending a receipt. ```python burnt_gas = \ config.action_receipt_creation_config.send_not_sir + \ diff --git a/specs/RuntimeSpec/FunctionCall.md b/specs/RuntimeSpec/FunctionCall.md index 7b6bd7968..82300cd0c 100644 --- a/specs/RuntimeSpec/FunctionCall.md +++ b/specs/RuntimeSpec/FunctionCall.md @@ -92,7 +92,7 @@ returned value. Eventually, these `DataReceipt` will be delivered to the corresp ### ReceiptIndex Result Successful result could not return any Value, but generates a bunch of new ActionReceipts instead. -One example could be a callback. In this case, we assume the the new Receipt will send its Value +One example could be a callback. In this case, we assume the new Receipt will send its Value Result to the [`output_data_receivers`](Receipts.md#output_data_receivers) of the current `ActionReceipt`. diff --git a/specs/RuntimeSpec/Receipts.md b/specs/RuntimeSpec/Receipts.md index 1eec90bf3..9ac3f298b 100644 --- a/specs/RuntimeSpec/Receipts.md +++ b/specs/RuntimeSpec/Receipts.md @@ -100,7 +100,7 @@ If smart contract finishes its execution with some value (not Promise), runtime - **`type`**: `CryptoHash` -An a unique `DataReceipt` identifier. +A unique `DataReceipt` identifier. #### data diff --git a/specs/Standards/StorageManagement.md b/specs/Standards/StorageManagement.md index 712ab73f9..16a024f0a 100644 --- a/specs/Standards/StorageManagement.md +++ b/specs/Standards/StorageManagement.md @@ -176,7 +176,7 @@ Bob wants to close his account, but has a non-zero balance of `ft` tokens. ### Example 2: Social Media Contract -Imagine a social media smart contract which passes storage costs onto users for posts and follower data. Let's say this this contract is deployed at account `social`. Like the Fungible Token contract example above, the `storage_balance_bounds.min` is 0.00235, because this contract will likewise add a newly-registered user to an internal Map. However, this contract sets no `storage_balance_bounds.max`, since users can add more data to the contract over time and must cover the cost for this storage. +Imagine a social media smart contract which passes storage costs onto users for posts and follower data. Let's say this contract is deployed at account `social`. Like the Fungible Token contract example above, the `storage_balance_bounds.min` is 0.00235, because this contract will likewise add a newly-registered user to an internal Map. However, this contract sets no `storage_balance_bounds.max`, since users can add more data to the contract over time and must cover the cost for this storage. So for this contract, `storage_balance_bounds` will return: From 97960c20020875c9ce628312e6609f9b71e6deaa Mon Sep 17 00:00:00 2001 From: dsuggs-near <148899138+dsuggs-near@users.noreply.github.com> Date: Mon, 22 Jul 2024 12:05:14 -0400 Subject: [PATCH 148/150] [Snyk] Upgrade @docusaurus/plugin-sitemap from 2.2.0 to 2.4.3 (#523) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit

This PR was automatically created by Snyk using the credentials of a real user.


Snyk has created this PR to upgrade @docusaurus/plugin-sitemap from 2.2.0 to 2.4.3.

:information_source: Keep your dependencies up-to-date. This makes it easier to fix existing vulnerabilities and to more quickly identify and fix newly disclosed vulnerabilities when they affect your project.
- The recommended version is **5 versions** ahead of your current version. - The recommended version was released **3 months ago**, on 2023-09-20.
**Note:** *You are seeing this because you or someone else with access to this repository has authorized Snyk to open upgrade PRs.* For more information: 🧐 [View latest project report](https://app.snyk.io/org/near-ecosystem/project/8d05cdef-c477-4162-9825-46c480ed630d?utm_source=github&utm_medium=referral&page=upgrade-pr) 🛠 [Adjust upgrade PR settings](https://app.snyk.io/org/near-ecosystem/project/8d05cdef-c477-4162-9825-46c480ed630d/settings/integration?utm_source=github&utm_medium=referral&page=upgrade-pr) 🔕 [Ignore this dependency or unsubscribe from future upgrade PRs](https://app.snyk.io/org/near-ecosystem/project/8d05cdef-c477-4162-9825-46c480ed630d/settings/integration?pkg=@docusaurus/plugin-sitemap&utm_source=github&utm_medium=referral&page=upgrade-pr#auto-dep-upgrades) Co-authored-by: snyk-bot Co-authored-by: Robert Zaremba --- website/package.json | 2 +- website/yarn.lock | 194 ++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 194 insertions(+), 2 deletions(-) diff --git a/website/package.json b/website/package.json index 0bf3f81fb..a37aec94e 100644 --- a/website/package.json +++ b/website/package.json @@ -16,7 +16,7 @@ "dependencies": { "@babel/helper-get-function-arity": "^7.16.7", "@docusaurus/core": "^2.0.0-beta.15", - "@docusaurus/plugin-sitemap": "^2.0.0-beta.15", + "@docusaurus/plugin-sitemap": "^2.4.3", "@docusaurus/preset-classic": "^2.0.0-beta.15", "@mdx-js/react": "^1.6.21", "clsx": "^1.1.1", diff --git a/website/yarn.lock b/website/yarn.lock index 66c62c12d..7ff61d064 100644 --- a/website/yarn.lock +++ b/website/yarn.lock @@ -1279,6 +1279,83 @@ webpack-merge "^5.8.0" webpackbar "^5.0.2" +"@docusaurus/core@2.4.3": + version "2.4.3" + resolved "https://registry.yarnpkg.com/@docusaurus/core/-/core-2.4.3.tgz#d86624901386fd8164ce4bff9cc7f16fde57f523" + integrity sha512-dWH5P7cgeNSIg9ufReX6gaCl/TmrGKD38Orbwuz05WPhAQtFXHd5B8Qym1TiXfvUNvwoYKkAJOJuGe8ou0Z7PA== + dependencies: + "@babel/core" "^7.18.6" + "@babel/generator" "^7.18.7" + "@babel/plugin-syntax-dynamic-import" "^7.8.3" + "@babel/plugin-transform-runtime" "^7.18.6" + "@babel/preset-env" "^7.18.6" + "@babel/preset-react" "^7.18.6" + "@babel/preset-typescript" "^7.18.6" + "@babel/runtime" "^7.18.6" + "@babel/runtime-corejs3" "^7.18.6" + "@babel/traverse" "^7.18.8" + "@docusaurus/cssnano-preset" "2.4.3" + "@docusaurus/logger" "2.4.3" + "@docusaurus/mdx-loader" "2.4.3" + "@docusaurus/react-loadable" "5.5.2" + "@docusaurus/utils" "2.4.3" + "@docusaurus/utils-common" "2.4.3" + "@docusaurus/utils-validation" "2.4.3" + "@slorber/static-site-generator-webpack-plugin" "^4.0.7" + "@svgr/webpack" "^6.2.1" + autoprefixer "^10.4.7" + babel-loader "^8.2.5" + babel-plugin-dynamic-import-node "^2.3.3" + boxen "^6.2.1" + chalk "^4.1.2" + chokidar "^3.5.3" + clean-css "^5.3.0" + cli-table3 "^0.6.2" + combine-promises "^1.1.0" + commander "^5.1.0" + copy-webpack-plugin "^11.0.0" + core-js "^3.23.3" + css-loader "^6.7.1" + css-minimizer-webpack-plugin "^4.0.0" + cssnano "^5.1.12" + del "^6.1.1" + detect-port "^1.3.0" + escape-html "^1.0.3" + eta "^2.0.0" + file-loader "^6.2.0" + fs-extra "^10.1.0" + html-minifier-terser "^6.1.0" + html-tags "^3.2.0" + html-webpack-plugin "^5.5.0" + import-fresh "^3.3.0" + leven "^3.1.0" + lodash "^4.17.21" + mini-css-extract-plugin "^2.6.1" + postcss "^8.4.14" + postcss-loader "^7.0.0" + prompts "^2.4.2" + react-dev-utils "^12.0.1" + react-helmet-async "^1.3.0" + react-loadable "npm:@docusaurus/react-loadable@5.5.2" + react-loadable-ssr-addon-v5-slorber "^1.0.1" + react-router "^5.3.3" + react-router-config "^5.1.1" + react-router-dom "^5.3.3" + rtl-detect "^1.0.4" + semver "^7.3.7" + serve-handler "^6.1.3" + shelljs "^0.8.5" + terser-webpack-plugin "^5.3.3" + tslib "^2.4.0" + update-notifier "^5.1.0" + url-loader "^4.1.1" + wait-on "^6.0.1" + webpack "^5.73.0" + webpack-bundle-analyzer "^4.5.0" + webpack-dev-server "^4.9.3" + webpack-merge "^5.8.0" + webpackbar "^5.0.2" + "@docusaurus/cssnano-preset@2.2.0": version "2.2.0" resolved "https://registry.yarnpkg.com/@docusaurus/cssnano-preset/-/cssnano-preset-2.2.0.tgz#fc05044659051ae74ab4482afcf4a9936e81d523" @@ -1289,6 +1366,16 @@ postcss-sort-media-queries "^4.2.1" tslib "^2.4.0" +"@docusaurus/cssnano-preset@2.4.3": + version "2.4.3" + resolved "https://registry.yarnpkg.com/@docusaurus/cssnano-preset/-/cssnano-preset-2.4.3.tgz#1d7e833c41ce240fcc2812a2ac27f7b862f32de0" + integrity sha512-ZvGSRCi7z9wLnZrXNPG6DmVPHdKGd8dIn9pYbEOFiYihfv4uDR3UtxogmKf+rT8ZlKFf5Lqne8E8nt08zNM8CA== + dependencies: + cssnano-preset-advanced "^5.3.8" + postcss "^8.4.14" + postcss-sort-media-queries "^4.2.1" + tslib "^2.4.0" + "@docusaurus/logger@2.2.0": version "2.2.0" resolved "https://registry.yarnpkg.com/@docusaurus/logger/-/logger-2.2.0.tgz#ea2f7feda7b8675485933b87f06d9c976d17423f" @@ -1297,6 +1384,14 @@ chalk "^4.1.2" tslib "^2.4.0" +"@docusaurus/logger@2.4.3": + version "2.4.3" + resolved "https://registry.yarnpkg.com/@docusaurus/logger/-/logger-2.4.3.tgz#518bbc965fb4ebe8f1d0b14e5f4161607552d34c" + integrity sha512-Zxws7r3yLufk9xM1zq9ged0YHs65mlRmtsobnFkdZTxWXdTYlWWLWdKyNKAsVC+D7zg+pv2fGbyabdOnyZOM3w== + dependencies: + chalk "^4.1.2" + tslib "^2.4.0" + "@docusaurus/mdx-loader@2.2.0": version "2.2.0" resolved "https://registry.yarnpkg.com/@docusaurus/mdx-loader/-/mdx-loader-2.2.0.tgz#fd558f429e5d9403d284bd4214e54d9768b041a0" @@ -1320,6 +1415,29 @@ url-loader "^4.1.1" webpack "^5.73.0" +"@docusaurus/mdx-loader@2.4.3": + version "2.4.3" + resolved "https://registry.yarnpkg.com/@docusaurus/mdx-loader/-/mdx-loader-2.4.3.tgz#e8ff37f30a060eaa97b8121c135f74cb531a4a3e" + integrity sha512-b1+fDnWtl3GiqkL0BRjYtc94FZrcDDBV1j8446+4tptB9BAOlePwG2p/pK6vGvfL53lkOsszXMghr2g67M0vCw== + dependencies: + "@babel/parser" "^7.18.8" + "@babel/traverse" "^7.18.8" + "@docusaurus/logger" "2.4.3" + "@docusaurus/utils" "2.4.3" + "@mdx-js/mdx" "^1.6.22" + escape-html "^1.0.3" + file-loader "^6.2.0" + fs-extra "^10.1.0" + image-size "^1.0.1" + mdast-util-to-string "^2.0.0" + remark-emoji "^2.2.0" + stringify-object "^3.3.0" + tslib "^2.4.0" + unified "^9.2.2" + unist-util-visit "^2.0.3" + url-loader "^4.1.1" + webpack "^5.73.0" + "@docusaurus/module-type-aliases@2.2.0": version "2.2.0" resolved "https://registry.yarnpkg.com/@docusaurus/module-type-aliases/-/module-type-aliases-2.2.0.tgz#1e23e54a1bbb6fde1961e4fa395b1b69f4803ba5" @@ -1424,7 +1542,7 @@ "@docusaurus/utils-validation" "2.2.0" tslib "^2.4.0" -"@docusaurus/plugin-sitemap@2.2.0", "@docusaurus/plugin-sitemap@^2.0.0-beta.15": +"@docusaurus/plugin-sitemap@2.2.0": version "2.2.0" resolved "https://registry.yarnpkg.com/@docusaurus/plugin-sitemap/-/plugin-sitemap-2.2.0.tgz#876da60937886032d63143253d420db6a4b34773" integrity sha512-0jAmyRDN/aI265CbWZNZuQpFqiZuo+5otk2MylU9iVrz/4J7gSc+ZJ9cy4EHrEsW7PV8s1w18hIEsmcA1YgkKg== @@ -1439,6 +1557,21 @@ sitemap "^7.1.1" tslib "^2.4.0" +"@docusaurus/plugin-sitemap@^2.4.3": + version "2.4.3" + resolved "https://registry.yarnpkg.com/@docusaurus/plugin-sitemap/-/plugin-sitemap-2.4.3.tgz#1b3930900a8f89670ce7e8f83fb4730cd3298c32" + integrity sha512-LRQYrK1oH1rNfr4YvWBmRzTL0LN9UAPxBbghgeFRBm5yloF6P+zv1tm2pe2hQTX/QP5bSKdnajCvfnScgKXMZQ== + dependencies: + "@docusaurus/core" "2.4.3" + "@docusaurus/logger" "2.4.3" + "@docusaurus/types" "2.4.3" + "@docusaurus/utils" "2.4.3" + "@docusaurus/utils-common" "2.4.3" + "@docusaurus/utils-validation" "2.4.3" + fs-extra "^10.1.0" + sitemap "^7.1.1" + tslib "^2.4.0" + "@docusaurus/preset-classic@^2.0.0-beta.15": version "2.2.0" resolved "https://registry.yarnpkg.com/@docusaurus/preset-classic/-/preset-classic-2.2.0.tgz#bece5a043eeb74430f7c6c7510000b9c43669eb7" @@ -1560,6 +1693,20 @@ webpack "^5.73.0" webpack-merge "^5.8.0" +"@docusaurus/types@2.4.3": + version "2.4.3" + resolved "https://registry.yarnpkg.com/@docusaurus/types/-/types-2.4.3.tgz#4aead281ca09f721b3c0a9b926818450cfa3db31" + integrity sha512-W6zNLGQqfrp/EoPD0bhb9n7OobP+RHpmvVzpA+Z/IuU3Q63njJM24hmT0GYboovWcDtFmnIJC9wcyx4RVPQscw== + dependencies: + "@types/history" "^4.7.11" + "@types/react" "*" + commander "^5.1.0" + joi "^17.6.0" + react-helmet-async "^1.3.0" + utility-types "^3.10.0" + webpack "^5.73.0" + webpack-merge "^5.8.0" + "@docusaurus/utils-common@2.2.0": version "2.2.0" resolved "https://registry.yarnpkg.com/@docusaurus/utils-common/-/utils-common-2.2.0.tgz#a401c1b93a8697dd566baf6ac64f0fdff1641a78" @@ -1567,6 +1714,13 @@ dependencies: tslib "^2.4.0" +"@docusaurus/utils-common@2.4.3": + version "2.4.3" + resolved "https://registry.yarnpkg.com/@docusaurus/utils-common/-/utils-common-2.4.3.tgz#30656c39ef1ce7e002af7ba39ea08330f58efcfb" + integrity sha512-/jascp4GbLQCPVmcGkPzEQjNaAk3ADVfMtudk49Ggb+131B1WDD6HqlSmDf8MxGdy7Dja2gc+StHf01kiWoTDQ== + dependencies: + tslib "^2.4.0" + "@docusaurus/utils-validation@2.2.0": version "2.2.0" resolved "https://registry.yarnpkg.com/@docusaurus/utils-validation/-/utils-validation-2.2.0.tgz#04d4d103137ad0145883971d3aa497f4a1315f25" @@ -1578,6 +1732,17 @@ js-yaml "^4.1.0" tslib "^2.4.0" +"@docusaurus/utils-validation@2.4.3": + version "2.4.3" + resolved "https://registry.yarnpkg.com/@docusaurus/utils-validation/-/utils-validation-2.4.3.tgz#8122c394feef3e96c73f6433987837ec206a63fb" + integrity sha512-G2+Vt3WR5E/9drAobP+hhZQMaswRwDlp6qOMi7o7ZypB+VO7N//DZWhZEwhcRGepMDJGQEwtPv7UxtYwPL9PBw== + dependencies: + "@docusaurus/logger" "2.4.3" + "@docusaurus/utils" "2.4.3" + joi "^17.6.0" + js-yaml "^4.1.0" + tslib "^2.4.0" + "@docusaurus/utils@2.2.0": version "2.2.0" resolved "https://registry.yarnpkg.com/@docusaurus/utils/-/utils-2.2.0.tgz#3d6f9b7a69168d5c92d371bf21c556a4f50d1da6" @@ -1599,6 +1764,28 @@ url-loader "^4.1.1" webpack "^5.73.0" +"@docusaurus/utils@2.4.3": + version "2.4.3" + resolved "https://registry.yarnpkg.com/@docusaurus/utils/-/utils-2.4.3.tgz#52b000d989380a2125831b84e3a7327bef471e89" + integrity sha512-fKcXsjrD86Smxv8Pt0TBFqYieZZCPh4cbf9oszUq/AMhZn3ujwpKaVYZACPX8mmjtYx0JOgNx52CREBfiGQB4A== + dependencies: + "@docusaurus/logger" "2.4.3" + "@svgr/webpack" "^6.2.1" + escape-string-regexp "^4.0.0" + file-loader "^6.2.0" + fs-extra "^10.1.0" + github-slugger "^1.4.0" + globby "^11.1.0" + gray-matter "^4.0.3" + js-yaml "^4.1.0" + lodash "^4.17.21" + micromatch "^4.0.5" + resolve-pathname "^3.0.0" + shelljs "^0.8.5" + tslib "^2.4.0" + url-loader "^4.1.1" + webpack "^5.73.0" + "@hapi/hoek@^9.0.0": version "9.3.0" resolved "https://registry.yarnpkg.com/@hapi/hoek/-/hoek-9.3.0.tgz#8368869dcb735be2e7f5cb7647de78e167a251fb" @@ -3786,6 +3973,11 @@ eta@^1.12.3: resolved "https://registry.yarnpkg.com/eta/-/eta-1.12.3.tgz#2982d08adfbef39f9fa50e2fbd42d7337e7338b1" integrity sha512-qHixwbDLtekO/d51Yr4glcaUJCIjGVJyTzuqV4GPlgZo1YpgOKG+avQynErZIYrfM6JIJdtiG2Kox8tbb+DoGg== +eta@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/eta/-/eta-2.2.0.tgz#eb8b5f8c4e8b6306561a455e62cd7492fe3a9b8a" + integrity sha512-UVQ72Rqjy/ZKQalzV5dCCJP80GrmPrMxh6NlNf+erV6ObL0ZFkhCstWRawS85z3smdr3d2wXPsZEY7rDPfGd2g== + etag@~1.8.1: version "1.8.1" resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887" From 6e636ba215e10bfa94ebd5381e3f0cee8b0aeae2 Mon Sep 17 00:00:00 2001 From: Vlad Frolov Date: Fri, 26 Jul 2024 09:37:00 +0200 Subject: [PATCH 149/150] chore: Bumped website dependencies (docusaurus 2.4.3) --- website/package.json | 6 +- website/yarn.lock | 4636 +++++++++++++++++++++--------------------- 2 files changed, 2294 insertions(+), 2348 deletions(-) diff --git a/website/package.json b/website/package.json index a37aec94e..568456f85 100644 --- a/website/package.json +++ b/website/package.json @@ -15,9 +15,9 @@ }, "dependencies": { "@babel/helper-get-function-arity": "^7.16.7", - "@docusaurus/core": "^2.0.0-beta.15", + "@docusaurus/core": "^2.4.3", "@docusaurus/plugin-sitemap": "^2.4.3", - "@docusaurus/preset-classic": "^2.0.0-beta.15", + "@docusaurus/preset-classic": "^2.4.3", "@mdx-js/react": "^1.6.21", "clsx": "^1.1.1", "gleap": "^7.0.29", @@ -26,7 +26,7 @@ "react": "^17.0.1", "react-dom": "^17.0.1", "rehype-katex": "5", - "rehype-mathjax": "^4.0.2", + "rehype-mathjax": "^4.0.3", "remark-math": "3" }, "browserslist": { diff --git a/website/yarn.lock b/website/yarn.lock index 7ff61d064..4c1ff0153 100644 --- a/website/yarn.lock +++ b/website/yarn.lock @@ -2,153 +2,179 @@ # yarn lockfile v1 -"@algolia/autocomplete-core@1.7.2": - version "1.7.2" - resolved "https://registry.yarnpkg.com/@algolia/autocomplete-core/-/autocomplete-core-1.7.2.tgz#8abbed88082f611997538760dffcb43b33b1fd1d" - integrity sha512-eclwUDC6qfApNnEfu1uWcL/rudQsn59tjEoUYZYE2JSXZrHLRjBUGMxiCoknobU2Pva8ejb0eRxpIYDtVVqdsw== +"@algolia/autocomplete-core@1.9.3": + version "1.9.3" + resolved "https://registry.yarnpkg.com/@algolia/autocomplete-core/-/autocomplete-core-1.9.3.tgz#1d56482a768c33aae0868c8533049e02e8961be7" + integrity sha512-009HdfugtGCdC4JdXUbVJClA0q0zh24yyePn+KUGk3rP7j8FEe/m5Yo/z65gn6nP/cM39PxpzqKrL7A6fP6PPw== dependencies: - "@algolia/autocomplete-shared" "1.7.2" + "@algolia/autocomplete-plugin-algolia-insights" "1.9.3" + "@algolia/autocomplete-shared" "1.9.3" -"@algolia/autocomplete-preset-algolia@1.7.2": - version "1.7.2" - resolved "https://registry.yarnpkg.com/@algolia/autocomplete-preset-algolia/-/autocomplete-preset-algolia-1.7.2.tgz#9cd4f64b3d64399657ee2dc2b7e0a939e0713a26" - integrity sha512-+RYEG6B0QiGGfRb2G3MtPfyrl0dALF3cQNTWBzBX6p5o01vCCGTTinAm2UKG3tfc2CnOMAtnPLkzNZyJUpnVJw== +"@algolia/autocomplete-plugin-algolia-insights@1.9.3": + version "1.9.3" + resolved "https://registry.yarnpkg.com/@algolia/autocomplete-plugin-algolia-insights/-/autocomplete-plugin-algolia-insights-1.9.3.tgz#9b7f8641052c8ead6d66c1623d444cbe19dde587" + integrity sha512-a/yTUkcO/Vyy+JffmAnTWbr4/90cLzw+CC3bRbhnULr/EM0fGNvM13oQQ14f2moLMcVDyAx/leczLlAOovhSZg== + dependencies: + "@algolia/autocomplete-shared" "1.9.3" + +"@algolia/autocomplete-preset-algolia@1.9.3": + version "1.9.3" + resolved "https://registry.yarnpkg.com/@algolia/autocomplete-preset-algolia/-/autocomplete-preset-algolia-1.9.3.tgz#64cca4a4304cfcad2cf730e83067e0c1b2f485da" + integrity sha512-d4qlt6YmrLMYy95n5TB52wtNDr6EgAIPH81dvvvW8UmuWRgxEtY0NJiPwl/h95JtG2vmRM804M0DSwMCNZlzRA== dependencies: - "@algolia/autocomplete-shared" "1.7.2" + "@algolia/autocomplete-shared" "1.9.3" -"@algolia/autocomplete-shared@1.7.2": - version "1.7.2" - resolved "https://registry.yarnpkg.com/@algolia/autocomplete-shared/-/autocomplete-shared-1.7.2.tgz#daa23280e78d3b42ae9564d12470ae034db51a89" - integrity sha512-QCckjiC7xXHIUaIL3ektBtjJ0w7tTA3iqKcAE/Hjn1lZ5omp7i3Y4e09rAr9ZybqirL7AbxCLLq0Ra5DDPKeug== +"@algolia/autocomplete-shared@1.9.3": + version "1.9.3" + resolved "https://registry.yarnpkg.com/@algolia/autocomplete-shared/-/autocomplete-shared-1.9.3.tgz#2e22e830d36f0a9cf2c0ccd3c7f6d59435b77dfa" + integrity sha512-Wnm9E4Ye6Rl6sTTqjoymD+l8DjSTHsHboVRYrKgEt8Q7UHm9nYbqhN/i0fhUYA3OAEH7WA8x3jfpnmJm3rKvaQ== -"@algolia/cache-browser-local-storage@4.14.2": - version "4.14.2" - resolved "https://registry.yarnpkg.com/@algolia/cache-browser-local-storage/-/cache-browser-local-storage-4.14.2.tgz#d5b1b90130ca87c6321de876e167df9ec6524936" - integrity sha512-FRweBkK/ywO+GKYfAWbrepewQsPTIEirhi1BdykX9mxvBPtGNKccYAxvGdDCumU1jL4r3cayio4psfzKMejBlA== +"@algolia/cache-browser-local-storage@4.24.0": + version "4.24.0" + resolved "https://registry.yarnpkg.com/@algolia/cache-browser-local-storage/-/cache-browser-local-storage-4.24.0.tgz#97bc6d067a9fd932b9c922faa6b7fd6e546e1348" + integrity sha512-t63W9BnoXVrGy9iYHBgObNXqYXM3tYXCjDSHeNwnsc324r4o5UiVKUiAB4THQ5z9U5hTj6qUvwg/Ez43ZD85ww== dependencies: - "@algolia/cache-common" "4.14.2" + "@algolia/cache-common" "4.24.0" -"@algolia/cache-common@4.14.2": - version "4.14.2" - resolved "https://registry.yarnpkg.com/@algolia/cache-common/-/cache-common-4.14.2.tgz#b946b6103c922f0c06006fb6929163ed2c67d598" - integrity sha512-SbvAlG9VqNanCErr44q6lEKD2qoK4XtFNx9Qn8FK26ePCI8I9yU7pYB+eM/cZdS9SzQCRJBbHUumVr4bsQ4uxg== +"@algolia/cache-common@4.24.0": + version "4.24.0" + resolved "https://registry.yarnpkg.com/@algolia/cache-common/-/cache-common-4.24.0.tgz#81a8d3a82ceb75302abb9b150a52eba9960c9744" + integrity sha512-emi+v+DmVLpMGhp0V9q9h5CdkURsNmFC+cOS6uK9ndeJm9J4TiqSvPYVu+THUP8P/S08rxf5x2P+p3CfID0Y4g== -"@algolia/cache-in-memory@4.14.2": - version "4.14.2" - resolved "https://registry.yarnpkg.com/@algolia/cache-in-memory/-/cache-in-memory-4.14.2.tgz#88e4a21474f9ac05331c2fa3ceb929684a395a24" - integrity sha512-HrOukWoop9XB/VFojPv1R5SVXowgI56T9pmezd/djh2JnVN/vXswhXV51RKy4nCpqxyHt/aGFSq2qkDvj6KiuQ== +"@algolia/cache-in-memory@4.24.0": + version "4.24.0" + resolved "https://registry.yarnpkg.com/@algolia/cache-in-memory/-/cache-in-memory-4.24.0.tgz#ffcf8872f3a10cb85c4f4641bdffd307933a6e44" + integrity sha512-gDrt2so19jW26jY3/MkFg5mEypFIPbPoXsQGQWAi6TrCPsNOSEYepBMPlucqWigsmEy/prp5ug2jy/N3PVG/8w== dependencies: - "@algolia/cache-common" "4.14.2" + "@algolia/cache-common" "4.24.0" -"@algolia/client-account@4.14.2": - version "4.14.2" - resolved "https://registry.yarnpkg.com/@algolia/client-account/-/client-account-4.14.2.tgz#b76ac1ba9ea71e8c3f77a1805b48350dc0728a16" - integrity sha512-WHtriQqGyibbb/Rx71YY43T0cXqyelEU0lB2QMBRXvD2X0iyeGl4qMxocgEIcbHyK7uqE7hKgjT8aBrHqhgc1w== +"@algolia/client-account@4.24.0": + version "4.24.0" + resolved "https://registry.yarnpkg.com/@algolia/client-account/-/client-account-4.24.0.tgz#eba7a921d828e7c8c40a32d4add21206c7fe12f1" + integrity sha512-adcvyJ3KjPZFDybxlqnf+5KgxJtBjwTPTeyG2aOyoJvx0Y8dUQAEOEVOJ/GBxX0WWNbmaSrhDURMhc+QeevDsA== dependencies: - "@algolia/client-common" "4.14.2" - "@algolia/client-search" "4.14.2" - "@algolia/transporter" "4.14.2" + "@algolia/client-common" "4.24.0" + "@algolia/client-search" "4.24.0" + "@algolia/transporter" "4.24.0" -"@algolia/client-analytics@4.14.2": - version "4.14.2" - resolved "https://registry.yarnpkg.com/@algolia/client-analytics/-/client-analytics-4.14.2.tgz#ca04dcaf9a78ee5c92c5cb5e9c74cf031eb2f1fb" - integrity sha512-yBvBv2mw+HX5a+aeR0dkvUbFZsiC4FKSnfqk9rrfX+QrlNOKEhCG0tJzjiOggRW4EcNqRmaTULIYvIzQVL2KYQ== +"@algolia/client-analytics@4.24.0": + version "4.24.0" + resolved "https://registry.yarnpkg.com/@algolia/client-analytics/-/client-analytics-4.24.0.tgz#9d2576c46a9093a14e668833c505ea697a1a3e30" + integrity sha512-y8jOZt1OjwWU4N2qr8G4AxXAzaa8DBvyHTWlHzX/7Me1LX8OayfgHexqrsL4vSBcoMmVw2XnVW9MhL+Y2ZDJXg== dependencies: - "@algolia/client-common" "4.14.2" - "@algolia/client-search" "4.14.2" - "@algolia/requester-common" "4.14.2" - "@algolia/transporter" "4.14.2" + "@algolia/client-common" "4.24.0" + "@algolia/client-search" "4.24.0" + "@algolia/requester-common" "4.24.0" + "@algolia/transporter" "4.24.0" -"@algolia/client-common@4.14.2": - version "4.14.2" - resolved "https://registry.yarnpkg.com/@algolia/client-common/-/client-common-4.14.2.tgz#e1324e167ffa8af60f3e8bcd122110fd0bfd1300" - integrity sha512-43o4fslNLcktgtDMVaT5XwlzsDPzlqvqesRi4MjQz2x4/Sxm7zYg5LRYFol1BIhG6EwxKvSUq8HcC/KxJu3J0Q== +"@algolia/client-common@4.24.0": + version "4.24.0" + resolved "https://registry.yarnpkg.com/@algolia/client-common/-/client-common-4.24.0.tgz#77c46eee42b9444a1d1c1583a83f7df4398a649d" + integrity sha512-bc2ROsNL6w6rqpl5jj/UywlIYC21TwSSoFHKl01lYirGMW+9Eek6r02Tocg4gZ8HAw3iBvu6XQiM3BEbmEMoiA== dependencies: - "@algolia/requester-common" "4.14.2" - "@algolia/transporter" "4.14.2" + "@algolia/requester-common" "4.24.0" + "@algolia/transporter" "4.24.0" -"@algolia/client-personalization@4.14.2": - version "4.14.2" - resolved "https://registry.yarnpkg.com/@algolia/client-personalization/-/client-personalization-4.14.2.tgz#656bbb6157a3dd1a4be7de65e457fda136c404ec" - integrity sha512-ACCoLi0cL8CBZ1W/2juehSltrw2iqsQBnfiu/Rbl9W2yE6o2ZUb97+sqN/jBqYNQBS+o0ekTMKNkQjHHAcEXNw== +"@algolia/client-personalization@4.24.0": + version "4.24.0" + resolved "https://registry.yarnpkg.com/@algolia/client-personalization/-/client-personalization-4.24.0.tgz#8b47789fb1cb0f8efbea0f79295b7c5a3850f6ae" + integrity sha512-l5FRFm/yngztweU0HdUzz1rC4yoWCFo3IF+dVIVTfEPg906eZg5BOd1k0K6rZx5JzyyoP4LdmOikfkfGsKVE9w== dependencies: - "@algolia/client-common" "4.14.2" - "@algolia/requester-common" "4.14.2" - "@algolia/transporter" "4.14.2" + "@algolia/client-common" "4.24.0" + "@algolia/requester-common" "4.24.0" + "@algolia/transporter" "4.24.0" -"@algolia/client-search@4.14.2": - version "4.14.2" - resolved "https://registry.yarnpkg.com/@algolia/client-search/-/client-search-4.14.2.tgz#357bdb7e640163f0e33bad231dfcc21f67dc2e92" - integrity sha512-L5zScdOmcZ6NGiVbLKTvP02UbxZ0njd5Vq9nJAmPFtjffUSOGEp11BmD2oMJ5QvARgx2XbX4KzTTNS5ECYIMWw== +"@algolia/client-search@4.24.0": + version "4.24.0" + resolved "https://registry.yarnpkg.com/@algolia/client-search/-/client-search-4.24.0.tgz#75e6c02d33ef3e0f34afd9962c085b856fc4a55f" + integrity sha512-uRW6EpNapmLAD0mW47OXqTP8eiIx5F6qN9/x/7HHO6owL3N1IXqydGwW5nhDFBrV+ldouro2W1VX3XlcUXEFCA== dependencies: - "@algolia/client-common" "4.14.2" - "@algolia/requester-common" "4.14.2" - "@algolia/transporter" "4.14.2" + "@algolia/client-common" "4.24.0" + "@algolia/requester-common" "4.24.0" + "@algolia/transporter" "4.24.0" "@algolia/events@^4.0.1": version "4.0.1" resolved "https://registry.yarnpkg.com/@algolia/events/-/events-4.0.1.tgz#fd39e7477e7bc703d7f893b556f676c032af3950" integrity sha512-FQzvOCgoFXAbf5Y6mYozw2aj5KCJoA3m4heImceldzPSMbdyS4atVjJzXKMsfX3wnZTFYwkkt8/z8UesLHlSBQ== -"@algolia/logger-common@4.14.2": - version "4.14.2" - resolved "https://registry.yarnpkg.com/@algolia/logger-common/-/logger-common-4.14.2.tgz#b74b3a92431f92665519d95942c246793ec390ee" - integrity sha512-/JGlYvdV++IcMHBnVFsqEisTiOeEr6cUJtpjz8zc0A9c31JrtLm318Njc72p14Pnkw3A/5lHHh+QxpJ6WFTmsA== - -"@algolia/logger-console@4.14.2": - version "4.14.2" - resolved "https://registry.yarnpkg.com/@algolia/logger-console/-/logger-console-4.14.2.tgz#ec49cb47408f5811d4792598683923a800abce7b" - integrity sha512-8S2PlpdshbkwlLCSAB5f8c91xyc84VM9Ar9EdfE9UmX+NrKNYnWR1maXXVDQQoto07G1Ol/tYFnFVhUZq0xV/g== - dependencies: - "@algolia/logger-common" "4.14.2" - -"@algolia/requester-browser-xhr@4.14.2": - version "4.14.2" - resolved "https://registry.yarnpkg.com/@algolia/requester-browser-xhr/-/requester-browser-xhr-4.14.2.tgz#a2cd4d9d8d90d53109cc7f3682dc6ebf20f798f2" - integrity sha512-CEh//xYz/WfxHFh7pcMjQNWgpl4wFB85lUMRyVwaDPibNzQRVcV33YS+63fShFWc2+42YEipFGH2iPzlpszmDw== - dependencies: - "@algolia/requester-common" "4.14.2" - -"@algolia/requester-common@4.14.2": - version "4.14.2" - resolved "https://registry.yarnpkg.com/@algolia/requester-common/-/requester-common-4.14.2.tgz#bc4e9e5ee16c953c0ecacbfb334a33c30c28b1a1" - integrity sha512-73YQsBOKa5fvVV3My7iZHu1sUqmjjfs9TteFWwPwDmnad7T0VTCopttcsM3OjLxZFtBnX61Xxl2T2gmG2O4ehg== - -"@algolia/requester-node-http@4.14.2": - version "4.14.2" - resolved "https://registry.yarnpkg.com/@algolia/requester-node-http/-/requester-node-http-4.14.2.tgz#7c1223a1785decaab1def64c83dade6bea45e115" - integrity sha512-oDbb02kd1o5GTEld4pETlPZLY0e+gOSWjWMJHWTgDXbv9rm/o2cF7japO6Vj1ENnrqWvLBmW1OzV9g6FUFhFXg== - dependencies: - "@algolia/requester-common" "4.14.2" - -"@algolia/transporter@4.14.2": - version "4.14.2" - resolved "https://registry.yarnpkg.com/@algolia/transporter/-/transporter-4.14.2.tgz#77c069047fb1a4359ee6a51f51829508e44a1e3d" - integrity sha512-t89dfQb2T9MFQHidjHcfhh6iGMNwvuKUvojAj+JsrHAGbuSy7yE4BylhLX6R0Q1xYRoC4Vvv+O5qIw/LdnQfsQ== - dependencies: - "@algolia/cache-common" "4.14.2" - "@algolia/logger-common" "4.14.2" - "@algolia/requester-common" "4.14.2" - -"@ampproject/remapping@^2.1.0": - version "2.2.0" - resolved "https://registry.yarnpkg.com/@ampproject/remapping/-/remapping-2.2.0.tgz#56c133824780de3174aed5ab6834f3026790154d" - integrity sha512-qRmjj8nj9qmLTQXXmaR1cck3UXSRMPrbsLJAasZpF+t3riI71BXed5ebIOYwQntykeZuhjsdweEc9BxH5Jc26w== +"@algolia/logger-common@4.24.0": + version "4.24.0" + resolved "https://registry.yarnpkg.com/@algolia/logger-common/-/logger-common-4.24.0.tgz#28d439976019ec0a46ba7a1a739ef493d4ef8123" + integrity sha512-LLUNjkahj9KtKYrQhFKCzMx0BY3RnNP4FEtO+sBybCjJ73E8jNdaKJ/Dd8A/VA4imVHP5tADZ8pn5B8Ga/wTMA== + +"@algolia/logger-console@4.24.0": + version "4.24.0" + resolved "https://registry.yarnpkg.com/@algolia/logger-console/-/logger-console-4.24.0.tgz#c6ff486036cd90b81d07a95aaba04461da7e1c65" + integrity sha512-X4C8IoHgHfiUROfoRCV+lzSy+LHMgkoEEU1BbKcsfnV0i0S20zyy0NLww9dwVHUWNfPPxdMU+/wKmLGYf96yTg== + dependencies: + "@algolia/logger-common" "4.24.0" + +"@algolia/recommend@4.24.0": + version "4.24.0" + resolved "https://registry.yarnpkg.com/@algolia/recommend/-/recommend-4.24.0.tgz#8a3f78aea471ee0a4836b78fd2aad4e9abcaaf34" + integrity sha512-P9kcgerfVBpfYHDfVZDvvdJv0lEoCvzNlOy2nykyt5bK8TyieYyiD0lguIJdRZZYGre03WIAFf14pgE+V+IBlw== + dependencies: + "@algolia/cache-browser-local-storage" "4.24.0" + "@algolia/cache-common" "4.24.0" + "@algolia/cache-in-memory" "4.24.0" + "@algolia/client-common" "4.24.0" + "@algolia/client-search" "4.24.0" + "@algolia/logger-common" "4.24.0" + "@algolia/logger-console" "4.24.0" + "@algolia/requester-browser-xhr" "4.24.0" + "@algolia/requester-common" "4.24.0" + "@algolia/requester-node-http" "4.24.0" + "@algolia/transporter" "4.24.0" + +"@algolia/requester-browser-xhr@4.24.0": + version "4.24.0" + resolved "https://registry.yarnpkg.com/@algolia/requester-browser-xhr/-/requester-browser-xhr-4.24.0.tgz#313c5edab4ed73a052e75803855833b62dd19c16" + integrity sha512-Z2NxZMb6+nVXSjF13YpjYTdvV3032YTBSGm2vnYvYPA6mMxzM3v5rsCiSspndn9rzIW4Qp1lPHBvuoKJV6jnAA== + dependencies: + "@algolia/requester-common" "4.24.0" + +"@algolia/requester-common@4.24.0": + version "4.24.0" + resolved "https://registry.yarnpkg.com/@algolia/requester-common/-/requester-common-4.24.0.tgz#1c60c198031f48fcdb9e34c4057a3ea987b9a436" + integrity sha512-k3CXJ2OVnvgE3HMwcojpvY6d9kgKMPRxs/kVohrwF5WMr2fnqojnycZkxPoEg+bXm8fi5BBfFmOqgYztRtHsQA== + +"@algolia/requester-node-http@4.24.0": + version "4.24.0" + resolved "https://registry.yarnpkg.com/@algolia/requester-node-http/-/requester-node-http-4.24.0.tgz#4461593714031d02aa7da221c49df675212f482f" + integrity sha512-JF18yTjNOVYvU/L3UosRcvbPMGT9B+/GQWNWnenIImglzNVGpyzChkXLnrSf6uxwVNO6ESGu6oN8MqcGQcjQJw== + dependencies: + "@algolia/requester-common" "4.24.0" + +"@algolia/transporter@4.24.0": + version "4.24.0" + resolved "https://registry.yarnpkg.com/@algolia/transporter/-/transporter-4.24.0.tgz#226bb1f8af62430374c1972b2e5c8580ab275102" + integrity sha512-86nI7w6NzWxd1Zp9q3413dRshDqAzSbsQjhcDhPIatEFiZrL1/TjnHL8S7jVKFePlIMzDsZWXAXwXzcok9c5oA== + dependencies: + "@algolia/cache-common" "4.24.0" + "@algolia/logger-common" "4.24.0" + "@algolia/requester-common" "4.24.0" + +"@ampproject/remapping@^2.2.0": + version "2.3.0" + resolved "https://registry.yarnpkg.com/@ampproject/remapping/-/remapping-2.3.0.tgz#ed441b6fa600072520ce18b43d2c8cc8caecc7f4" + integrity sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw== dependencies: - "@jridgewell/gen-mapping" "^0.1.0" - "@jridgewell/trace-mapping" "^0.3.9" + "@jridgewell/gen-mapping" "^0.3.5" + "@jridgewell/trace-mapping" "^0.3.24" -"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.10.4", "@babel/code-frame@^7.16.0", "@babel/code-frame@^7.18.6", "@babel/code-frame@^7.8.3": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.18.6.tgz#3b25d38c89600baa2dcc219edfa88a74eb2c427a" - integrity sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q== +"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.10.4", "@babel/code-frame@^7.16.0", "@babel/code-frame@^7.24.7", "@babel/code-frame@^7.8.3": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.24.7.tgz#882fd9e09e8ee324e496bd040401c6f046ef4465" + integrity sha512-BcYH1CVJBO9tvyIZ2jVeXgSIMvGZ2FDRvDdOIVQyuklNKSsx+eppDEBq/g47Ayw+RqNFE+URvOShmf+f/qwAlA== dependencies: - "@babel/highlight" "^7.18.6" + "@babel/highlight" "^7.24.7" + picocolors "^1.0.0" -"@babel/compat-data@^7.17.7", "@babel/compat-data@^7.20.0", "@babel/compat-data@^7.20.1": - version "7.20.1" - resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.20.1.tgz#f2e6ef7790d8c8dbf03d379502dcc246dcce0b30" - integrity sha512-EWZ4mE2diW3QALKvDMiXnbZpRvlj+nayZ112nK93SnhqOtpdsbVD4W+2tEoT3YNBAG9RBR0ISY758ZkOgsn6pQ== +"@babel/compat-data@^7.22.6", "@babel/compat-data@^7.24.8": + version "7.24.9" + resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.24.9.tgz#53eee4e68f1c1d0282aa0eb05ddb02d033fc43a0" + integrity sha512-e701mcfApCJqMMueQI0Fb68Amflj83+dvAvHawoBpAz+GDjCIyGHzNwnefjsWJ3xiYAqqiQFoWbspGYBdb2/ng== "@babel/core@7.12.9": version "7.12.9" @@ -173,112 +199,111 @@ source-map "^0.5.0" "@babel/core@^7.18.6", "@babel/core@^7.19.6": - version "7.20.2" - resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.20.2.tgz#8dc9b1620a673f92d3624bd926dc49a52cf25b92" - integrity sha512-w7DbG8DtMrJcFOi4VrLm+8QM4az8Mo+PuLBKLp2zrYRCow8W/f9xiXm5sN53C8HksCyDQwCKha9JiDoIyPjT2g== - dependencies: - "@ampproject/remapping" "^2.1.0" - "@babel/code-frame" "^7.18.6" - "@babel/generator" "^7.20.2" - "@babel/helper-compilation-targets" "^7.20.0" - "@babel/helper-module-transforms" "^7.20.2" - "@babel/helpers" "^7.20.1" - "@babel/parser" "^7.20.2" - "@babel/template" "^7.18.10" - "@babel/traverse" "^7.20.1" - "@babel/types" "^7.20.2" - convert-source-map "^1.7.0" + version "7.24.9" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.24.9.tgz#dc07c9d307162c97fa9484ea997ade65841c7c82" + integrity sha512-5e3FI4Q3M3Pbr21+5xJwCv6ZT6KmGkI0vw3Tozy5ODAQFTIWe37iT8Cr7Ice2Ntb+M3iSKCEWMB1MBgKrW3whg== + dependencies: + "@ampproject/remapping" "^2.2.0" + "@babel/code-frame" "^7.24.7" + "@babel/generator" "^7.24.9" + "@babel/helper-compilation-targets" "^7.24.8" + "@babel/helper-module-transforms" "^7.24.9" + "@babel/helpers" "^7.24.8" + "@babel/parser" "^7.24.8" + "@babel/template" "^7.24.7" + "@babel/traverse" "^7.24.8" + "@babel/types" "^7.24.9" + convert-source-map "^2.0.0" debug "^4.1.0" gensync "^1.0.0-beta.2" - json5 "^2.2.1" - semver "^6.3.0" + json5 "^2.2.3" + semver "^6.3.1" -"@babel/generator@^7.12.5", "@babel/generator@^7.18.7", "@babel/generator@^7.20.1", "@babel/generator@^7.20.2": - version "7.20.4" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.20.4.tgz#4d9f8f0c30be75fd90a0562099a26e5839602ab8" - integrity sha512-luCf7yk/cm7yab6CAW1aiFnmEfBJplb/JojV56MYEK7ziWfGmFlTfmL9Ehwfy4gFhbjBfWO1wj7/TuSbVNEEtA== +"@babel/generator@^7.12.5", "@babel/generator@^7.18.7", "@babel/generator@^7.24.8", "@babel/generator@^7.24.9": + version "7.24.10" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.24.10.tgz#a4ab681ec2a78bbb9ba22a3941195e28a81d8e76" + integrity sha512-o9HBZL1G2129luEUlG1hB4N/nlYNWHnpwlND9eOMclRqqu1YDy2sSYVCFUZwl8I1Gxh+QSRrP2vD7EpUmFVXxg== dependencies: - "@babel/types" "^7.20.2" - "@jridgewell/gen-mapping" "^0.3.2" + "@babel/types" "^7.24.9" + "@jridgewell/gen-mapping" "^0.3.5" + "@jridgewell/trace-mapping" "^0.3.25" jsesc "^2.5.1" -"@babel/helper-annotate-as-pure@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.18.6.tgz#eaa49f6f80d5a33f9a5dd2276e6d6e451be0a6bb" - integrity sha512-duORpUiYrEpzKIop6iNbjnwKLAKnJ47csTyRACyEmWj0QdUrm5aqNJGHSSEQSUAvNW0ojX0dOmK9dZduvkfeXA== - dependencies: - "@babel/types" "^7.18.6" - -"@babel/helper-builder-binary-assignment-operator-visitor@^7.18.6": - version "7.18.9" - resolved "https://registry.yarnpkg.com/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.18.9.tgz#acd4edfd7a566d1d51ea975dff38fd52906981bb" - integrity sha512-yFQ0YCHoIqarl8BCRwBL8ulYUaZpz3bNsA7oFepAzee+8/+ImtADXNOmO5vJvsPff3qi+hvpkY/NYBTrBQgdNw== - dependencies: - "@babel/helper-explode-assignable-expression" "^7.18.6" - "@babel/types" "^7.18.9" - -"@babel/helper-compilation-targets@^7.17.7", "@babel/helper-compilation-targets@^7.18.9", "@babel/helper-compilation-targets@^7.20.0": - version "7.20.0" - resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.20.0.tgz#6bf5374d424e1b3922822f1d9bdaa43b1a139d0a" - integrity sha512-0jp//vDGp9e8hZzBc6N/KwA5ZK3Wsm/pfm4CrY7vzegkVxc65SgSn6wYOnwHe9Js9HRQ1YTCKLGPzDtaS3RoLQ== +"@babel/helper-annotate-as-pure@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.24.7.tgz#5373c7bc8366b12a033b4be1ac13a206c6656aab" + integrity sha512-BaDeOonYvhdKw+JoMVkAixAAJzG2jVPIwWoKBPdYuY9b452e2rPuI9QPYh3KpofZ3pW2akOmwZLOiOsHMiqRAg== + dependencies: + "@babel/types" "^7.24.7" + +"@babel/helper-builder-binary-assignment-operator-visitor@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.24.7.tgz#37d66feb012024f2422b762b9b2a7cfe27c7fba3" + integrity sha512-xZeCVVdwb4MsDBkkyZ64tReWYrLRHlMN72vP7Bdm3OUOuyFZExhsHUUnuWnm2/XOlAJzR0LfPpB56WXZn0X/lA== + dependencies: + "@babel/traverse" "^7.24.7" + "@babel/types" "^7.24.7" + +"@babel/helper-compilation-targets@^7.22.6", "@babel/helper-compilation-targets@^7.24.7", "@babel/helper-compilation-targets@^7.24.8": + version "7.24.8" + resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.24.8.tgz#b607c3161cd9d1744977d4f97139572fe778c271" + integrity sha512-oU+UoqCHdp+nWVDkpldqIQL/i/bvAv53tRqLG/s+cOXxe66zOYLU7ar/Xs3LdmBihrUMEUhwu6dMZwbNOYDwvw== + dependencies: + "@babel/compat-data" "^7.24.8" + "@babel/helper-validator-option" "^7.24.8" + browserslist "^4.23.1" + lru-cache "^5.1.1" + semver "^6.3.1" + +"@babel/helper-create-class-features-plugin@^7.24.7", "@babel/helper-create-class-features-plugin@^7.24.8": + version "7.24.8" + resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.24.8.tgz#47f546408d13c200c0867f9d935184eaa0851b09" + integrity sha512-4f6Oqnmyp2PP3olgUMmOwC3akxSm5aBYraQ6YDdKy7NcAMkDECHWG0DEnV6M2UAkERgIBhYt8S27rURPg7SxWA== + dependencies: + "@babel/helper-annotate-as-pure" "^7.24.7" + "@babel/helper-environment-visitor" "^7.24.7" + "@babel/helper-function-name" "^7.24.7" + "@babel/helper-member-expression-to-functions" "^7.24.8" + "@babel/helper-optimise-call-expression" "^7.24.7" + "@babel/helper-replace-supers" "^7.24.7" + "@babel/helper-skip-transparent-expression-wrappers" "^7.24.7" + "@babel/helper-split-export-declaration" "^7.24.7" + semver "^6.3.1" + +"@babel/helper-create-regexp-features-plugin@^7.18.6", "@babel/helper-create-regexp-features-plugin@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.24.7.tgz#be4f435a80dc2b053c76eeb4b7d16dd22cfc89da" + integrity sha512-03TCmXy2FtXJEZfbXDTSqq1fRJArk7lX9DOFC/47VthYcxyIOx+eXQmdo6DOQvrbpIix+KfXwvuXdFDZHxt+rA== + dependencies: + "@babel/helper-annotate-as-pure" "^7.24.7" + regexpu-core "^5.3.1" + semver "^6.3.1" + +"@babel/helper-define-polyfill-provider@^0.6.1", "@babel/helper-define-polyfill-provider@^0.6.2": + version "0.6.2" + resolved "https://registry.yarnpkg.com/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.6.2.tgz#18594f789c3594acb24cfdb4a7f7b7d2e8bd912d" + integrity sha512-LV76g+C502biUK6AyZ3LK10vDpDyCzZnhZFXkH1L75zHPj68+qc8Zfpx2th+gzwA2MzyK+1g/3EPl62yFnVttQ== dependencies: - "@babel/compat-data" "^7.20.0" - "@babel/helper-validator-option" "^7.18.6" - browserslist "^4.21.3" - semver "^6.3.0" - -"@babel/helper-create-class-features-plugin@^7.18.6", "@babel/helper-create-class-features-plugin@^7.20.2": - version "7.20.2" - resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.20.2.tgz#3c08a5b5417c7f07b5cf3dfb6dc79cbec682e8c2" - integrity sha512-k22GoYRAHPYr9I+Gvy2ZQlAe5mGy8BqWst2wRt8cwIufWTxrsVshhIBvYNqC80N0GSFWTsqRVexOtfzlgOEDvA== - dependencies: - "@babel/helper-annotate-as-pure" "^7.18.6" - "@babel/helper-environment-visitor" "^7.18.9" - "@babel/helper-function-name" "^7.19.0" - "@babel/helper-member-expression-to-functions" "^7.18.9" - "@babel/helper-optimise-call-expression" "^7.18.6" - "@babel/helper-replace-supers" "^7.19.1" - "@babel/helper-split-export-declaration" "^7.18.6" - -"@babel/helper-create-regexp-features-plugin@^7.18.6", "@babel/helper-create-regexp-features-plugin@^7.19.0": - version "7.19.0" - resolved "https://registry.yarnpkg.com/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.19.0.tgz#7976aca61c0984202baca73d84e2337a5424a41b" - integrity sha512-htnV+mHX32DF81amCDrwIDr8nrp1PTm+3wfBN9/v8QJOLEioOCOG7qNyq0nHeFiWbT3Eb7gsPwEmV64UCQ1jzw== - dependencies: - "@babel/helper-annotate-as-pure" "^7.18.6" - regexpu-core "^5.1.0" - -"@babel/helper-define-polyfill-provider@^0.3.3": - version "0.3.3" - resolved "https://registry.yarnpkg.com/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.3.3.tgz#8612e55be5d51f0cd1f36b4a5a83924e89884b7a" - integrity sha512-z5aQKU4IzbqCC1XH0nAqfsFLMVSo22SBKUc0BxGrLkolTdPTructy0ToNnlO2zA4j9Q/7pjMZf0DSY+DSTYzww== - dependencies: - "@babel/helper-compilation-targets" "^7.17.7" - "@babel/helper-plugin-utils" "^7.16.7" + "@babel/helper-compilation-targets" "^7.22.6" + "@babel/helper-plugin-utils" "^7.22.5" debug "^4.1.1" lodash.debounce "^4.0.8" resolve "^1.14.2" - semver "^6.1.2" -"@babel/helper-environment-visitor@^7.18.9": - version "7.18.9" - resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.9.tgz#0c0cee9b35d2ca190478756865bb3528422f51be" - integrity sha512-3r/aACDJ3fhQ/EVgFy0hpj8oHyHpQc+LPtJoY9SzTThAsStm4Ptegq92vqKoE3vD706ZVFWITnMnxucw+S9Ipg== - -"@babel/helper-explode-assignable-expression@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.18.6.tgz#41f8228ef0a6f1a036b8dfdfec7ce94f9a6bc096" - integrity sha512-eyAYAsQmB80jNfg4baAtLeWAQHfHFiR483rzFK+BhETlGZaQC9bsfrugfXDCbRHLQbIA7U5NxhhOxN7p/dWIcg== +"@babel/helper-environment-visitor@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.24.7.tgz#4b31ba9551d1f90781ba83491dd59cf9b269f7d9" + integrity sha512-DoiN84+4Gnd0ncbBOM9AZENV4a5ZiL39HYMyZJGZ/AZEykHYdJw0wW3kdcsh9/Kn+BRXHLkkklZ51ecPKmI1CQ== dependencies: - "@babel/types" "^7.18.6" + "@babel/types" "^7.24.7" -"@babel/helper-function-name@^7.18.9", "@babel/helper-function-name@^7.19.0": - version "7.19.0" - resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.19.0.tgz#941574ed5390682e872e52d3f38ce9d1bef4648c" - integrity sha512-WAwHBINyrpqywkUH0nTnNgI5ina5TFn85HKS0pbPDfxFfhyR/aNQEn4hGi1P1JyT//I0t4OgXUlofzWILRvS5w== +"@babel/helper-function-name@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.24.7.tgz#75f1e1725742f39ac6584ee0b16d94513da38dd2" + integrity sha512-FyoJTsj/PEUWu1/TYRiXTIHc8lbw+TDYkZuoE43opPS5TrI7MyONBE1oNvfguEXAD9yhQRrVBnXdXzSLQl9XnA== dependencies: - "@babel/template" "^7.18.10" - "@babel/types" "^7.19.0" + "@babel/template" "^7.24.7" + "@babel/types" "^7.24.7" "@babel/helper-get-function-arity@^7.16.7": version "7.16.7" @@ -287,238 +312,177 @@ dependencies: "@babel/types" "^7.16.7" -"@babel/helper-hoist-variables@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.18.6.tgz#d4d2c8fb4baeaa5c68b99cc8245c56554f926678" - integrity sha512-UlJQPkFqFULIcyW5sbzgbkxn2FKRgwWiRexcuaR8RNJRy8+LLveqPjwZV/bwrLZCN0eUHD/x8D0heK1ozuoo6Q== +"@babel/helper-hoist-variables@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.24.7.tgz#b4ede1cde2fd89436397f30dc9376ee06b0f25ee" + integrity sha512-MJJwhkoGy5c4ehfoRyrJ/owKeMl19U54h27YYftT0o2teQ3FJ3nQUf/I3LlJsX4l3qlw7WRXUmiyajvHXoTubQ== dependencies: - "@babel/types" "^7.18.6" + "@babel/types" "^7.24.7" -"@babel/helper-member-expression-to-functions@^7.18.9": - version "7.18.9" - resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.18.9.tgz#1531661e8375af843ad37ac692c132841e2fd815" - integrity sha512-RxifAh2ZoVU67PyKIO4AMi1wTenGfMR/O/ae0CCRqwgBAt5v7xjdtRw7UoSbsreKrQn5t7r89eruK/9JjYHuDg== +"@babel/helper-member-expression-to-functions@^7.24.7", "@babel/helper-member-expression-to-functions@^7.24.8": + version "7.24.8" + resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.24.8.tgz#6155e079c913357d24a4c20480db7c712a5c3fb6" + integrity sha512-LABppdt+Lp/RlBxqrh4qgf1oEH/WxdzQNDJIu5gC/W1GyvPVrOBiItmmM8wan2fm4oYqFuFfkXmlGpLQhPY8CA== dependencies: - "@babel/types" "^7.18.9" + "@babel/traverse" "^7.24.8" + "@babel/types" "^7.24.8" -"@babel/helper-module-imports@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.18.6.tgz#1e3ebdbbd08aad1437b428c50204db13c5a3ca6e" - integrity sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA== - dependencies: - "@babel/types" "^7.18.6" - -"@babel/helper-module-transforms@^7.12.1", "@babel/helper-module-transforms@^7.18.6", "@babel/helper-module-transforms@^7.19.6", "@babel/helper-module-transforms@^7.20.2": - version "7.20.2" - resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.20.2.tgz#ac53da669501edd37e658602a21ba14c08748712" - integrity sha512-zvBKyJXRbmK07XhMuujYoJ48B5yvvmM6+wcpv6Ivj4Yg6qO7NOZOSnvZN9CRl1zz1Z4cKf8YejmCMh8clOoOeA== - dependencies: - "@babel/helper-environment-visitor" "^7.18.9" - "@babel/helper-module-imports" "^7.18.6" - "@babel/helper-simple-access" "^7.20.2" - "@babel/helper-split-export-declaration" "^7.18.6" - "@babel/helper-validator-identifier" "^7.19.1" - "@babel/template" "^7.18.10" - "@babel/traverse" "^7.20.1" - "@babel/types" "^7.20.2" - -"@babel/helper-optimise-call-expression@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.18.6.tgz#9369aa943ee7da47edab2cb4e838acf09d290ffe" - integrity sha512-HP59oD9/fEHQkdcbgFCnbmgH5vIQTJbxh2yf+CdM89/glUNnuzr87Q8GIjGEnOktTROemO0Pe0iPAYbqZuOUiA== +"@babel/helper-module-imports@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.24.7.tgz#f2f980392de5b84c3328fc71d38bd81bbb83042b" + integrity sha512-8AyH3C+74cgCVVXow/myrynrAGv+nTVg5vKu2nZph9x7RcRwzmh0VFallJuFTZ9mx6u4eSdXZfcOzSqTUm0HCA== dependencies: - "@babel/types" "^7.18.6" + "@babel/traverse" "^7.24.7" + "@babel/types" "^7.24.7" -"@babel/helper-plugin-utils@7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.10.4.tgz#2f75a831269d4f677de49986dff59927533cf375" - integrity sha512-O4KCvQA6lLiMU9l2eawBPMf1xPP8xPfB3iEQw150hOVTqj/rfXz0ThTb4HEzqQfs2Bmo5Ay8BzxfzVtBrr9dVg== - -"@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.10.4", "@babel/helper-plugin-utils@^7.12.13", "@babel/helper-plugin-utils@^7.14.5", "@babel/helper-plugin-utils@^7.16.7", "@babel/helper-plugin-utils@^7.18.6", "@babel/helper-plugin-utils@^7.18.9", "@babel/helper-plugin-utils@^7.19.0", "@babel/helper-plugin-utils@^7.20.2", "@babel/helper-plugin-utils@^7.8.0", "@babel/helper-plugin-utils@^7.8.3": - version "7.20.2" - resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.20.2.tgz#d1b9000752b18d0877cff85a5c376ce5c3121629" - integrity sha512-8RvlJG2mj4huQ4pZ+rU9lqKi9ZKiRmuvGuM2HlWmkmgOhbs6zEAw6IEiJ5cQqGbDzGZOhwuOQNtZMi/ENLjZoQ== - -"@babel/helper-remap-async-to-generator@^7.18.6", "@babel/helper-remap-async-to-generator@^7.18.9": - version "7.18.9" - resolved "https://registry.yarnpkg.com/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.18.9.tgz#997458a0e3357080e54e1d79ec347f8a8cd28519" - integrity sha512-dI7q50YKd8BAv3VEfgg7PS7yD3Rtbi2J1XMXaalXO0W0164hYLnh8zpjRS0mte9MfVp/tltvr/cfdXPvJr1opA== - dependencies: - "@babel/helper-annotate-as-pure" "^7.18.6" - "@babel/helper-environment-visitor" "^7.18.9" - "@babel/helper-wrap-function" "^7.18.9" - "@babel/types" "^7.18.9" - -"@babel/helper-replace-supers@^7.18.6", "@babel/helper-replace-supers@^7.19.1": - version "7.19.1" - resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.19.1.tgz#e1592a9b4b368aa6bdb8784a711e0bcbf0612b78" - integrity sha512-T7ahH7wV0Hfs46SFh5Jz3s0B6+o8g3c+7TMxu7xKfmHikg7EAZ3I2Qk9LFhjxXq8sL7UkP5JflezNwoZa8WvWw== - dependencies: - "@babel/helper-environment-visitor" "^7.18.9" - "@babel/helper-member-expression-to-functions" "^7.18.9" - "@babel/helper-optimise-call-expression" "^7.18.6" - "@babel/traverse" "^7.19.1" - "@babel/types" "^7.19.0" - -"@babel/helper-simple-access@^7.19.4", "@babel/helper-simple-access@^7.20.2": - version "7.20.2" - resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.20.2.tgz#0ab452687fe0c2cfb1e2b9e0015de07fc2d62dd9" - integrity sha512-+0woI/WPq59IrqDYbVGfshjT5Dmk/nnbdpcF8SnMhhXObpTq2KNBdLFRFrkVdbDOyUmHBCxzm5FHV1rACIkIbA== +"@babel/helper-module-transforms@^7.12.1", "@babel/helper-module-transforms@^7.24.7", "@babel/helper-module-transforms@^7.24.8", "@babel/helper-module-transforms@^7.24.9": + version "7.24.9" + resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.24.9.tgz#e13d26306b89eea569180868e652e7f514de9d29" + integrity sha512-oYbh+rtFKj/HwBQkFlUzvcybzklmVdVV3UU+mN7n2t/q3yGHbuVdNxyFvSBO1tfvjyArpHNcWMAzsSPdyI46hw== dependencies: - "@babel/types" "^7.20.2" + "@babel/helper-environment-visitor" "^7.24.7" + "@babel/helper-module-imports" "^7.24.7" + "@babel/helper-simple-access" "^7.24.7" + "@babel/helper-split-export-declaration" "^7.24.7" + "@babel/helper-validator-identifier" "^7.24.7" -"@babel/helper-skip-transparent-expression-wrappers@^7.18.9": - version "7.20.0" - resolved "https://registry.yarnpkg.com/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.20.0.tgz#fbe4c52f60518cab8140d77101f0e63a8a230684" - integrity sha512-5y1JYeNKfvnT8sZcK9DVRtpTbGiomYIHviSP3OQWmDPU3DeH4a1ZlT/N2lyQ5P8egjcRaT/Y9aNqUxK0WsnIIg== - dependencies: - "@babel/types" "^7.20.0" - -"@babel/helper-split-export-declaration@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.18.6.tgz#7367949bc75b20c6d5a5d4a97bba2824ae8ef075" - integrity sha512-bde1etTx6ZyTmobl9LLMMQsaizFVZrquTEHOqKeQESMKo4PlObf+8+JA25ZsIpZhT/WEd39+vOdLXAFG/nELpA== +"@babel/helper-optimise-call-expression@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.24.7.tgz#8b0a0456c92f6b323d27cfd00d1d664e76692a0f" + integrity sha512-jKiTsW2xmWwxT1ixIdfXUZp+P5yURx2suzLZr5Hi64rURpDYdMW0pv+Uf17EYk2Rd428Lx4tLsnjGJzYKDM/6A== dependencies: - "@babel/types" "^7.18.6" + "@babel/types" "^7.24.7" -"@babel/helper-string-parser@^7.19.4": - version "7.19.4" - resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.19.4.tgz#38d3acb654b4701a9b77fb0615a96f775c3a9e63" - integrity sha512-nHtDoQcuqFmwYNYPz3Rah5ph2p8PFeFCsZk9A/48dPc/rGocJ5J3hAAZ7pb76VWX3fZKu+uEr/FhH5jLx7umrw== - -"@babel/helper-validator-identifier@^7.18.6", "@babel/helper-validator-identifier@^7.19.1": - version "7.19.1" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.19.1.tgz#7eea834cf32901ffdc1a7ee555e2f9c27e249ca2" - integrity sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w== - -"@babel/helper-validator-option@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.18.6.tgz#bf0d2b5a509b1f336099e4ff36e1a63aa5db4db8" - integrity sha512-XO7gESt5ouv/LRJdrVjkShckw6STTaB7l9BrpBaAHDeF5YZT+01PCwmR0SJHnkW6i8OwW/EVWRShfi4j2x+KQw== - -"@babel/helper-wrap-function@^7.18.9": - version "7.19.0" - resolved "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.19.0.tgz#89f18335cff1152373222f76a4b37799636ae8b1" - integrity sha512-txX8aN8CZyYGTwcLhlk87KRqncAzhh5TpQamZUa0/u3an36NtDpUP6bQgBCBcLeBs09R/OwQu3OjK0k/HwfNDg== - dependencies: - "@babel/helper-function-name" "^7.19.0" - "@babel/template" "^7.18.10" - "@babel/traverse" "^7.19.0" - "@babel/types" "^7.19.0" - -"@babel/helpers@^7.12.5", "@babel/helpers@^7.20.1": - version "7.20.1" - resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.20.1.tgz#2ab7a0fcb0a03b5bf76629196ed63c2d7311f4c9" - integrity sha512-J77mUVaDTUJFZ5BpP6mMn6OIl3rEWymk2ZxDBQJUG3P+PbmyMcF3bYWvz0ma69Af1oobDqT/iAsvzhB58xhQUg== - dependencies: - "@babel/template" "^7.18.10" - "@babel/traverse" "^7.20.1" - "@babel/types" "^7.20.0" +"@babel/helper-plugin-utils@7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.10.4.tgz#2f75a831269d4f677de49986dff59927533cf375" + integrity sha512-O4KCvQA6lLiMU9l2eawBPMf1xPP8xPfB3iEQw150hOVTqj/rfXz0ThTb4HEzqQfs2Bmo5Ay8BzxfzVtBrr9dVg== -"@babel/highlight@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.18.6.tgz#81158601e93e2563795adcbfbdf5d64be3f2ecdf" - integrity sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g== - dependencies: - "@babel/helper-validator-identifier" "^7.18.6" - chalk "^2.0.0" +"@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.10.4", "@babel/helper-plugin-utils@^7.12.13", "@babel/helper-plugin-utils@^7.14.5", "@babel/helper-plugin-utils@^7.18.6", "@babel/helper-plugin-utils@^7.22.5", "@babel/helper-plugin-utils@^7.24.7", "@babel/helper-plugin-utils@^7.24.8", "@babel/helper-plugin-utils@^7.8.0", "@babel/helper-plugin-utils@^7.8.3": + version "7.24.8" + resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.24.8.tgz#94ee67e8ec0e5d44ea7baeb51e571bd26af07878" + integrity sha512-FFWx5142D8h2Mgr/iPVGH5G7w6jDn4jUSpZTyDnQO0Yn7Ks2Kuz6Pci8H6MPCoUJegd/UZQ3tAvfLCxQSnWWwg== + +"@babel/helper-remap-async-to-generator@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.24.7.tgz#b3f0f203628522713849d49403f1a414468be4c7" + integrity sha512-9pKLcTlZ92hNZMQfGCHImUpDOlAgkkpqalWEeftW5FBya75k8Li2ilerxkM/uBEj01iBZXcCIB/bwvDYgWyibA== + dependencies: + "@babel/helper-annotate-as-pure" "^7.24.7" + "@babel/helper-environment-visitor" "^7.24.7" + "@babel/helper-wrap-function" "^7.24.7" + +"@babel/helper-replace-supers@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.24.7.tgz#f933b7eed81a1c0265740edc91491ce51250f765" + integrity sha512-qTAxxBM81VEyoAY0TtLrx1oAEJc09ZK67Q9ljQToqCnA+55eNwCORaxlKyu+rNfX86o8OXRUSNUnrtsAZXM9sg== + dependencies: + "@babel/helper-environment-visitor" "^7.24.7" + "@babel/helper-member-expression-to-functions" "^7.24.7" + "@babel/helper-optimise-call-expression" "^7.24.7" + +"@babel/helper-simple-access@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.24.7.tgz#bcade8da3aec8ed16b9c4953b74e506b51b5edb3" + integrity sha512-zBAIvbCMh5Ts+b86r/CjU+4XGYIs+R1j951gxI3KmmxBMhCg4oQMsv6ZXQ64XOm/cvzfU1FmoCyt6+owc5QMYg== + dependencies: + "@babel/traverse" "^7.24.7" + "@babel/types" "^7.24.7" + +"@babel/helper-skip-transparent-expression-wrappers@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.24.7.tgz#5f8fa83b69ed5c27adc56044f8be2b3ea96669d9" + integrity sha512-IO+DLT3LQUElMbpzlatRASEyQtfhSE0+m465v++3jyyXeBTBUjtVZg28/gHeV5mrTJqvEKhKroBGAvhW+qPHiQ== + dependencies: + "@babel/traverse" "^7.24.7" + "@babel/types" "^7.24.7" + +"@babel/helper-split-export-declaration@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.24.7.tgz#83949436890e07fa3d6873c61a96e3bbf692d856" + integrity sha512-oy5V7pD+UvfkEATUKvIjvIAH/xCzfsFVw7ygW2SI6NClZzquT+mwdTfgfdbUiceh6iQO0CHtCPsyze/MZ2YbAA== + dependencies: + "@babel/types" "^7.24.7" + +"@babel/helper-string-parser@^7.24.8": + version "7.24.8" + resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.24.8.tgz#5b3329c9a58803d5df425e5785865881a81ca48d" + integrity sha512-pO9KhhRcuUyGnJWwyEgnRJTSIZHiT+vMD0kPeD+so0l7mxkMT19g3pjY9GTnHySck/hDzq+dtW/4VgnMkippsQ== + +"@babel/helper-validator-identifier@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.7.tgz#75b889cfaf9e35c2aaf42cf0d72c8e91719251db" + integrity sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w== + +"@babel/helper-validator-option@^7.24.7", "@babel/helper-validator-option@^7.24.8": + version "7.24.8" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.24.8.tgz#3725cdeea8b480e86d34df15304806a06975e33d" + integrity sha512-xb8t9tD1MHLungh/AIoWYN+gVHaB9kwlu8gffXGSt3FFEIT7RjS+xWbc2vUD1UTZdIpKj/ab3rdqJ7ufngyi2Q== + +"@babel/helper-wrap-function@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.24.7.tgz#52d893af7e42edca7c6d2c6764549826336aae1f" + integrity sha512-N9JIYk3TD+1vq/wn77YnJOqMtfWhNewNE+DJV4puD2X7Ew9J4JvrzrFDfTfyv5EgEXVy9/Wt8QiOErzEmv5Ifw== + dependencies: + "@babel/helper-function-name" "^7.24.7" + "@babel/template" "^7.24.7" + "@babel/traverse" "^7.24.7" + "@babel/types" "^7.24.7" + +"@babel/helpers@^7.12.5", "@babel/helpers@^7.24.8": + version "7.24.8" + resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.24.8.tgz#2820d64d5d6686cca8789dd15b074cd862795873" + integrity sha512-gV2265Nkcz7weJJfvDoAEVzC1e2OTDpkGbEsebse8koXUJUXPsCMi7sRo/+SPMuMZ9MtUPnGwITTnQnU5YjyaQ== + dependencies: + "@babel/template" "^7.24.7" + "@babel/types" "^7.24.8" + +"@babel/highlight@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.24.7.tgz#a05ab1df134b286558aae0ed41e6c5f731bf409d" + integrity sha512-EStJpq4OuY8xYfhGVXngigBJRWxftKX9ksiGDnmlY3o7B/V7KIAc9X4oiK87uPJSc/vs5L869bem5fhZa8caZw== + dependencies: + "@babel/helper-validator-identifier" "^7.24.7" + chalk "^2.4.2" js-tokens "^4.0.0" + picocolors "^1.0.0" -"@babel/parser@^7.12.7", "@babel/parser@^7.18.10", "@babel/parser@^7.18.8", "@babel/parser@^7.20.1", "@babel/parser@^7.20.2": - version "7.20.3" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.20.3.tgz#5358cf62e380cf69efcb87a7bb922ff88bfac6e2" - integrity sha512-OP/s5a94frIPXwjzEcv5S/tpQfc6XhxYUnmWpgdqMWGgYCuErA3SzozaRAMQgSZWKeTJxht9aWAkUY+0UzvOFg== - -"@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.18.6.tgz#da5b8f9a580acdfbe53494dba45ea389fb09a4d2" - integrity sha512-Dgxsyg54Fx1d4Nge8UnvTrED63vrwOdPmyvPzlNN/boaliRP54pm3pGzZD1SJUwrBA+Cs/xdG8kXX6Mn/RfISQ== - dependencies: - "@babel/helper-plugin-utils" "^7.18.6" - -"@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@^7.18.9": - version "7.18.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.18.9.tgz#a11af19aa373d68d561f08e0a57242350ed0ec50" - integrity sha512-AHrP9jadvH7qlOj6PINbgSuphjQUAK7AOT7DPjBo9EHoLhQTnnK5u45e1Hd4DbSQEO9nqPWtQ89r+XEOWFScKg== - dependencies: - "@babel/helper-plugin-utils" "^7.18.9" - "@babel/helper-skip-transparent-expression-wrappers" "^7.18.9" - "@babel/plugin-proposal-optional-chaining" "^7.18.9" - -"@babel/plugin-proposal-async-generator-functions@^7.20.1": - version "7.20.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.20.1.tgz#352f02baa5d69f4e7529bdac39aaa02d41146af9" - integrity sha512-Gh5rchzSwE4kC+o/6T8waD0WHEQIsDmjltY8WnWRXHUdH8axZhuH86Ov9M72YhJfDrZseQwuuWaaIT/TmePp3g== - dependencies: - "@babel/helper-environment-visitor" "^7.18.9" - "@babel/helper-plugin-utils" "^7.19.0" - "@babel/helper-remap-async-to-generator" "^7.18.9" - "@babel/plugin-syntax-async-generators" "^7.8.4" - -"@babel/plugin-proposal-class-properties@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.18.6.tgz#b110f59741895f7ec21a6fff696ec46265c446a3" - integrity sha512-cumfXOF0+nzZrrN8Rf0t7M+tF6sZc7vhQwYQck9q1/5w2OExlD+b4v4RpMJFaV1Z7WcDRgO6FqvxqxGlwo+RHQ== - dependencies: - "@babel/helper-create-class-features-plugin" "^7.18.6" - "@babel/helper-plugin-utils" "^7.18.6" - -"@babel/plugin-proposal-class-static-block@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-class-static-block/-/plugin-proposal-class-static-block-7.18.6.tgz#8aa81d403ab72d3962fc06c26e222dacfc9b9020" - integrity sha512-+I3oIiNxrCpup3Gi8n5IGMwj0gOCAjcJUSQEcotNnCCPMEnixawOQ+KeJPlgfjzx+FKQ1QSyZOWe7wmoJp7vhw== - dependencies: - "@babel/helper-create-class-features-plugin" "^7.18.6" - "@babel/helper-plugin-utils" "^7.18.6" - "@babel/plugin-syntax-class-static-block" "^7.14.5" - -"@babel/plugin-proposal-dynamic-import@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.18.6.tgz#72bcf8d408799f547d759298c3c27c7e7faa4d94" - integrity sha512-1auuwmK+Rz13SJj36R+jqFPMJWyKEDd7lLSdOj4oJK0UTgGueSAtkrCvz9ewmgyU/P941Rv2fQwZJN8s6QruXw== - dependencies: - "@babel/helper-plugin-utils" "^7.18.6" - "@babel/plugin-syntax-dynamic-import" "^7.8.3" - -"@babel/plugin-proposal-export-namespace-from@^7.18.9": - version "7.18.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.18.9.tgz#5f7313ab348cdb19d590145f9247540e94761203" - integrity sha512-k1NtHyOMvlDDFeb9G5PhUXuGj8m/wiwojgQVEhJ/fsVsMCpLyOP4h0uGEjYJKrRI+EVPlb5Jk+Gt9P97lOGwtA== - dependencies: - "@babel/helper-plugin-utils" "^7.18.9" - "@babel/plugin-syntax-export-namespace-from" "^7.8.3" +"@babel/parser@^7.12.7", "@babel/parser@^7.18.8", "@babel/parser@^7.24.7", "@babel/parser@^7.24.8": + version "7.24.8" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.24.8.tgz#58a4dbbcad7eb1d48930524a3fd93d93e9084c6f" + integrity sha512-WzfbgXOkGzZiXXCqk43kKwZjzwx4oulxZi3nq2TYL9mOjQv6kYwul9mz6ID36njuL7Xkp6nJEfok848Zj10j/w== -"@babel/plugin-proposal-json-strings@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.18.6.tgz#7e8788c1811c393aff762817e7dbf1ebd0c05f0b" - integrity sha512-lr1peyn9kOdbYc0xr0OdHTZ5FMqS6Di+H0Fz2I/JwMzGmzJETNeOFq2pBySw6X/KFL5EWDjlJuMsUGRFb8fQgQ== +"@babel/plugin-bugfix-firefox-class-in-computed-class-key@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-firefox-class-in-computed-class-key/-/plugin-bugfix-firefox-class-in-computed-class-key-7.24.7.tgz#fd059fd27b184ea2b4c7e646868a9a381bbc3055" + integrity sha512-TiT1ss81W80eQsN+722OaeQMY/G4yTb4G9JrqeiDADs3N8lbPMGldWi9x8tyqCW5NLx1Jh2AvkE6r6QvEltMMQ== dependencies: - "@babel/helper-plugin-utils" "^7.18.6" - "@babel/plugin-syntax-json-strings" "^7.8.3" + "@babel/helper-environment-visitor" "^7.24.7" + "@babel/helper-plugin-utils" "^7.24.7" -"@babel/plugin-proposal-logical-assignment-operators@^7.18.9": - version "7.18.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.18.9.tgz#8148cbb350483bf6220af06fa6db3690e14b2e23" - integrity sha512-128YbMpjCrP35IOExw2Fq+x55LMP42DzhOhX2aNNIdI9avSWl2PI0yuBWarr3RYpZBSPtabfadkH2yeRiMD61Q== +"@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.24.7.tgz#468096ca44bbcbe8fcc570574e12eb1950e18107" + integrity sha512-unaQgZ/iRu/By6tsjMZzpeBZjChYfLYry6HrEXPoz3KmfF0sVBQ1l8zKMQ4xRGLWVsjuvB8nQfjNP/DcfEOCsg== dependencies: - "@babel/helper-plugin-utils" "^7.18.9" - "@babel/plugin-syntax-logical-assignment-operators" "^7.10.4" + "@babel/helper-plugin-utils" "^7.24.7" -"@babel/plugin-proposal-nullish-coalescing-operator@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.18.6.tgz#fdd940a99a740e577d6c753ab6fbb43fdb9467e1" - integrity sha512-wQxQzxYeJqHcfppzBDnm1yAY0jSRkUXR2z8RePZYrKwMKgMlE8+Z6LUno+bd6LvbGh8Gltvy74+9pIYkr+XkKA== +"@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.24.7.tgz#e4eabdd5109acc399b38d7999b2ef66fc2022f89" + integrity sha512-+izXIbke1T33mY4MSNnrqhPXDz01WYhEf3yF5NbnUtkiNnm+XBZJl3kNfoK6NKmYlz/D07+l2GWVK/QfDkNCuQ== dependencies: - "@babel/helper-plugin-utils" "^7.18.6" - "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.3" + "@babel/helper-plugin-utils" "^7.24.7" + "@babel/helper-skip-transparent-expression-wrappers" "^7.24.7" + "@babel/plugin-transform-optional-chaining" "^7.24.7" -"@babel/plugin-proposal-numeric-separator@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.18.6.tgz#899b14fbafe87f053d2c5ff05b36029c62e13c75" - integrity sha512-ozlZFogPqoLm8WBr5Z8UckIoE4YQ5KESVcNudyXOR8uqIkliTEgJ3RoketfG6pmzLdeZF0H/wjE9/cCEitBl7Q== +"@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.24.7.tgz#71b21bb0286d5810e63a1538aa901c58e87375ec" + integrity sha512-utA4HuR6F4Vvcr+o4DnjL8fCOlgRFGbeeBEGNg3ZTrLFw6VWG5XmUrvcQ0FjIYMU2ST4XcR2Wsp7t9qOAPnxMg== dependencies: - "@babel/helper-plugin-utils" "^7.18.6" - "@babel/plugin-syntax-numeric-separator" "^7.10.4" + "@babel/helper-environment-visitor" "^7.24.7" + "@babel/helper-plugin-utils" "^7.24.7" "@babel/plugin-proposal-object-rest-spread@7.12.1": version "7.12.1" @@ -529,59 +493,10 @@ "@babel/plugin-syntax-object-rest-spread" "^7.8.0" "@babel/plugin-transform-parameters" "^7.12.1" -"@babel/plugin-proposal-object-rest-spread@^7.20.2": - version "7.20.2" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.20.2.tgz#a556f59d555f06961df1e572bb5eca864c84022d" - integrity sha512-Ks6uej9WFK+fvIMesSqbAto5dD8Dz4VuuFvGJFKgIGSkJuRGcrwGECPA1fDgQK3/DbExBJpEkTeYeB8geIFCSQ== - dependencies: - "@babel/compat-data" "^7.20.1" - "@babel/helper-compilation-targets" "^7.20.0" - "@babel/helper-plugin-utils" "^7.20.2" - "@babel/plugin-syntax-object-rest-spread" "^7.8.3" - "@babel/plugin-transform-parameters" "^7.20.1" - -"@babel/plugin-proposal-optional-catch-binding@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.18.6.tgz#f9400d0e6a3ea93ba9ef70b09e72dd6da638a2cb" - integrity sha512-Q40HEhs9DJQyaZfUjjn6vE8Cv4GmMHCYuMGIWUnlxH6400VGxOuwWsPt4FxXxJkC/5eOzgn0z21M9gMT4MOhbw== - dependencies: - "@babel/helper-plugin-utils" "^7.18.6" - "@babel/plugin-syntax-optional-catch-binding" "^7.8.3" - -"@babel/plugin-proposal-optional-chaining@^7.18.9": - version "7.18.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.18.9.tgz#e8e8fe0723f2563960e4bf5e9690933691915993" - integrity sha512-v5nwt4IqBXihxGsW2QmCWMDS3B3bzGIk/EQVZz2ei7f3NJl8NzAJVvUmpDW5q1CRNY+Beb/k58UAH1Km1N411w== - dependencies: - "@babel/helper-plugin-utils" "^7.18.9" - "@babel/helper-skip-transparent-expression-wrappers" "^7.18.9" - "@babel/plugin-syntax-optional-chaining" "^7.8.3" - -"@babel/plugin-proposal-private-methods@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.18.6.tgz#5209de7d213457548a98436fa2882f52f4be6bea" - integrity sha512-nutsvktDItsNn4rpGItSNV2sz1XwS+nfU0Rg8aCx3W3NOKVzdMjJRu0O5OkgDp3ZGICSTbgRpxZoWsxoKRvbeA== - dependencies: - "@babel/helper-create-class-features-plugin" "^7.18.6" - "@babel/helper-plugin-utils" "^7.18.6" - -"@babel/plugin-proposal-private-property-in-object@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.18.6.tgz#a64137b232f0aca3733a67eb1a144c192389c503" - integrity sha512-9Rysx7FOctvT5ouj5JODjAFAkgGoudQuLPamZb0v1TGLpapdNaftzifU8NTWQm0IRjqoYypdrSmyWgkocDQ8Dw== - dependencies: - "@babel/helper-annotate-as-pure" "^7.18.6" - "@babel/helper-create-class-features-plugin" "^7.18.6" - "@babel/helper-plugin-utils" "^7.18.6" - "@babel/plugin-syntax-private-property-in-object" "^7.14.5" - -"@babel/plugin-proposal-unicode-property-regex@^7.18.6", "@babel/plugin-proposal-unicode-property-regex@^7.4.4": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.18.6.tgz#af613d2cd5e643643b65cded64207b15c85cb78e" - integrity sha512-2BShG/d5yoZyXZfVePH91urL5wTG6ASZU9M4o03lKK8u8UW1y08OMttBSOADTcJrnPMpvDXRG3G8fyLh4ovs8w== - dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.18.6" - "@babel/helper-plugin-utils" "^7.18.6" +"@babel/plugin-proposal-private-property-in-object@7.21.0-placeholder-for-preset-env.2": + version "7.21.0-placeholder-for-preset-env.2" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0-placeholder-for-preset-env.2.tgz#7844f9289546efa9febac2de4cfe358a050bd703" + integrity sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w== "@babel/plugin-syntax-async-generators@^7.8.4": version "7.8.4" @@ -618,12 +533,26 @@ dependencies: "@babel/helper-plugin-utils" "^7.8.3" -"@babel/plugin-syntax-import-assertions@^7.20.0": - version "7.20.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.20.0.tgz#bb50e0d4bea0957235390641209394e87bdb9cc4" - integrity sha512-IUh1vakzNoWalR8ch/areW7qFopR2AEw03JlG7BbrDqmQ4X3q9uuipQwSGrUn7oGiemKjtSLDhNtQHzMHr1JdQ== +"@babel/plugin-syntax-import-assertions@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.24.7.tgz#2a0b406b5871a20a841240586b1300ce2088a778" + integrity sha512-Ec3NRUMoi8gskrkBe3fNmEQfxDvY8bgfQpz6jlk/41kX9eUjvpyqWU7PBP/pLAvMaSQjbMNKJmvX57jP+M6bPg== + dependencies: + "@babel/helper-plugin-utils" "^7.24.7" + +"@babel/plugin-syntax-import-attributes@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.24.7.tgz#b4f9ea95a79e6912480c4b626739f86a076624ca" + integrity sha512-hbX+lKKeUMGihnK8nvKqmXBInriT3GVjzXKFriV3YC6APGxMbP8RZNFwy91+hocLXq90Mta+HshoB31802bb8A== dependencies: - "@babel/helper-plugin-utils" "^7.19.0" + "@babel/helper-plugin-utils" "^7.24.7" + +"@babel/plugin-syntax-import-meta@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz#ee601348c370fa334d2207be158777496521fd51" + integrity sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-syntax-json-strings@^7.8.3": version "7.8.3" @@ -639,12 +568,12 @@ dependencies: "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-syntax-jsx@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.18.6.tgz#a8feef63b010150abd97f1649ec296e849943ca0" - integrity sha512-6mmljtAedFGTWu2p/8WIORGwy+61PLgOMPOdazc7YoJ9ZCWUyFy3A6CpPkRKLKD1ToAesxX8KGEViAiLo9N+7Q== +"@babel/plugin-syntax-jsx@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.24.7.tgz#39a1fa4a7e3d3d7f34e2acc6be585b718d30e02d" + integrity sha512-6ddciUPe/mpMnOKv/U+RSd2vvVy+Yw/JfBB0ZHYjEZt9NLHmCUylNYlsbqCCS1Bffjlb0fCwC9Vqz+sBz6PsiQ== dependencies: - "@babel/helper-plugin-utils" "^7.18.6" + "@babel/helper-plugin-utils" "^7.24.7" "@babel/plugin-syntax-logical-assignment-operators@^7.10.4": version "7.10.4" @@ -702,356 +631,492 @@ dependencies: "@babel/helper-plugin-utils" "^7.14.5" -"@babel/plugin-syntax-typescript@^7.20.0": - version "7.20.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.20.0.tgz#4e9a0cfc769c85689b77a2e642d24e9f697fc8c7" - integrity sha512-rd9TkG+u1CExzS4SM1BlMEhMXwFLKVjOAFFCDx9PbX5ycJWDoWMcwdJH9RhkPu1dOgn5TrxLot/Gx6lWFuAUNQ== +"@babel/plugin-syntax-typescript@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.24.7.tgz#58d458271b4d3b6bb27ee6ac9525acbb259bad1c" + integrity sha512-c/+fVeJBB0FeKsFvwytYiUD+LBvhHjGSI0g446PRGdSVGZLRNArBUno2PETbAly3tpiNAQR5XaZ+JslxkotsbA== dependencies: - "@babel/helper-plugin-utils" "^7.19.0" + "@babel/helper-plugin-utils" "^7.24.7" -"@babel/plugin-transform-arrow-functions@^7.18.6": +"@babel/plugin-syntax-unicode-sets-regex@^7.18.6": version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.18.6.tgz#19063fcf8771ec7b31d742339dac62433d0611fe" - integrity sha512-9S9X9RUefzrsHZmKMbDXxweEH+YlE8JJEuat9FdvW9Qh1cw7W64jELCtWNkPBPX5En45uy28KGvA/AySqUh8CQ== + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-unicode-sets-regex/-/plugin-syntax-unicode-sets-regex-7.18.6.tgz#d49a3b3e6b52e5be6740022317580234a6a47357" + integrity sha512-727YkEAPwSIQTv5im8QHz3upqp92JTWhidIC81Tdx4VJYIte/VndKf1qKrfnnhPLiPghStWfvC/iFaMCQu7Nqg== dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.18.6" "@babel/helper-plugin-utils" "^7.18.6" -"@babel/plugin-transform-async-to-generator@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.18.6.tgz#ccda3d1ab9d5ced5265fdb13f1882d5476c71615" - integrity sha512-ARE5wZLKnTgPW7/1ftQmSi1CmkqqHo2DNmtztFhvgtOWSDfq0Cq9/9L+KnZNYSNrydBekhW3rwShduf59RoXag== +"@babel/plugin-transform-arrow-functions@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.24.7.tgz#4f6886c11e423bd69f3ce51dbf42424a5f275514" + integrity sha512-Dt9LQs6iEY++gXUwY03DNFat5C2NbO48jj+j/bSAz6b3HgPs39qcPiYt77fDObIcFwj3/C2ICX9YMwGflUoSHQ== dependencies: - "@babel/helper-module-imports" "^7.18.6" - "@babel/helper-plugin-utils" "^7.18.6" - "@babel/helper-remap-async-to-generator" "^7.18.6" + "@babel/helper-plugin-utils" "^7.24.7" -"@babel/plugin-transform-block-scoped-functions@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.18.6.tgz#9187bf4ba302635b9d70d986ad70f038726216a8" - integrity sha512-ExUcOqpPWnliRcPqves5HJcJOvHvIIWfuS4sroBUenPuMdmW+SMHDakmtS7qOo13sVppmUijqeTv7qqGsvURpQ== +"@babel/plugin-transform-async-generator-functions@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.24.7.tgz#7330a5c50e05181ca52351b8fd01642000c96cfd" + integrity sha512-o+iF77e3u7ZS4AoAuJvapz9Fm001PuD2V3Lp6OSE4FYQke+cSewYtnek+THqGRWyQloRCyvWL1OkyfNEl9vr/g== dependencies: - "@babel/helper-plugin-utils" "^7.18.6" + "@babel/helper-environment-visitor" "^7.24.7" + "@babel/helper-plugin-utils" "^7.24.7" + "@babel/helper-remap-async-to-generator" "^7.24.7" + "@babel/plugin-syntax-async-generators" "^7.8.4" + +"@babel/plugin-transform-async-to-generator@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.24.7.tgz#72a3af6c451d575842a7e9b5a02863414355bdcc" + integrity sha512-SQY01PcJfmQ+4Ash7NE+rpbLFbmqA2GPIgqzxfFTL4t1FKRq4zTms/7htKpoCUI9OcFYgzqfmCdH53s6/jn5fA== + dependencies: + "@babel/helper-module-imports" "^7.24.7" + "@babel/helper-plugin-utils" "^7.24.7" + "@babel/helper-remap-async-to-generator" "^7.24.7" + +"@babel/plugin-transform-block-scoped-functions@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.24.7.tgz#a4251d98ea0c0f399dafe1a35801eaba455bbf1f" + integrity sha512-yO7RAz6EsVQDaBH18IDJcMB1HnrUn2FJ/Jslc/WtPPWcjhpUJXU/rjbwmluzp7v/ZzWcEhTMXELnnsz8djWDwQ== + dependencies: + "@babel/helper-plugin-utils" "^7.24.7" + +"@babel/plugin-transform-block-scoping@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.24.7.tgz#42063e4deb850c7bd7c55e626bf4e7ab48e6ce02" + integrity sha512-Nd5CvgMbWc+oWzBsuaMcbwjJWAcp5qzrbg69SZdHSP7AMY0AbWFqFO0WTFCA1jxhMCwodRwvRec8k0QUbZk7RQ== + dependencies: + "@babel/helper-plugin-utils" "^7.24.7" + +"@babel/plugin-transform-class-properties@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.24.7.tgz#256879467b57b0b68c7ddfc5b76584f398cd6834" + integrity sha512-vKbfawVYayKcSeSR5YYzzyXvsDFWU2mD8U5TFeXtbCPLFUqe7GyCgvO6XDHzje862ODrOwy6WCPmKeWHbCFJ4w== + dependencies: + "@babel/helper-create-class-features-plugin" "^7.24.7" + "@babel/helper-plugin-utils" "^7.24.7" + +"@babel/plugin-transform-class-static-block@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.24.7.tgz#c82027ebb7010bc33c116d4b5044fbbf8c05484d" + integrity sha512-HMXK3WbBPpZQufbMG4B46A90PkuuhN9vBCb5T8+VAHqvAqvcLi+2cKoukcpmUYkszLhScU3l1iudhrks3DggRQ== + dependencies: + "@babel/helper-create-class-features-plugin" "^7.24.7" + "@babel/helper-plugin-utils" "^7.24.7" + "@babel/plugin-syntax-class-static-block" "^7.14.5" -"@babel/plugin-transform-block-scoping@^7.20.2": - version "7.20.2" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.20.2.tgz#f59b1767e6385c663fd0bce655db6ca9c8b236ed" - integrity sha512-y5V15+04ry69OV2wULmwhEA6jwSWXO1TwAtIwiPXcvHcoOQUqpyMVd2bDsQJMW8AurjulIyUV8kDqtjSwHy1uQ== - dependencies: - "@babel/helper-plugin-utils" "^7.20.2" - -"@babel/plugin-transform-classes@^7.20.2": - version "7.20.2" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.20.2.tgz#c0033cf1916ccf78202d04be4281d161f6709bb2" - integrity sha512-9rbPp0lCVVoagvtEyQKSo5L8oo0nQS/iif+lwlAz29MccX2642vWDlSZK+2T2buxbopotId2ld7zZAzRfz9j1g== - dependencies: - "@babel/helper-annotate-as-pure" "^7.18.6" - "@babel/helper-compilation-targets" "^7.20.0" - "@babel/helper-environment-visitor" "^7.18.9" - "@babel/helper-function-name" "^7.19.0" - "@babel/helper-optimise-call-expression" "^7.18.6" - "@babel/helper-plugin-utils" "^7.20.2" - "@babel/helper-replace-supers" "^7.19.1" - "@babel/helper-split-export-declaration" "^7.18.6" +"@babel/plugin-transform-classes@^7.24.8": + version "7.24.8" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.24.8.tgz#ad23301fe5bc153ca4cf7fb572a9bc8b0b711cf7" + integrity sha512-VXy91c47uujj758ud9wx+OMgheXm4qJfyhj1P18YvlrQkNOSrwsteHk+EFS3OMGfhMhpZa0A+81eE7G4QC+3CA== + dependencies: + "@babel/helper-annotate-as-pure" "^7.24.7" + "@babel/helper-compilation-targets" "^7.24.8" + "@babel/helper-environment-visitor" "^7.24.7" + "@babel/helper-function-name" "^7.24.7" + "@babel/helper-plugin-utils" "^7.24.8" + "@babel/helper-replace-supers" "^7.24.7" + "@babel/helper-split-export-declaration" "^7.24.7" globals "^11.1.0" -"@babel/plugin-transform-computed-properties@^7.18.9": - version "7.18.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.18.9.tgz#2357a8224d402dad623caf6259b611e56aec746e" - integrity sha512-+i0ZU1bCDymKakLxn5srGHrsAPRELC2WIbzwjLhHW9SIE1cPYkLCL0NlnXMZaM1vhfgA2+M7hySk42VBvrkBRw== +"@babel/plugin-transform-computed-properties@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.24.7.tgz#4cab3214e80bc71fae3853238d13d097b004c707" + integrity sha512-25cS7v+707Gu6Ds2oY6tCkUwsJ9YIDbggd9+cu9jzzDgiNq7hR/8dkzxWfKWnTic26vsI3EsCXNd4iEB6e8esQ== dependencies: - "@babel/helper-plugin-utils" "^7.18.9" + "@babel/helper-plugin-utils" "^7.24.7" + "@babel/template" "^7.24.7" -"@babel/plugin-transform-destructuring@^7.20.2": - version "7.20.2" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.20.2.tgz#c23741cfa44ddd35f5e53896e88c75331b8b2792" - integrity sha512-mENM+ZHrvEgxLTBXUiQ621rRXZes3KWUv6NdQlrnr1TkWVw+hUjQBZuP2X32qKlrlG2BzgR95gkuCRSkJl8vIw== +"@babel/plugin-transform-destructuring@^7.24.8": + version "7.24.8" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.24.8.tgz#c828e814dbe42a2718a838c2a2e16a408e055550" + integrity sha512-36e87mfY8TnRxc7yc6M9g9gOB7rKgSahqkIKwLpz4Ppk2+zC2Cy1is0uwtuSG6AE4zlTOUa+7JGz9jCJGLqQFQ== dependencies: - "@babel/helper-plugin-utils" "^7.20.2" + "@babel/helper-plugin-utils" "^7.24.8" -"@babel/plugin-transform-dotall-regex@^7.18.6", "@babel/plugin-transform-dotall-regex@^7.4.4": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.18.6.tgz#b286b3e7aae6c7b861e45bed0a2fafd6b1a4fef8" - integrity sha512-6S3jpun1eEbAxq7TdjLotAsl4WpQI9DxfkycRcKrjhQYzU87qpXdknpBg/e+TdcMehqGnLFi7tnFUBR02Vq6wg== +"@babel/plugin-transform-dotall-regex@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.24.7.tgz#5f8bf8a680f2116a7207e16288a5f974ad47a7a0" + integrity sha512-ZOA3W+1RRTSWvyqcMJDLqbchh7U4NRGqwRfFSVbOLS/ePIP4vHB5e8T8eXcuqyN1QkgKyj5wuW0lcS85v4CrSw== dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.18.6" - "@babel/helper-plugin-utils" "^7.18.6" + "@babel/helper-create-regexp-features-plugin" "^7.24.7" + "@babel/helper-plugin-utils" "^7.24.7" -"@babel/plugin-transform-duplicate-keys@^7.18.9": - version "7.18.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.18.9.tgz#687f15ee3cdad6d85191eb2a372c4528eaa0ae0e" - integrity sha512-d2bmXCtZXYc59/0SanQKbiWINadaJXqtvIQIzd4+hNwkWBgyCd5F/2t1kXoUdvPMrxzPvhK6EMQRROxsue+mfw== +"@babel/plugin-transform-duplicate-keys@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.24.7.tgz#dd20102897c9a2324e5adfffb67ff3610359a8ee" + integrity sha512-JdYfXyCRihAe46jUIliuL2/s0x0wObgwwiGxw/UbgJBr20gQBThrokO4nYKgWkD7uBaqM7+9x5TU7NkExZJyzw== dependencies: - "@babel/helper-plugin-utils" "^7.18.9" + "@babel/helper-plugin-utils" "^7.24.7" -"@babel/plugin-transform-exponentiation-operator@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.18.6.tgz#421c705f4521888c65e91fdd1af951bfefd4dacd" - integrity sha512-wzEtc0+2c88FVR34aQmiz56dxEkxr2g8DQb/KfaFa1JYXOFVsbhvAonFN6PwVWj++fKmku8NP80plJ5Et4wqHw== +"@babel/plugin-transform-dynamic-import@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.24.7.tgz#4d8b95e3bae2b037673091aa09cd33fecd6419f4" + integrity sha512-sc3X26PhZQDb3JhORmakcbvkeInvxz+A8oda99lj7J60QRuPZvNAk9wQlTBS1ZynelDrDmTU4pw1tyc5d5ZMUg== dependencies: - "@babel/helper-builder-binary-assignment-operator-visitor" "^7.18.6" - "@babel/helper-plugin-utils" "^7.18.6" + "@babel/helper-plugin-utils" "^7.24.7" + "@babel/plugin-syntax-dynamic-import" "^7.8.3" -"@babel/plugin-transform-for-of@^7.18.8": - version "7.18.8" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.18.8.tgz#6ef8a50b244eb6a0bdbad0c7c61877e4e30097c1" - integrity sha512-yEfTRnjuskWYo0k1mHUqrVWaZwrdq8AYbfrpqULOJOaucGSp4mNMVps+YtA8byoevxS/urwU75vyhQIxcCgiBQ== +"@babel/plugin-transform-exponentiation-operator@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.24.7.tgz#b629ee22645f412024297d5245bce425c31f9b0d" + integrity sha512-Rqe/vSc9OYgDajNIK35u7ot+KeCoetqQYFXM4Epf7M7ez3lWlOjrDjrwMei6caCVhfdw+mIKD4cgdGNy5JQotQ== dependencies: - "@babel/helper-plugin-utils" "^7.18.6" + "@babel/helper-builder-binary-assignment-operator-visitor" "^7.24.7" + "@babel/helper-plugin-utils" "^7.24.7" -"@babel/plugin-transform-function-name@^7.18.9": - version "7.18.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.18.9.tgz#cc354f8234e62968946c61a46d6365440fc764e0" - integrity sha512-WvIBoRPaJQ5yVHzcnJFor7oS5Ls0PYixlTYE63lCj2RtdQEl15M68FXQlxnG6wdraJIXRdR7KI+hQ7q/9QjrCQ== +"@babel/plugin-transform-export-namespace-from@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.24.7.tgz#176d52d8d8ed516aeae7013ee9556d540c53f197" + integrity sha512-v0K9uNYsPL3oXZ/7F9NNIbAj2jv1whUEtyA6aujhekLs56R++JDQuzRcP2/z4WX5Vg/c5lE9uWZA0/iUoFhLTA== dependencies: - "@babel/helper-compilation-targets" "^7.18.9" - "@babel/helper-function-name" "^7.18.9" - "@babel/helper-plugin-utils" "^7.18.9" + "@babel/helper-plugin-utils" "^7.24.7" + "@babel/plugin-syntax-export-namespace-from" "^7.8.3" -"@babel/plugin-transform-literals@^7.18.9": - version "7.18.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-literals/-/plugin-transform-literals-7.18.9.tgz#72796fdbef80e56fba3c6a699d54f0de557444bc" - integrity sha512-IFQDSRoTPnrAIrI5zoZv73IFeZu2dhu6irxQjY9rNjTT53VmKg9fenjvoiOWOkJ6mm4jKVPtdMzBY98Fp4Z4cg== +"@babel/plugin-transform-for-of@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.24.7.tgz#f25b33f72df1d8be76399e1b8f3f9d366eb5bc70" + integrity sha512-wo9ogrDG1ITTTBsy46oGiN1dS9A7MROBTcYsfS8DtsImMkHk9JXJ3EWQM6X2SUw4x80uGPlwj0o00Uoc6nEE3g== dependencies: - "@babel/helper-plugin-utils" "^7.18.9" + "@babel/helper-plugin-utils" "^7.24.7" + "@babel/helper-skip-transparent-expression-wrappers" "^7.24.7" -"@babel/plugin-transform-member-expression-literals@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.18.6.tgz#ac9fdc1a118620ac49b7e7a5d2dc177a1bfee88e" - integrity sha512-qSF1ihLGO3q+/g48k85tUjD033C29TNTVB2paCwZPVmOsjn9pClvYYrM2VeJpBY2bcNkuny0YUyTNRyRxJ54KA== +"@babel/plugin-transform-function-name@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.24.7.tgz#6d8601fbffe665c894440ab4470bc721dd9131d6" + integrity sha512-U9FcnA821YoILngSmYkW6FjyQe2TyZD5pHt4EVIhmcTkrJw/3KqcrRSxuOo5tFZJi7TE19iDyI1u+weTI7bn2w== dependencies: - "@babel/helper-plugin-utils" "^7.18.6" + "@babel/helper-compilation-targets" "^7.24.7" + "@babel/helper-function-name" "^7.24.7" + "@babel/helper-plugin-utils" "^7.24.7" -"@babel/plugin-transform-modules-amd@^7.19.6": - version "7.19.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.19.6.tgz#aca391801ae55d19c4d8d2ebfeaa33df5f2a2cbd" - integrity sha512-uG3od2mXvAtIFQIh0xrpLH6r5fpSQN04gIVovl+ODLdUMANokxQLZnPBHcjmv3GxRjnqwLuHvppjjcelqUFZvg== +"@babel/plugin-transform-json-strings@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.24.7.tgz#f3e9c37c0a373fee86e36880d45b3664cedaf73a" + integrity sha512-2yFnBGDvRuxAaE/f0vfBKvtnvvqU8tGpMHqMNpTN2oWMKIR3NqFkjaAgGwawhqK/pIN2T3XdjGPdaG0vDhOBGw== dependencies: - "@babel/helper-module-transforms" "^7.19.6" - "@babel/helper-plugin-utils" "^7.19.0" + "@babel/helper-plugin-utils" "^7.24.7" + "@babel/plugin-syntax-json-strings" "^7.8.3" -"@babel/plugin-transform-modules-commonjs@^7.19.6": - version "7.19.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.19.6.tgz#25b32feef24df8038fc1ec56038917eacb0b730c" - integrity sha512-8PIa1ym4XRTKuSsOUXqDG0YaOlEuTVvHMe5JCfgBMOtHvJKw/4NGovEGN33viISshG/rZNVrACiBmPQLvWN8xQ== +"@babel/plugin-transform-literals@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-literals/-/plugin-transform-literals-7.24.7.tgz#36b505c1e655151a9d7607799a9988fc5467d06c" + integrity sha512-vcwCbb4HDH+hWi8Pqenwnjy+UiklO4Kt1vfspcQYFhJdpthSnW8XvWGyDZWKNVrVbVViI/S7K9PDJZiUmP2fYQ== dependencies: - "@babel/helper-module-transforms" "^7.19.6" - "@babel/helper-plugin-utils" "^7.19.0" - "@babel/helper-simple-access" "^7.19.4" + "@babel/helper-plugin-utils" "^7.24.7" -"@babel/plugin-transform-modules-systemjs@^7.19.6": - version "7.19.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.19.6.tgz#59e2a84064b5736a4471b1aa7b13d4431d327e0d" - integrity sha512-fqGLBepcc3kErfR9R3DnVpURmckXP7gj7bAlrTQyBxrigFqszZCkFkcoxzCp2v32XmwXLvbw+8Yq9/b+QqksjQ== +"@babel/plugin-transform-logical-assignment-operators@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.24.7.tgz#a58fb6eda16c9dc8f9ff1c7b1ba6deb7f4694cb0" + integrity sha512-4D2tpwlQ1odXmTEIFWy9ELJcZHqrStlzK/dAOWYyxX3zT0iXQB6banjgeOJQXzEc4S0E0a5A+hahxPaEFYftsw== dependencies: - "@babel/helper-hoist-variables" "^7.18.6" - "@babel/helper-module-transforms" "^7.19.6" - "@babel/helper-plugin-utils" "^7.19.0" - "@babel/helper-validator-identifier" "^7.19.1" + "@babel/helper-plugin-utils" "^7.24.7" + "@babel/plugin-syntax-logical-assignment-operators" "^7.10.4" -"@babel/plugin-transform-modules-umd@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.18.6.tgz#81d3832d6034b75b54e62821ba58f28ed0aab4b9" - integrity sha512-dcegErExVeXcRqNtkRU/z8WlBLnvD4MRnHgNs3MytRO1Mn1sHRyhbcpYbVMGclAqOjdW+9cfkdZno9dFdfKLfQ== +"@babel/plugin-transform-member-expression-literals@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.24.7.tgz#3b4454fb0e302e18ba4945ba3246acb1248315df" + integrity sha512-T/hRC1uqrzXMKLQ6UCwMT85S3EvqaBXDGf0FaMf4446Qx9vKwlghvee0+uuZcDUCZU5RuNi4781UQ7R308zzBw== dependencies: - "@babel/helper-module-transforms" "^7.18.6" - "@babel/helper-plugin-utils" "^7.18.6" + "@babel/helper-plugin-utils" "^7.24.7" -"@babel/plugin-transform-named-capturing-groups-regex@^7.19.1": - version "7.19.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.19.1.tgz#ec7455bab6cd8fb05c525a94876f435a48128888" - integrity sha512-oWk9l9WItWBQYS4FgXD4Uyy5kq898lvkXpXQxoJEY1RnvPk4R/Dvu2ebXU9q8lP+rlMwUQTFf2Ok6d78ODa0kw== +"@babel/plugin-transform-modules-amd@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.24.7.tgz#65090ed493c4a834976a3ca1cde776e6ccff32d7" + integrity sha512-9+pB1qxV3vs/8Hdmz/CulFB8w2tuu6EB94JZFsjdqxQokwGa9Unap7Bo2gGBGIvPmDIVvQrom7r5m/TCDMURhg== dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.19.0" - "@babel/helper-plugin-utils" "^7.19.0" + "@babel/helper-module-transforms" "^7.24.7" + "@babel/helper-plugin-utils" "^7.24.7" -"@babel/plugin-transform-new-target@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.18.6.tgz#d128f376ae200477f37c4ddfcc722a8a1b3246a8" - integrity sha512-DjwFA/9Iu3Z+vrAn+8pBUGcjhxKguSMlsFqeCKbhb9BAV756v0krzVK04CRDi/4aqmk8BsHb4a/gFcaA5joXRw== +"@babel/plugin-transform-modules-commonjs@^7.24.7", "@babel/plugin-transform-modules-commonjs@^7.24.8": + version "7.24.8" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.24.8.tgz#ab6421e564b717cb475d6fff70ae7f103536ea3c" + integrity sha512-WHsk9H8XxRs3JXKWFiqtQebdh9b/pTk4EgueygFzYlTKAg0Ud985mSevdNjdXdFBATSKVJGQXP1tv6aGbssLKA== dependencies: - "@babel/helper-plugin-utils" "^7.18.6" + "@babel/helper-module-transforms" "^7.24.8" + "@babel/helper-plugin-utils" "^7.24.8" + "@babel/helper-simple-access" "^7.24.7" -"@babel/plugin-transform-object-super@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.18.6.tgz#fb3c6ccdd15939b6ff7939944b51971ddc35912c" - integrity sha512-uvGz6zk+pZoS1aTZrOvrbj6Pp/kK2mp45t2B+bTDre2UgsZZ8EZLSJtUg7m/no0zOJUWgFONpB7Zv9W2tSaFlA== +"@babel/plugin-transform-modules-systemjs@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.24.7.tgz#f8012316c5098f6e8dee6ecd58e2bc6f003d0ce7" + integrity sha512-GYQE0tW7YoaN13qFh3O1NCY4MPkUiAH3fiF7UcV/I3ajmDKEdG3l+UOcbAm4zUE3gnvUU+Eni7XrVKo9eO9auw== dependencies: - "@babel/helper-plugin-utils" "^7.18.6" - "@babel/helper-replace-supers" "^7.18.6" + "@babel/helper-hoist-variables" "^7.24.7" + "@babel/helper-module-transforms" "^7.24.7" + "@babel/helper-plugin-utils" "^7.24.7" + "@babel/helper-validator-identifier" "^7.24.7" -"@babel/plugin-transform-parameters@^7.12.1", "@babel/plugin-transform-parameters@^7.20.1": - version "7.20.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.20.3.tgz#7b3468d70c3c5b62e46be0a47b6045d8590fb748" - integrity sha512-oZg/Fpx0YDrj13KsLyO8I/CX3Zdw7z0O9qOd95SqcoIzuqy/WTGWvePeHAnZCN54SfdyjHcb1S30gc8zlzlHcA== +"@babel/plugin-transform-modules-umd@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.24.7.tgz#edd9f43ec549099620df7df24e7ba13b5c76efc8" + integrity sha512-3aytQvqJ/h9z4g8AsKPLvD4Zqi2qT+L3j7XoFFu1XBlZWEl2/1kWnhmAbxpLgPrHSY0M6UA02jyTiwUVtiKR6A== dependencies: - "@babel/helper-plugin-utils" "^7.20.2" + "@babel/helper-module-transforms" "^7.24.7" + "@babel/helper-plugin-utils" "^7.24.7" -"@babel/plugin-transform-property-literals@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.18.6.tgz#e22498903a483448e94e032e9bbb9c5ccbfc93a3" - integrity sha512-cYcs6qlgafTud3PAzrrRNbQtfpQ8+y/+M5tKmksS9+M1ckbH6kzY8MrexEM9mcA6JDsukE19iIRvAyYl463sMg== +"@babel/plugin-transform-named-capturing-groups-regex@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.24.7.tgz#9042e9b856bc6b3688c0c2e4060e9e10b1460923" + integrity sha512-/jr7h/EWeJtk1U/uz2jlsCioHkZk1JJZVcc8oQsJ1dUlaJD83f4/6Zeh2aHt9BIFokHIsSeDfhUmju0+1GPd6g== dependencies: - "@babel/helper-plugin-utils" "^7.18.6" + "@babel/helper-create-regexp-features-plugin" "^7.24.7" + "@babel/helper-plugin-utils" "^7.24.7" + +"@babel/plugin-transform-new-target@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.24.7.tgz#31ff54c4e0555cc549d5816e4ab39241dfb6ab00" + integrity sha512-RNKwfRIXg4Ls/8mMTza5oPF5RkOW8Wy/WgMAp1/F1yZ8mMbtwXW+HDoJiOsagWrAhI5f57Vncrmr9XeT4CVapA== + dependencies: + "@babel/helper-plugin-utils" "^7.24.7" + +"@babel/plugin-transform-nullish-coalescing-operator@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.24.7.tgz#1de4534c590af9596f53d67f52a92f12db984120" + integrity sha512-Ts7xQVk1OEocqzm8rHMXHlxvsfZ0cEF2yomUqpKENHWMF4zKk175Y4q8H5knJes6PgYad50uuRmt3UJuhBw8pQ== + dependencies: + "@babel/helper-plugin-utils" "^7.24.7" + "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.3" + +"@babel/plugin-transform-numeric-separator@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.24.7.tgz#bea62b538c80605d8a0fac9b40f48e97efa7de63" + integrity sha512-e6q1TiVUzvH9KRvicuxdBTUj4AdKSRwzIyFFnfnezpCfP2/7Qmbb8qbU2j7GODbl4JMkblitCQjKYUaX/qkkwA== + dependencies: + "@babel/helper-plugin-utils" "^7.24.7" + "@babel/plugin-syntax-numeric-separator" "^7.10.4" + +"@babel/plugin-transform-object-rest-spread@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.24.7.tgz#d13a2b93435aeb8a197e115221cab266ba6e55d6" + integrity sha512-4QrHAr0aXQCEFni2q4DqKLD31n2DL+RxcwnNjDFkSG0eNQ/xCavnRkfCUjsyqGC2OviNJvZOF/mQqZBw7i2C5Q== + dependencies: + "@babel/helper-compilation-targets" "^7.24.7" + "@babel/helper-plugin-utils" "^7.24.7" + "@babel/plugin-syntax-object-rest-spread" "^7.8.3" + "@babel/plugin-transform-parameters" "^7.24.7" + +"@babel/plugin-transform-object-super@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.24.7.tgz#66eeaff7830bba945dd8989b632a40c04ed625be" + integrity sha512-A/vVLwN6lBrMFmMDmPPz0jnE6ZGx7Jq7d6sT/Ev4H65RER6pZ+kczlf1DthF5N0qaPHBsI7UXiE8Zy66nmAovg== + dependencies: + "@babel/helper-plugin-utils" "^7.24.7" + "@babel/helper-replace-supers" "^7.24.7" + +"@babel/plugin-transform-optional-catch-binding@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.24.7.tgz#00eabd883d0dd6a60c1c557548785919b6e717b4" + integrity sha512-uLEndKqP5BfBbC/5jTwPxLh9kqPWWgzN/f8w6UwAIirAEqiIVJWWY312X72Eub09g5KF9+Zn7+hT7sDxmhRuKA== + dependencies: + "@babel/helper-plugin-utils" "^7.24.7" + "@babel/plugin-syntax-optional-catch-binding" "^7.8.3" + +"@babel/plugin-transform-optional-chaining@^7.24.7", "@babel/plugin-transform-optional-chaining@^7.24.8": + version "7.24.8" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.24.8.tgz#bb02a67b60ff0406085c13d104c99a835cdf365d" + integrity sha512-5cTOLSMs9eypEy8JUVvIKOu6NgvbJMnpG62VpIHrTmROdQ+L5mDAaI40g25k5vXti55JWNX5jCkq3HZxXBQANw== + dependencies: + "@babel/helper-plugin-utils" "^7.24.8" + "@babel/helper-skip-transparent-expression-wrappers" "^7.24.7" + "@babel/plugin-syntax-optional-chaining" "^7.8.3" + +"@babel/plugin-transform-parameters@^7.12.1", "@babel/plugin-transform-parameters@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.24.7.tgz#5881f0ae21018400e320fc7eb817e529d1254b68" + integrity sha512-yGWW5Rr+sQOhK0Ot8hjDJuxU3XLRQGflvT4lhlSY0DFvdb3TwKaY26CJzHtYllU0vT9j58hc37ndFPsqT1SrzA== + dependencies: + "@babel/helper-plugin-utils" "^7.24.7" + +"@babel/plugin-transform-private-methods@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.24.7.tgz#e6318746b2ae70a59d023d5cc1344a2ba7a75f5e" + integrity sha512-COTCOkG2hn4JKGEKBADkA8WNb35TGkkRbI5iT845dB+NyqgO8Hn+ajPbSnIQznneJTa3d30scb6iz/DhH8GsJQ== + dependencies: + "@babel/helper-create-class-features-plugin" "^7.24.7" + "@babel/helper-plugin-utils" "^7.24.7" + +"@babel/plugin-transform-private-property-in-object@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.24.7.tgz#4eec6bc701288c1fab5f72e6a4bbc9d67faca061" + integrity sha512-9z76mxwnwFxMyxZWEgdgECQglF2Q7cFLm0kMf8pGwt+GSJsY0cONKj/UuO4bOH0w/uAel3ekS4ra5CEAyJRmDA== + dependencies: + "@babel/helper-annotate-as-pure" "^7.24.7" + "@babel/helper-create-class-features-plugin" "^7.24.7" + "@babel/helper-plugin-utils" "^7.24.7" + "@babel/plugin-syntax-private-property-in-object" "^7.14.5" + +"@babel/plugin-transform-property-literals@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.24.7.tgz#f0d2ed8380dfbed949c42d4d790266525d63bbdc" + integrity sha512-EMi4MLQSHfd2nrCqQEWxFdha2gBCqU4ZcCng4WBGZ5CJL4bBRW0ptdqqDdeirGZcpALazVVNJqRmsO8/+oNCBA== + dependencies: + "@babel/helper-plugin-utils" "^7.24.7" "@babel/plugin-transform-react-constant-elements@^7.18.12": - version "7.20.2" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-constant-elements/-/plugin-transform-react-constant-elements-7.20.2.tgz#3f02c784e0b711970d7d8ccc96c4359d64e27ac7" - integrity sha512-KS/G8YI8uwMGKErLFOHS/ekhqdHhpEloxs43NecQHVgo2QuQSyJhGIY1fL8UGl9wy5ItVwwoUL4YxVqsplGq2g== + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-constant-elements/-/plugin-transform-react-constant-elements-7.24.7.tgz#b85e8f240b14400277f106c9c9b585d9acf608a1" + integrity sha512-7LidzZfUXyfZ8/buRW6qIIHBY8wAZ1OrY9c/wTr8YhZ6vMPo+Uc/CVFLYY1spZrEQlD4w5u8wjqk5NQ3OVqQKA== dependencies: - "@babel/helper-plugin-utils" "^7.20.2" + "@babel/helper-plugin-utils" "^7.24.7" -"@babel/plugin-transform-react-display-name@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.18.6.tgz#8b1125f919ef36ebdfff061d664e266c666b9415" - integrity sha512-TV4sQ+T013n61uMoygyMRm+xf04Bd5oqFpv2jAEQwSZ8NwQA7zeRPg1LMVg2PWi3zWBz+CLKD+v5bcpZ/BS0aA== +"@babel/plugin-transform-react-display-name@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.24.7.tgz#9caff79836803bc666bcfe210aeb6626230c293b" + integrity sha512-H/Snz9PFxKsS1JLI4dJLtnJgCJRoo0AUm3chP6NYr+9En1JMKloheEiLIhlp5MDVznWo+H3AAC1Mc8lmUEpsgg== dependencies: - "@babel/helper-plugin-utils" "^7.18.6" + "@babel/helper-plugin-utils" "^7.24.7" -"@babel/plugin-transform-react-jsx-development@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.18.6.tgz#dbe5c972811e49c7405b630e4d0d2e1380c0ddc5" - integrity sha512-SA6HEjwYFKF7WDjWcMcMGUimmw/nhNRDWxr+KaLSCrkD/LMDBvWRmHAYgE1HDeF8KUuI8OAu+RT6EOtKxSW2qA== +"@babel/plugin-transform-react-jsx-development@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.24.7.tgz#eaee12f15a93f6496d852509a850085e6361470b" + integrity sha512-QG9EnzoGn+Qar7rxuW+ZOsbWOt56FvvI93xInqsZDC5fsekx1AlIO4KIJ5M+D0p0SqSH156EpmZyXq630B8OlQ== dependencies: - "@babel/plugin-transform-react-jsx" "^7.18.6" + "@babel/plugin-transform-react-jsx" "^7.24.7" -"@babel/plugin-transform-react-jsx@^7.18.6": - version "7.19.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.19.0.tgz#b3cbb7c3a00b92ec8ae1027910e331ba5c500eb9" - integrity sha512-UVEvX3tXie3Szm3emi1+G63jyw1w5IcMY0FSKM+CRnKRI5Mr1YbCNgsSTwoTwKphQEG9P+QqmuRFneJPZuHNhg== +"@babel/plugin-transform-react-jsx@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.24.7.tgz#17cd06b75a9f0e2bd076503400e7c4b99beedac4" + integrity sha512-+Dj06GDZEFRYvclU6k4bme55GKBEWUmByM/eoKuqg4zTNQHiApWRhQph5fxQB2wAEFvRzL1tOEj1RJ19wJrhoA== dependencies: - "@babel/helper-annotate-as-pure" "^7.18.6" - "@babel/helper-module-imports" "^7.18.6" - "@babel/helper-plugin-utils" "^7.19.0" - "@babel/plugin-syntax-jsx" "^7.18.6" - "@babel/types" "^7.19.0" + "@babel/helper-annotate-as-pure" "^7.24.7" + "@babel/helper-module-imports" "^7.24.7" + "@babel/helper-plugin-utils" "^7.24.7" + "@babel/plugin-syntax-jsx" "^7.24.7" + "@babel/types" "^7.24.7" -"@babel/plugin-transform-react-pure-annotations@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.18.6.tgz#561af267f19f3e5d59291f9950fd7b9663d0d844" - integrity sha512-I8VfEPg9r2TRDdvnHgPepTKvuRomzA8+u+nhY7qSI1fR2hRNebasZEETLyM5mAUr0Ku56OkXJ0I7NHJnO6cJiQ== +"@babel/plugin-transform-react-pure-annotations@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.24.7.tgz#bdd9d140d1c318b4f28b29a00fb94f97ecab1595" + integrity sha512-PLgBVk3fzbmEjBJ/u8kFzOqS9tUeDjiaWud/rRym/yjCo/M9cASPlnrd2ZmmZpQT40fOOrvR8jh+n8jikrOhNA== dependencies: - "@babel/helper-annotate-as-pure" "^7.18.6" - "@babel/helper-plugin-utils" "^7.18.6" + "@babel/helper-annotate-as-pure" "^7.24.7" + "@babel/helper-plugin-utils" "^7.24.7" -"@babel/plugin-transform-regenerator@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.18.6.tgz#585c66cb84d4b4bf72519a34cfce761b8676ca73" - integrity sha512-poqRI2+qiSdeldcz4wTSTXBRryoq3Gc70ye7m7UD5Ww0nE29IXqMl6r7Nd15WBgRd74vloEMlShtH6CKxVzfmQ== +"@babel/plugin-transform-regenerator@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.24.7.tgz#021562de4534d8b4b1851759fd7af4e05d2c47f8" + integrity sha512-lq3fvXPdimDrlg6LWBoqj+r/DEWgONuwjuOuQCSYgRroXDH/IdM1C0IZf59fL5cHLpjEH/O6opIRBbqv7ELnuA== dependencies: - "@babel/helper-plugin-utils" "^7.18.6" - regenerator-transform "^0.15.0" + "@babel/helper-plugin-utils" "^7.24.7" + regenerator-transform "^0.15.2" -"@babel/plugin-transform-reserved-words@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.18.6.tgz#b1abd8ebf8edaa5f7fe6bbb8d2133d23b6a6f76a" - integrity sha512-oX/4MyMoypzHjFrT1CdivfKZ+XvIPMFXwwxHp/r0Ddy2Vuomt4HDFGmft1TAY2yiTKiNSsh3kjBAzcM8kSdsjA== +"@babel/plugin-transform-reserved-words@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.24.7.tgz#80037fe4fbf031fc1125022178ff3938bb3743a4" + integrity sha512-0DUq0pHcPKbjFZCfTss/pGkYMfy3vFWydkUBd9r0GHpIyfs2eCDENvqadMycRS9wZCXR41wucAfJHJmwA0UmoQ== dependencies: - "@babel/helper-plugin-utils" "^7.18.6" + "@babel/helper-plugin-utils" "^7.24.7" "@babel/plugin-transform-runtime@^7.18.6": - version "7.19.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.19.6.tgz#9d2a9dbf4e12644d6f46e5e75bfbf02b5d6e9194" - integrity sha512-PRH37lz4JU156lYFW1p8OxE5i7d6Sl/zV58ooyr+q1J1lnQPyg5tIiXlIwNVhJaY4W3TmOtdc8jqdXQcB1v5Yw== - dependencies: - "@babel/helper-module-imports" "^7.18.6" - "@babel/helper-plugin-utils" "^7.19.0" - babel-plugin-polyfill-corejs2 "^0.3.3" - babel-plugin-polyfill-corejs3 "^0.6.0" - babel-plugin-polyfill-regenerator "^0.4.1" - semver "^6.3.0" + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.24.7.tgz#00a5bfaf8c43cf5c8703a8a6e82b59d9c58f38ca" + integrity sha512-YqXjrk4C+a1kZjewqt+Mmu2UuV1s07y8kqcUf4qYLnoqemhR4gRQikhdAhSVJioMjVTu6Mo6pAbaypEA3jY6fw== + dependencies: + "@babel/helper-module-imports" "^7.24.7" + "@babel/helper-plugin-utils" "^7.24.7" + babel-plugin-polyfill-corejs2 "^0.4.10" + babel-plugin-polyfill-corejs3 "^0.10.1" + babel-plugin-polyfill-regenerator "^0.6.1" + semver "^6.3.1" -"@babel/plugin-transform-shorthand-properties@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.18.6.tgz#6d6df7983d67b195289be24909e3f12a8f664dc9" - integrity sha512-eCLXXJqv8okzg86ywZJbRn19YJHU4XUa55oz2wbHhaQVn/MM+XhukiT7SYqp/7o00dg52Rj51Ny+Ecw4oyoygw== +"@babel/plugin-transform-shorthand-properties@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.24.7.tgz#85448c6b996e122fa9e289746140aaa99da64e73" + integrity sha512-KsDsevZMDsigzbA09+vacnLpmPH4aWjcZjXdyFKGzpplxhbeB4wYtury3vglQkg6KM/xEPKt73eCjPPf1PgXBA== dependencies: - "@babel/helper-plugin-utils" "^7.18.6" + "@babel/helper-plugin-utils" "^7.24.7" -"@babel/plugin-transform-spread@^7.19.0": - version "7.19.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-spread/-/plugin-transform-spread-7.19.0.tgz#dd60b4620c2fec806d60cfaae364ec2188d593b6" - integrity sha512-RsuMk7j6n+r752EtzyScnWkQyuJdli6LdO5Klv8Yx0OfPVTcQkIUfS8clx5e9yHXzlnhOZF3CbQ8C2uP5j074w== +"@babel/plugin-transform-spread@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-spread/-/plugin-transform-spread-7.24.7.tgz#e8a38c0fde7882e0fb8f160378f74bd885cc7bb3" + integrity sha512-x96oO0I09dgMDxJaANcRyD4ellXFLLiWhuwDxKZX5g2rWP1bTPkBSwCYv96VDXVT1bD9aPj8tppr5ITIh8hBng== dependencies: - "@babel/helper-plugin-utils" "^7.19.0" - "@babel/helper-skip-transparent-expression-wrappers" "^7.18.9" + "@babel/helper-plugin-utils" "^7.24.7" + "@babel/helper-skip-transparent-expression-wrappers" "^7.24.7" -"@babel/plugin-transform-sticky-regex@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.18.6.tgz#c6706eb2b1524028e317720339583ad0f444adcc" - integrity sha512-kfiDrDQ+PBsQDO85yj1icueWMfGfJFKN1KCkndygtu/C9+XUfydLC8Iv5UYJqRwy4zk8EcplRxEOeLyjq1gm6Q== +"@babel/plugin-transform-sticky-regex@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.24.7.tgz#96ae80d7a7e5251f657b5cf18f1ea6bf926f5feb" + integrity sha512-kHPSIJc9v24zEml5geKg9Mjx5ULpfncj0wRpYtxbvKyTtHCYDkVE3aHQ03FrpEo4gEe2vrJJS1Y9CJTaThA52g== dependencies: - "@babel/helper-plugin-utils" "^7.18.6" + "@babel/helper-plugin-utils" "^7.24.7" -"@babel/plugin-transform-template-literals@^7.18.9": - version "7.18.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.18.9.tgz#04ec6f10acdaa81846689d63fae117dd9c243a5e" - integrity sha512-S8cOWfT82gTezpYOiVaGHrCbhlHgKhQt8XH5ES46P2XWmX92yisoZywf5km75wv5sYcXDUCLMmMxOLCtthDgMA== +"@babel/plugin-transform-template-literals@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.24.7.tgz#a05debb4a9072ae8f985bcf77f3f215434c8f8c8" + integrity sha512-AfDTQmClklHCOLxtGoP7HkeMw56k1/bTQjwsfhL6pppo/M4TOBSq+jjBUBLmV/4oeFg4GWMavIl44ZeCtmmZTw== dependencies: - "@babel/helper-plugin-utils" "^7.18.9" + "@babel/helper-plugin-utils" "^7.24.7" -"@babel/plugin-transform-typeof-symbol@^7.18.9": - version "7.18.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.18.9.tgz#c8cea68263e45addcd6afc9091429f80925762c0" - integrity sha512-SRfwTtF11G2aemAZWivL7PD+C9z52v9EvMqH9BuYbabyPuKUvSWks3oCg6041pT925L4zVFqaVBeECwsmlguEw== +"@babel/plugin-transform-typeof-symbol@^7.24.8": + version "7.24.8" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.24.8.tgz#383dab37fb073f5bfe6e60c654caac309f92ba1c" + integrity sha512-adNTUpDCVnmAE58VEqKlAA6ZBlNkMnWD0ZcW76lyNFN3MJniyGFZfNwERVk8Ap56MCnXztmDr19T4mPTztcuaw== dependencies: - "@babel/helper-plugin-utils" "^7.18.9" + "@babel/helper-plugin-utils" "^7.24.8" -"@babel/plugin-transform-typescript@^7.18.6": - version "7.20.2" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.20.2.tgz#91515527b376fc122ba83b13d70b01af8fe98f3f" - integrity sha512-jvS+ngBfrnTUBfOQq8NfGnSbF9BrqlR6hjJ2yVxMkmO5nL/cdifNbI30EfjRlN4g5wYWNnMPyj5Sa6R1pbLeag== +"@babel/plugin-transform-typescript@^7.24.7": + version "7.24.8" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.24.8.tgz#c104d6286e04bf7e44b8cba1b686d41bad57eb84" + integrity sha512-CgFgtN61BbdOGCP4fLaAMOPkzWUh6yQZNMr5YSt8uz2cZSSiQONCQFWqsE4NeVfOIhqDOlS9CR3WD91FzMeB2Q== dependencies: - "@babel/helper-create-class-features-plugin" "^7.20.2" - "@babel/helper-plugin-utils" "^7.20.2" - "@babel/plugin-syntax-typescript" "^7.20.0" + "@babel/helper-annotate-as-pure" "^7.24.7" + "@babel/helper-create-class-features-plugin" "^7.24.8" + "@babel/helper-plugin-utils" "^7.24.8" + "@babel/plugin-syntax-typescript" "^7.24.7" -"@babel/plugin-transform-unicode-escapes@^7.18.10": - version "7.18.10" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.18.10.tgz#1ecfb0eda83d09bbcb77c09970c2dd55832aa246" - integrity sha512-kKAdAI+YzPgGY/ftStBFXTI1LZFju38rYThnfMykS+IXy8BVx+res7s2fxf1l8I35DV2T97ezo6+SGrXz6B3iQ== +"@babel/plugin-transform-unicode-escapes@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.24.7.tgz#2023a82ced1fb4971630a2e079764502c4148e0e" + integrity sha512-U3ap1gm5+4edc2Q/P+9VrBNhGkfnf+8ZqppY71Bo/pzZmXhhLdqgaUl6cuB07O1+AQJtCLfaOmswiNbSQ9ivhw== dependencies: - "@babel/helper-plugin-utils" "^7.18.9" + "@babel/helper-plugin-utils" "^7.24.7" -"@babel/plugin-transform-unicode-regex@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.18.6.tgz#194317225d8c201bbae103364ffe9e2cea36cdca" - integrity sha512-gE7A6Lt7YLnNOL3Pb9BNeZvi+d8l7tcRrG4+pwJjK9hD2xX4mEvjlQW60G9EEmfXVYRPv9VRQcyegIVHCql/AA== +"@babel/plugin-transform-unicode-property-regex@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.24.7.tgz#9073a4cd13b86ea71c3264659590ac086605bbcd" + integrity sha512-uH2O4OV5M9FZYQrwc7NdVmMxQJOCCzFeYudlZSzUAHRFeOujQefa92E74TQDVskNHCzOXoigEuoyzHDhaEaK5w== dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.18.6" - "@babel/helper-plugin-utils" "^7.18.6" + "@babel/helper-create-regexp-features-plugin" "^7.24.7" + "@babel/helper-plugin-utils" "^7.24.7" + +"@babel/plugin-transform-unicode-regex@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.24.7.tgz#dfc3d4a51127108099b19817c0963be6a2adf19f" + integrity sha512-hlQ96MBZSAXUq7ltkjtu3FJCCSMx/j629ns3hA3pXnBXjanNP0LHi+JpPeA81zaWgVK1VGH95Xuy7u0RyQ8kMg== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.24.7" + "@babel/helper-plugin-utils" "^7.24.7" + +"@babel/plugin-transform-unicode-sets-regex@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.24.7.tgz#d40705d67523803a576e29c63cef6e516b858ed9" + integrity sha512-2G8aAvF4wy1w/AGZkemprdGMRg5o6zPNhbHVImRz3lss55TYCBd6xStN19rt8XJHq20sqV0JbyWjOWwQRwV/wg== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.24.7" + "@babel/helper-plugin-utils" "^7.24.7" "@babel/preset-env@^7.18.6", "@babel/preset-env@^7.19.4": - version "7.20.2" - resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.20.2.tgz#9b1642aa47bb9f43a86f9630011780dab7f86506" - integrity sha512-1G0efQEWR1EHkKvKHqbG+IN/QdgwfByUpM5V5QroDzGV2t3S/WXNQd693cHiHTlCFMpr9B6FkPFXDA2lQcKoDg== - dependencies: - "@babel/compat-data" "^7.20.1" - "@babel/helper-compilation-targets" "^7.20.0" - "@babel/helper-plugin-utils" "^7.20.2" - "@babel/helper-validator-option" "^7.18.6" - "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression" "^7.18.6" - "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining" "^7.18.9" - "@babel/plugin-proposal-async-generator-functions" "^7.20.1" - "@babel/plugin-proposal-class-properties" "^7.18.6" - "@babel/plugin-proposal-class-static-block" "^7.18.6" - "@babel/plugin-proposal-dynamic-import" "^7.18.6" - "@babel/plugin-proposal-export-namespace-from" "^7.18.9" - "@babel/plugin-proposal-json-strings" "^7.18.6" - "@babel/plugin-proposal-logical-assignment-operators" "^7.18.9" - "@babel/plugin-proposal-nullish-coalescing-operator" "^7.18.6" - "@babel/plugin-proposal-numeric-separator" "^7.18.6" - "@babel/plugin-proposal-object-rest-spread" "^7.20.2" - "@babel/plugin-proposal-optional-catch-binding" "^7.18.6" - "@babel/plugin-proposal-optional-chaining" "^7.18.9" - "@babel/plugin-proposal-private-methods" "^7.18.6" - "@babel/plugin-proposal-private-property-in-object" "^7.18.6" - "@babel/plugin-proposal-unicode-property-regex" "^7.18.6" + version "7.24.8" + resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.24.8.tgz#e0db94d7f17d6f0e2564e8d29190bc8cdacec2d1" + integrity sha512-vObvMZB6hNWuDxhSaEPTKCwcqkAIuDtE+bQGn4XMXne1DSLzFVY8Vmj1bm+mUQXYNN8NmaQEO+r8MMbzPr1jBQ== + dependencies: + "@babel/compat-data" "^7.24.8" + "@babel/helper-compilation-targets" "^7.24.8" + "@babel/helper-plugin-utils" "^7.24.8" + "@babel/helper-validator-option" "^7.24.8" + "@babel/plugin-bugfix-firefox-class-in-computed-class-key" "^7.24.7" + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression" "^7.24.7" + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining" "^7.24.7" + "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly" "^7.24.7" + "@babel/plugin-proposal-private-property-in-object" "7.21.0-placeholder-for-preset-env.2" "@babel/plugin-syntax-async-generators" "^7.8.4" "@babel/plugin-syntax-class-properties" "^7.12.13" "@babel/plugin-syntax-class-static-block" "^7.14.5" "@babel/plugin-syntax-dynamic-import" "^7.8.3" "@babel/plugin-syntax-export-namespace-from" "^7.8.3" - "@babel/plugin-syntax-import-assertions" "^7.20.0" + "@babel/plugin-syntax-import-assertions" "^7.24.7" + "@babel/plugin-syntax-import-attributes" "^7.24.7" + "@babel/plugin-syntax-import-meta" "^7.10.4" "@babel/plugin-syntax-json-strings" "^7.8.3" "@babel/plugin-syntax-logical-assignment-operators" "^7.10.4" "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.3" @@ -1061,125 +1126,146 @@ "@babel/plugin-syntax-optional-chaining" "^7.8.3" "@babel/plugin-syntax-private-property-in-object" "^7.14.5" "@babel/plugin-syntax-top-level-await" "^7.14.5" - "@babel/plugin-transform-arrow-functions" "^7.18.6" - "@babel/plugin-transform-async-to-generator" "^7.18.6" - "@babel/plugin-transform-block-scoped-functions" "^7.18.6" - "@babel/plugin-transform-block-scoping" "^7.20.2" - "@babel/plugin-transform-classes" "^7.20.2" - "@babel/plugin-transform-computed-properties" "^7.18.9" - "@babel/plugin-transform-destructuring" "^7.20.2" - "@babel/plugin-transform-dotall-regex" "^7.18.6" - "@babel/plugin-transform-duplicate-keys" "^7.18.9" - "@babel/plugin-transform-exponentiation-operator" "^7.18.6" - "@babel/plugin-transform-for-of" "^7.18.8" - "@babel/plugin-transform-function-name" "^7.18.9" - "@babel/plugin-transform-literals" "^7.18.9" - "@babel/plugin-transform-member-expression-literals" "^7.18.6" - "@babel/plugin-transform-modules-amd" "^7.19.6" - "@babel/plugin-transform-modules-commonjs" "^7.19.6" - "@babel/plugin-transform-modules-systemjs" "^7.19.6" - "@babel/plugin-transform-modules-umd" "^7.18.6" - "@babel/plugin-transform-named-capturing-groups-regex" "^7.19.1" - "@babel/plugin-transform-new-target" "^7.18.6" - "@babel/plugin-transform-object-super" "^7.18.6" - "@babel/plugin-transform-parameters" "^7.20.1" - "@babel/plugin-transform-property-literals" "^7.18.6" - "@babel/plugin-transform-regenerator" "^7.18.6" - "@babel/plugin-transform-reserved-words" "^7.18.6" - "@babel/plugin-transform-shorthand-properties" "^7.18.6" - "@babel/plugin-transform-spread" "^7.19.0" - "@babel/plugin-transform-sticky-regex" "^7.18.6" - "@babel/plugin-transform-template-literals" "^7.18.9" - "@babel/plugin-transform-typeof-symbol" "^7.18.9" - "@babel/plugin-transform-unicode-escapes" "^7.18.10" - "@babel/plugin-transform-unicode-regex" "^7.18.6" - "@babel/preset-modules" "^0.1.5" - "@babel/types" "^7.20.2" - babel-plugin-polyfill-corejs2 "^0.3.3" - babel-plugin-polyfill-corejs3 "^0.6.0" - babel-plugin-polyfill-regenerator "^0.4.1" - core-js-compat "^3.25.1" - semver "^6.3.0" - -"@babel/preset-modules@^0.1.5": - version "0.1.5" - resolved "https://registry.yarnpkg.com/@babel/preset-modules/-/preset-modules-0.1.5.tgz#ef939d6e7f268827e1841638dc6ff95515e115d9" - integrity sha512-A57th6YRG7oR3cq/yt/Y84MvGgE0eJG2F1JLhKuyG+jFxEgrd/HAMJatiFtmOiZurz+0DkrvbheCLaV5f2JfjA== + "@babel/plugin-syntax-unicode-sets-regex" "^7.18.6" + "@babel/plugin-transform-arrow-functions" "^7.24.7" + "@babel/plugin-transform-async-generator-functions" "^7.24.7" + "@babel/plugin-transform-async-to-generator" "^7.24.7" + "@babel/plugin-transform-block-scoped-functions" "^7.24.7" + "@babel/plugin-transform-block-scoping" "^7.24.7" + "@babel/plugin-transform-class-properties" "^7.24.7" + "@babel/plugin-transform-class-static-block" "^7.24.7" + "@babel/plugin-transform-classes" "^7.24.8" + "@babel/plugin-transform-computed-properties" "^7.24.7" + "@babel/plugin-transform-destructuring" "^7.24.8" + "@babel/plugin-transform-dotall-regex" "^7.24.7" + "@babel/plugin-transform-duplicate-keys" "^7.24.7" + "@babel/plugin-transform-dynamic-import" "^7.24.7" + "@babel/plugin-transform-exponentiation-operator" "^7.24.7" + "@babel/plugin-transform-export-namespace-from" "^7.24.7" + "@babel/plugin-transform-for-of" "^7.24.7" + "@babel/plugin-transform-function-name" "^7.24.7" + "@babel/plugin-transform-json-strings" "^7.24.7" + "@babel/plugin-transform-literals" "^7.24.7" + "@babel/plugin-transform-logical-assignment-operators" "^7.24.7" + "@babel/plugin-transform-member-expression-literals" "^7.24.7" + "@babel/plugin-transform-modules-amd" "^7.24.7" + "@babel/plugin-transform-modules-commonjs" "^7.24.8" + "@babel/plugin-transform-modules-systemjs" "^7.24.7" + "@babel/plugin-transform-modules-umd" "^7.24.7" + "@babel/plugin-transform-named-capturing-groups-regex" "^7.24.7" + "@babel/plugin-transform-new-target" "^7.24.7" + "@babel/plugin-transform-nullish-coalescing-operator" "^7.24.7" + "@babel/plugin-transform-numeric-separator" "^7.24.7" + "@babel/plugin-transform-object-rest-spread" "^7.24.7" + "@babel/plugin-transform-object-super" "^7.24.7" + "@babel/plugin-transform-optional-catch-binding" "^7.24.7" + "@babel/plugin-transform-optional-chaining" "^7.24.8" + "@babel/plugin-transform-parameters" "^7.24.7" + "@babel/plugin-transform-private-methods" "^7.24.7" + "@babel/plugin-transform-private-property-in-object" "^7.24.7" + "@babel/plugin-transform-property-literals" "^7.24.7" + "@babel/plugin-transform-regenerator" "^7.24.7" + "@babel/plugin-transform-reserved-words" "^7.24.7" + "@babel/plugin-transform-shorthand-properties" "^7.24.7" + "@babel/plugin-transform-spread" "^7.24.7" + "@babel/plugin-transform-sticky-regex" "^7.24.7" + "@babel/plugin-transform-template-literals" "^7.24.7" + "@babel/plugin-transform-typeof-symbol" "^7.24.8" + "@babel/plugin-transform-unicode-escapes" "^7.24.7" + "@babel/plugin-transform-unicode-property-regex" "^7.24.7" + "@babel/plugin-transform-unicode-regex" "^7.24.7" + "@babel/plugin-transform-unicode-sets-regex" "^7.24.7" + "@babel/preset-modules" "0.1.6-no-external-plugins" + babel-plugin-polyfill-corejs2 "^0.4.10" + babel-plugin-polyfill-corejs3 "^0.10.4" + babel-plugin-polyfill-regenerator "^0.6.1" + core-js-compat "^3.37.1" + semver "^6.3.1" + +"@babel/preset-modules@0.1.6-no-external-plugins": + version "0.1.6-no-external-plugins" + resolved "https://registry.yarnpkg.com/@babel/preset-modules/-/preset-modules-0.1.6-no-external-plugins.tgz#ccb88a2c49c817236861fee7826080573b8a923a" + integrity sha512-HrcgcIESLm9aIR842yhJ5RWan/gebQUJ6E/E5+rf0y9o6oj7w0Br+sWuL6kEQ/o/AdfvR1Je9jG18/gnpwjEyA== dependencies: "@babel/helper-plugin-utils" "^7.0.0" - "@babel/plugin-proposal-unicode-property-regex" "^7.4.4" - "@babel/plugin-transform-dotall-regex" "^7.4.4" "@babel/types" "^7.4.4" esutils "^2.0.2" "@babel/preset-react@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/preset-react/-/preset-react-7.18.6.tgz#979f76d6277048dc19094c217b507f3ad517dd2d" - integrity sha512-zXr6atUmyYdiWRVLOZahakYmOBHtWc2WGCkP8PYTgZi0iJXDY2CN180TdrIW4OGOAdLc7TifzDIvtx6izaRIzg== + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/preset-react/-/preset-react-7.24.7.tgz#480aeb389b2a798880bf1f889199e3641cbb22dc" + integrity sha512-AAH4lEkpmzFWrGVlHaxJB7RLH21uPQ9+He+eFLWHmF9IuFQVugz8eAsamaW0DXRrTfco5zj1wWtpdcXJUOfsag== dependencies: - "@babel/helper-plugin-utils" "^7.18.6" - "@babel/helper-validator-option" "^7.18.6" - "@babel/plugin-transform-react-display-name" "^7.18.6" - "@babel/plugin-transform-react-jsx" "^7.18.6" - "@babel/plugin-transform-react-jsx-development" "^7.18.6" - "@babel/plugin-transform-react-pure-annotations" "^7.18.6" + "@babel/helper-plugin-utils" "^7.24.7" + "@babel/helper-validator-option" "^7.24.7" + "@babel/plugin-transform-react-display-name" "^7.24.7" + "@babel/plugin-transform-react-jsx" "^7.24.7" + "@babel/plugin-transform-react-jsx-development" "^7.24.7" + "@babel/plugin-transform-react-pure-annotations" "^7.24.7" "@babel/preset-typescript@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/preset-typescript/-/preset-typescript-7.18.6.tgz#ce64be3e63eddc44240c6358daefac17b3186399" - integrity sha512-s9ik86kXBAnD760aybBucdpnLsAt0jK1xqJn2juOn9lkOvSHV60os5hxoVJsPzMQxvnUJFAlkont2DvvaYEBtQ== + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/preset-typescript/-/preset-typescript-7.24.7.tgz#66cd86ea8f8c014855671d5ea9a737139cbbfef1" + integrity sha512-SyXRe3OdWwIwalxDg5UtJnJQO+YPcTfwiIY2B0Xlddh9o7jpWLvv8X1RthIeDOxQ+O1ML5BLPCONToObyVQVuQ== dependencies: - "@babel/helper-plugin-utils" "^7.18.6" - "@babel/helper-validator-option" "^7.18.6" - "@babel/plugin-transform-typescript" "^7.18.6" + "@babel/helper-plugin-utils" "^7.24.7" + "@babel/helper-validator-option" "^7.24.7" + "@babel/plugin-syntax-jsx" "^7.24.7" + "@babel/plugin-transform-modules-commonjs" "^7.24.7" + "@babel/plugin-transform-typescript" "^7.24.7" + +"@babel/regjsgen@^0.8.0": + version "0.8.0" + resolved "https://registry.yarnpkg.com/@babel/regjsgen/-/regjsgen-0.8.0.tgz#f0ba69b075e1f05fb2825b7fad991e7adbb18310" + integrity sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA== "@babel/runtime-corejs3@^7.18.6": - version "7.20.1" - resolved "https://registry.yarnpkg.com/@babel/runtime-corejs3/-/runtime-corejs3-7.20.1.tgz#d0775a49bb5fba77e42cbb7276c9955c7b05af8d" - integrity sha512-CGulbEDcg/ND1Im7fUNRZdGXmX2MTWVVZacQi/6DiKE5HNwZ3aVTm5PV4lO8HHz0B2h8WQyvKKjbX5XgTtydsg== - dependencies: - core-js-pure "^3.25.1" - regenerator-runtime "^0.13.10" - -"@babel/runtime@^7.1.2", "@babel/runtime@^7.10.2", "@babel/runtime@^7.10.3", "@babel/runtime@^7.12.13", "@babel/runtime@^7.12.5", "@babel/runtime@^7.18.6", "@babel/runtime@^7.8.4": - version "7.20.1" - resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.20.1.tgz#1148bb33ab252b165a06698fde7576092a78b4a9" - integrity sha512-mrzLkl6U9YLF8qpqI7TB82PESyEGjm/0Ly91jG575eVxMMlb8fYfOXFZIJ8XfLrJZQbm7dlKry2bJmXBUEkdFg== - dependencies: - regenerator-runtime "^0.13.10" - -"@babel/template@^7.12.7", "@babel/template@^7.18.10": - version "7.18.10" - resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.18.10.tgz#6f9134835970d1dbf0835c0d100c9f38de0c5e71" - integrity sha512-TI+rCtooWHr3QJ27kJxfjutghu44DLnasDMwpDqCXVTal9RLp3RSYNh4NdBrRP2cQAoG9A8juOQl6P6oZG4JxA== - dependencies: - "@babel/code-frame" "^7.18.6" - "@babel/parser" "^7.18.10" - "@babel/types" "^7.18.10" - -"@babel/traverse@^7.12.9", "@babel/traverse@^7.18.8", "@babel/traverse@^7.19.0", "@babel/traverse@^7.19.1", "@babel/traverse@^7.20.1": - version "7.20.1" - resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.20.1.tgz#9b15ccbf882f6d107eeeecf263fbcdd208777ec8" - integrity sha512-d3tN8fkVJwFLkHkBN479SOsw4DMZnz8cdbL/gvuDuzy3TS6Nfw80HuQqhw1pITbIruHyh7d1fMA47kWzmcUEGA== - dependencies: - "@babel/code-frame" "^7.18.6" - "@babel/generator" "^7.20.1" - "@babel/helper-environment-visitor" "^7.18.9" - "@babel/helper-function-name" "^7.19.0" - "@babel/helper-hoist-variables" "^7.18.6" - "@babel/helper-split-export-declaration" "^7.18.6" - "@babel/parser" "^7.20.1" - "@babel/types" "^7.20.0" - debug "^4.1.0" + version "7.24.8" + resolved "https://registry.yarnpkg.com/@babel/runtime-corejs3/-/runtime-corejs3-7.24.8.tgz#c0ae5a1c380f8442920866d0cc51de8024507e28" + integrity sha512-DXG/BhegtMHhnN7YPIvxWd303/9aXvYFD1TjNL3CD6tUrhI2LVsg3Lck0aql5TRH29n4sj3emcROypkZVUfSuA== + dependencies: + core-js-pure "^3.30.2" + regenerator-runtime "^0.14.0" + +"@babel/runtime@^7.1.2", "@babel/runtime@^7.10.3", "@babel/runtime@^7.12.13", "@babel/runtime@^7.12.5", "@babel/runtime@^7.18.6", "@babel/runtime@^7.20.13", "@babel/runtime@^7.8.4": + version "7.24.8" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.24.8.tgz#5d958c3827b13cc6d05e038c07fb2e5e3420d82e" + integrity sha512-5F7SDGs1T72ZczbRwbGO9lQi0NLjQxzl6i4lJxLxfW9U5UluCSyEJeniWvnhl3/euNiqQVbo8zruhsDfid0esA== + dependencies: + regenerator-runtime "^0.14.0" + +"@babel/template@^7.12.7", "@babel/template@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.24.7.tgz#02efcee317d0609d2c07117cb70ef8fb17ab7315" + integrity sha512-jYqfPrU9JTF0PmPy1tLYHW4Mp4KlgxJD9l2nP9fD6yT/ICi554DmrWBAEYpIelzjHf1msDP3PxJIRt/nFNfBig== + dependencies: + "@babel/code-frame" "^7.24.7" + "@babel/parser" "^7.24.7" + "@babel/types" "^7.24.7" + +"@babel/traverse@^7.12.9", "@babel/traverse@^7.18.8", "@babel/traverse@^7.24.7", "@babel/traverse@^7.24.8": + version "7.24.8" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.24.8.tgz#6c14ed5232b7549df3371d820fbd9abfcd7dfab7" + integrity sha512-t0P1xxAPzEDcEPmjprAQq19NWum4K0EQPjMwZQZbHt+GiZqvjCHjj755Weq1YRPVzBI+3zSfvScfpnuIecVFJQ== + dependencies: + "@babel/code-frame" "^7.24.7" + "@babel/generator" "^7.24.8" + "@babel/helper-environment-visitor" "^7.24.7" + "@babel/helper-function-name" "^7.24.7" + "@babel/helper-hoist-variables" "^7.24.7" + "@babel/helper-split-export-declaration" "^7.24.7" + "@babel/parser" "^7.24.8" + "@babel/types" "^7.24.8" + debug "^4.3.1" globals "^11.1.0" -"@babel/types@^7.12.7", "@babel/types@^7.16.7", "@babel/types@^7.18.10", "@babel/types@^7.18.6", "@babel/types@^7.18.9", "@babel/types@^7.19.0", "@babel/types@^7.20.0", "@babel/types@^7.20.2", "@babel/types@^7.4.4": - version "7.20.2" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.20.2.tgz#67ac09266606190f496322dbaff360fdaa5e7842" - integrity sha512-FnnvsNWgZCr232sqtXggapvlkk/tuwR/qhGzcmxI0GXLCjmPYQPzio2FbdlWuY6y1sHFfQKk+rRbUZ9VStQMog== +"@babel/types@^7.12.7", "@babel/types@^7.16.7", "@babel/types@^7.20.0", "@babel/types@^7.24.7", "@babel/types@^7.24.8", "@babel/types@^7.24.9", "@babel/types@^7.4.4": + version "7.24.9" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.24.9.tgz#228ce953d7b0d16646e755acf204f4cf3d08cc73" + integrity sha512-xm8XrMKz0IlUdocVbYJe0Z9xEgidU7msskG8BbhnTPK/HZ2z/7FP7ykqPgrUH+C+r414mNfNWam1f2vqOjqjYQ== dependencies: - "@babel/helper-string-parser" "^7.19.4" - "@babel/helper-validator-identifier" "^7.19.1" + "@babel/helper-string-parser" "^7.24.8" + "@babel/helper-validator-identifier" "^7.24.7" to-fast-properties "^2.0.0" "@colors/colors@1.5.0": @@ -1187,99 +1273,27 @@ resolved "https://registry.yarnpkg.com/@colors/colors/-/colors-1.5.0.tgz#bb504579c1cae923e6576a4f5da43d25f97bdbd9" integrity sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ== -"@docsearch/css@3.3.0": - version "3.3.0" - resolved "https://registry.yarnpkg.com/@docsearch/css/-/css-3.3.0.tgz#d698e48302d12240d7c2f7452ccb2d2239a8cd80" - integrity sha512-rODCdDtGyudLj+Va8b6w6Y85KE85bXRsps/R4Yjwt5vueXKXZQKYw0aA9knxLBT6a/bI/GMrAcmCR75KYOM6hg== +"@discoveryjs/json-ext@0.5.7": + version "0.5.7" + resolved "https://registry.yarnpkg.com/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz#1d572bfbbe14b7704e0ba0f39b74815b84870d70" + integrity sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw== -"@docsearch/react@^3.1.1": - version "3.3.0" - resolved "https://registry.yarnpkg.com/@docsearch/react/-/react-3.3.0.tgz#b8ac8e7f49b9bf2f96d34c24bc1cfd097ec0eead" - integrity sha512-fhS5adZkae2SSdMYEMVg6pxI5a/cE+tW16ki1V0/ur4Fdok3hBRkmN/H8VvlXnxzggkQIIRIVvYPn00JPjen3A== - dependencies: - "@algolia/autocomplete-core" "1.7.2" - "@algolia/autocomplete-preset-algolia" "1.7.2" - "@docsearch/css" "3.3.0" - algoliasearch "^4.0.0" +"@docsearch/css@3.6.1": + version "3.6.1" + resolved "https://registry.yarnpkg.com/@docsearch/css/-/css-3.6.1.tgz#f0a728ecb486c81f2d282650fc1820c914913408" + integrity sha512-VtVb5DS+0hRIprU2CO6ZQjK2Zg4QU5HrDM1+ix6rT0umsYvFvatMAnf97NHZlVWDaaLlx7GRfR/7FikANiM2Fg== -"@docusaurus/core@2.2.0", "@docusaurus/core@^2.0.0-beta.15": - version "2.2.0" - resolved "https://registry.yarnpkg.com/@docusaurus/core/-/core-2.2.0.tgz#64c9ee31502c23b93c869f8188f73afaf5fd4867" - integrity sha512-Vd6XOluKQqzG12fEs9prJgDtyn6DPok9vmUWDR2E6/nV5Fl9SVkhEQOBxwObjk3kQh7OY7vguFaLh0jqdApWsA== +"@docsearch/react@^3.1.1": + version "3.6.1" + resolved "https://registry.yarnpkg.com/@docsearch/react/-/react-3.6.1.tgz#0f826df08693293806d64277d6d9c38636211b97" + integrity sha512-qXZkEPvybVhSXj0K7U3bXc233tk5e8PfhoZ6MhPOiik/qUQxYC+Dn9DnoS7CxHQQhHfCvTiN0eY9M12oRghEXw== dependencies: - "@babel/core" "^7.18.6" - "@babel/generator" "^7.18.7" - "@babel/plugin-syntax-dynamic-import" "^7.8.3" - "@babel/plugin-transform-runtime" "^7.18.6" - "@babel/preset-env" "^7.18.6" - "@babel/preset-react" "^7.18.6" - "@babel/preset-typescript" "^7.18.6" - "@babel/runtime" "^7.18.6" - "@babel/runtime-corejs3" "^7.18.6" - "@babel/traverse" "^7.18.8" - "@docusaurus/cssnano-preset" "2.2.0" - "@docusaurus/logger" "2.2.0" - "@docusaurus/mdx-loader" "2.2.0" - "@docusaurus/react-loadable" "5.5.2" - "@docusaurus/utils" "2.2.0" - "@docusaurus/utils-common" "2.2.0" - "@docusaurus/utils-validation" "2.2.0" - "@slorber/static-site-generator-webpack-plugin" "^4.0.7" - "@svgr/webpack" "^6.2.1" - autoprefixer "^10.4.7" - babel-loader "^8.2.5" - babel-plugin-dynamic-import-node "^2.3.3" - boxen "^6.2.1" - chalk "^4.1.2" - chokidar "^3.5.3" - clean-css "^5.3.0" - cli-table3 "^0.6.2" - combine-promises "^1.1.0" - commander "^5.1.0" - copy-webpack-plugin "^11.0.0" - core-js "^3.23.3" - css-loader "^6.7.1" - css-minimizer-webpack-plugin "^4.0.0" - cssnano "^5.1.12" - del "^6.1.1" - detect-port "^1.3.0" - escape-html "^1.0.3" - eta "^1.12.3" - file-loader "^6.2.0" - fs-extra "^10.1.0" - html-minifier-terser "^6.1.0" - html-tags "^3.2.0" - html-webpack-plugin "^5.5.0" - import-fresh "^3.3.0" - leven "^3.1.0" - lodash "^4.17.21" - mini-css-extract-plugin "^2.6.1" - postcss "^8.4.14" - postcss-loader "^7.0.0" - prompts "^2.4.2" - react-dev-utils "^12.0.1" - react-helmet-async "^1.3.0" - react-loadable "npm:@docusaurus/react-loadable@5.5.2" - react-loadable-ssr-addon-v5-slorber "^1.0.1" - react-router "^5.3.3" - react-router-config "^5.1.1" - react-router-dom "^5.3.3" - rtl-detect "^1.0.4" - semver "^7.3.7" - serve-handler "^6.1.3" - shelljs "^0.8.5" - terser-webpack-plugin "^5.3.3" - tslib "^2.4.0" - update-notifier "^5.1.0" - url-loader "^4.1.1" - wait-on "^6.0.1" - webpack "^5.73.0" - webpack-bundle-analyzer "^4.5.0" - webpack-dev-server "^4.9.3" - webpack-merge "^5.8.0" - webpackbar "^5.0.2" + "@algolia/autocomplete-core" "1.9.3" + "@algolia/autocomplete-preset-algolia" "1.9.3" + "@docsearch/css" "3.6.1" + algoliasearch "^4.19.1" -"@docusaurus/core@2.4.3": +"@docusaurus/core@2.4.3", "@docusaurus/core@^2.4.3": version "2.4.3" resolved "https://registry.yarnpkg.com/@docusaurus/core/-/core-2.4.3.tgz#d86624901386fd8164ce4bff9cc7f16fde57f523" integrity sha512-dWH5P7cgeNSIg9ufReX6gaCl/TmrGKD38Orbwuz05WPhAQtFXHd5B8Qym1TiXfvUNvwoYKkAJOJuGe8ou0Z7PA== @@ -1353,18 +1367,8 @@ webpack "^5.73.0" webpack-bundle-analyzer "^4.5.0" webpack-dev-server "^4.9.3" - webpack-merge "^5.8.0" - webpackbar "^5.0.2" - -"@docusaurus/cssnano-preset@2.2.0": - version "2.2.0" - resolved "https://registry.yarnpkg.com/@docusaurus/cssnano-preset/-/cssnano-preset-2.2.0.tgz#fc05044659051ae74ab4482afcf4a9936e81d523" - integrity sha512-mAAwCo4n66TMWBH1kXnHVZsakW9VAXJzTO4yZukuL3ro4F+JtkMwKfh42EG75K/J/YIFQG5I/Bzy0UH/hFxaTg== - dependencies: - cssnano-preset-advanced "^5.3.8" - postcss "^8.4.14" - postcss-sort-media-queries "^4.2.1" - tslib "^2.4.0" + webpack-merge "^5.8.0" + webpackbar "^5.0.2" "@docusaurus/cssnano-preset@2.4.3": version "2.4.3" @@ -1376,14 +1380,6 @@ postcss-sort-media-queries "^4.2.1" tslib "^2.4.0" -"@docusaurus/logger@2.2.0": - version "2.2.0" - resolved "https://registry.yarnpkg.com/@docusaurus/logger/-/logger-2.2.0.tgz#ea2f7feda7b8675485933b87f06d9c976d17423f" - integrity sha512-DF3j1cA5y2nNsu/vk8AG7xwpZu6f5MKkPPMaaIbgXLnWGfm6+wkOeW7kNrxnM95YOhKUkJUophX69nGUnLsm0A== - dependencies: - chalk "^4.1.2" - tslib "^2.4.0" - "@docusaurus/logger@2.4.3": version "2.4.3" resolved "https://registry.yarnpkg.com/@docusaurus/logger/-/logger-2.4.3.tgz#518bbc965fb4ebe8f1d0b14e5f4161607552d34c" @@ -1392,29 +1388,6 @@ chalk "^4.1.2" tslib "^2.4.0" -"@docusaurus/mdx-loader@2.2.0": - version "2.2.0" - resolved "https://registry.yarnpkg.com/@docusaurus/mdx-loader/-/mdx-loader-2.2.0.tgz#fd558f429e5d9403d284bd4214e54d9768b041a0" - integrity sha512-X2bzo3T0jW0VhUU+XdQofcEeozXOTmKQMvc8tUnWRdTnCvj4XEcBVdC3g+/jftceluiwSTNRAX4VBOJdNt18jA== - dependencies: - "@babel/parser" "^7.18.8" - "@babel/traverse" "^7.18.8" - "@docusaurus/logger" "2.2.0" - "@docusaurus/utils" "2.2.0" - "@mdx-js/mdx" "^1.6.22" - escape-html "^1.0.3" - file-loader "^6.2.0" - fs-extra "^10.1.0" - image-size "^1.0.1" - mdast-util-to-string "^2.0.0" - remark-emoji "^2.2.0" - stringify-object "^3.3.0" - tslib "^2.4.0" - unified "^9.2.2" - unist-util-visit "^2.0.3" - url-loader "^4.1.1" - webpack "^5.73.0" - "@docusaurus/mdx-loader@2.4.3": version "2.4.3" resolved "https://registry.yarnpkg.com/@docusaurus/mdx-loader/-/mdx-loader-2.4.3.tgz#e8ff37f30a060eaa97b8121c135f74cb531a4a3e" @@ -1438,13 +1411,13 @@ url-loader "^4.1.1" webpack "^5.73.0" -"@docusaurus/module-type-aliases@2.2.0": - version "2.2.0" - resolved "https://registry.yarnpkg.com/@docusaurus/module-type-aliases/-/module-type-aliases-2.2.0.tgz#1e23e54a1bbb6fde1961e4fa395b1b69f4803ba5" - integrity sha512-wDGW4IHKoOr9YuJgy7uYuKWrDrSpsUSDHLZnWQYM9fN7D5EpSmYHjFruUpKWVyxLpD/Wh0rW8hYZwdjJIQUQCQ== +"@docusaurus/module-type-aliases@2.4.3": + version "2.4.3" + resolved "https://registry.yarnpkg.com/@docusaurus/module-type-aliases/-/module-type-aliases-2.4.3.tgz#d08ef67e4151e02f352a2836bcf9ecde3b9c56ac" + integrity sha512-cwkBkt1UCiduuvEAo7XZY01dJfRn7UR/75mBgOdb1hKknhrabJZ8YH+7savd/y9kLExPyrhe0QwdS9GuzsRRIA== dependencies: "@docusaurus/react-loadable" "5.5.2" - "@docusaurus/types" "2.2.0" + "@docusaurus/types" "2.4.3" "@types/history" "^4.7.11" "@types/react" "*" "@types/react-router-config" "*" @@ -1452,18 +1425,18 @@ react-helmet-async "*" react-loadable "npm:@docusaurus/react-loadable@5.5.2" -"@docusaurus/plugin-content-blog@2.2.0": - version "2.2.0" - resolved "https://registry.yarnpkg.com/@docusaurus/plugin-content-blog/-/plugin-content-blog-2.2.0.tgz#dc55982e76771f4e678ac10e26d10e1da2011dc1" - integrity sha512-0mWBinEh0a5J2+8ZJXJXbrCk1tSTNf7Nm4tYAl5h2/xx+PvH/Bnu0V+7mMljYm/1QlDYALNIIaT/JcoZQFUN3w== - dependencies: - "@docusaurus/core" "2.2.0" - "@docusaurus/logger" "2.2.0" - "@docusaurus/mdx-loader" "2.2.0" - "@docusaurus/types" "2.2.0" - "@docusaurus/utils" "2.2.0" - "@docusaurus/utils-common" "2.2.0" - "@docusaurus/utils-validation" "2.2.0" +"@docusaurus/plugin-content-blog@2.4.3": + version "2.4.3" + resolved "https://registry.yarnpkg.com/@docusaurus/plugin-content-blog/-/plugin-content-blog-2.4.3.tgz#6473b974acab98e967414d8bbb0d37e0cedcea14" + integrity sha512-PVhypqaA0t98zVDpOeTqWUTvRqCEjJubtfFUQ7zJNYdbYTbS/E/ytq6zbLVsN/dImvemtO/5JQgjLxsh8XLo8Q== + dependencies: + "@docusaurus/core" "2.4.3" + "@docusaurus/logger" "2.4.3" + "@docusaurus/mdx-loader" "2.4.3" + "@docusaurus/types" "2.4.3" + "@docusaurus/utils" "2.4.3" + "@docusaurus/utils-common" "2.4.3" + "@docusaurus/utils-validation" "2.4.3" cheerio "^1.0.0-rc.12" feed "^4.2.2" fs-extra "^10.1.0" @@ -1474,18 +1447,18 @@ utility-types "^3.10.0" webpack "^5.73.0" -"@docusaurus/plugin-content-docs@2.2.0": - version "2.2.0" - resolved "https://registry.yarnpkg.com/@docusaurus/plugin-content-docs/-/plugin-content-docs-2.2.0.tgz#0fcb85226fcdb80dc1e2d4a36ef442a650dcc84d" - integrity sha512-BOazBR0XjzsHE+2K1wpNxz5QZmrJgmm3+0Re0EVPYFGW8qndCWGNtXW/0lGKhecVPML8yyFeAmnUCIs7xM2wPw== - dependencies: - "@docusaurus/core" "2.2.0" - "@docusaurus/logger" "2.2.0" - "@docusaurus/mdx-loader" "2.2.0" - "@docusaurus/module-type-aliases" "2.2.0" - "@docusaurus/types" "2.2.0" - "@docusaurus/utils" "2.2.0" - "@docusaurus/utils-validation" "2.2.0" +"@docusaurus/plugin-content-docs@2.4.3": + version "2.4.3" + resolved "https://registry.yarnpkg.com/@docusaurus/plugin-content-docs/-/plugin-content-docs-2.4.3.tgz#aa224c0512351e81807adf778ca59fd9cd136973" + integrity sha512-N7Po2LSH6UejQhzTCsvuX5NOzlC+HiXOVvofnEPj0WhMu1etpLEXE6a4aTxrtg95lQ5kf0xUIdjX9sh3d3G76A== + dependencies: + "@docusaurus/core" "2.4.3" + "@docusaurus/logger" "2.4.3" + "@docusaurus/mdx-loader" "2.4.3" + "@docusaurus/module-type-aliases" "2.4.3" + "@docusaurus/types" "2.4.3" + "@docusaurus/utils" "2.4.3" + "@docusaurus/utils-validation" "2.4.3" "@types/react-router-config" "^5.0.6" combine-promises "^1.1.0" fs-extra "^10.1.0" @@ -1496,68 +1469,63 @@ utility-types "^3.10.0" webpack "^5.73.0" -"@docusaurus/plugin-content-pages@2.2.0": - version "2.2.0" - resolved "https://registry.yarnpkg.com/@docusaurus/plugin-content-pages/-/plugin-content-pages-2.2.0.tgz#e3f40408787bbe229545dd50595f87e1393bc3ae" - integrity sha512-+OTK3FQHk5WMvdelz8v19PbEbx+CNT6VSpx7nVOvMNs5yJCKvmqBJBQ2ZSxROxhVDYn+CZOlmyrC56NSXzHf6g== - dependencies: - "@docusaurus/core" "2.2.0" - "@docusaurus/mdx-loader" "2.2.0" - "@docusaurus/types" "2.2.0" - "@docusaurus/utils" "2.2.0" - "@docusaurus/utils-validation" "2.2.0" +"@docusaurus/plugin-content-pages@2.4.3": + version "2.4.3" + resolved "https://registry.yarnpkg.com/@docusaurus/plugin-content-pages/-/plugin-content-pages-2.4.3.tgz#7f285e718b53da8c8d0101e70840c75b9c0a1ac0" + integrity sha512-txtDVz7y3zGk67q0HjG0gRttVPodkHqE0bpJ+7dOaTH40CQFLSh7+aBeGnPOTl+oCPG+hxkim4SndqPqXjQ8Bg== + dependencies: + "@docusaurus/core" "2.4.3" + "@docusaurus/mdx-loader" "2.4.3" + "@docusaurus/types" "2.4.3" + "@docusaurus/utils" "2.4.3" + "@docusaurus/utils-validation" "2.4.3" fs-extra "^10.1.0" tslib "^2.4.0" webpack "^5.73.0" -"@docusaurus/plugin-debug@2.2.0": - version "2.2.0" - resolved "https://registry.yarnpkg.com/@docusaurus/plugin-debug/-/plugin-debug-2.2.0.tgz#b38741d2c492f405fee01ee0ef2e0029cedb689a" - integrity sha512-p9vOep8+7OVl6r/NREEYxf4HMAjV8JMYJ7Bos5fCFO0Wyi9AZEo0sCTliRd7R8+dlJXZEgcngSdxAUo/Q+CJow== +"@docusaurus/plugin-debug@2.4.3": + version "2.4.3" + resolved "https://registry.yarnpkg.com/@docusaurus/plugin-debug/-/plugin-debug-2.4.3.tgz#2f90eb0c9286a9f225444e3a88315676fe02c245" + integrity sha512-LkUbuq3zCmINlFb+gAd4ZvYr+bPAzMC0hwND4F7V9bZ852dCX8YoWyovVUBKq4er1XsOwSQaHmNGtObtn8Av8Q== dependencies: - "@docusaurus/core" "2.2.0" - "@docusaurus/types" "2.2.0" - "@docusaurus/utils" "2.2.0" + "@docusaurus/core" "2.4.3" + "@docusaurus/types" "2.4.3" + "@docusaurus/utils" "2.4.3" fs-extra "^10.1.0" react-json-view "^1.21.3" tslib "^2.4.0" -"@docusaurus/plugin-google-analytics@2.2.0": - version "2.2.0" - resolved "https://registry.yarnpkg.com/@docusaurus/plugin-google-analytics/-/plugin-google-analytics-2.2.0.tgz#63c7137eff5a1208d2059fea04b5207c037d7954" - integrity sha512-+eZVVxVeEnV5nVQJdey9ZsfyEVMls6VyWTIj8SmX0k5EbqGvnIfET+J2pYEuKQnDIHxy+syRMoRM6AHXdHYGIg== +"@docusaurus/plugin-google-analytics@2.4.3": + version "2.4.3" + resolved "https://registry.yarnpkg.com/@docusaurus/plugin-google-analytics/-/plugin-google-analytics-2.4.3.tgz#0d19993136ade6f7a7741251b4f617400d92ab45" + integrity sha512-KzBV3k8lDkWOhg/oYGxlK5o9bOwX7KpPc/FTWoB+SfKhlHfhq7qcQdMi1elAaVEIop8tgK6gD1E58Q+XC6otSQ== dependencies: - "@docusaurus/core" "2.2.0" - "@docusaurus/types" "2.2.0" - "@docusaurus/utils-validation" "2.2.0" + "@docusaurus/core" "2.4.3" + "@docusaurus/types" "2.4.3" + "@docusaurus/utils-validation" "2.4.3" tslib "^2.4.0" -"@docusaurus/plugin-google-gtag@2.2.0": - version "2.2.0" - resolved "https://registry.yarnpkg.com/@docusaurus/plugin-google-gtag/-/plugin-google-gtag-2.2.0.tgz#7b086d169ac5fe9a88aca10ab0fd2bf00c6c6b12" - integrity sha512-6SOgczP/dYdkqUMGTRqgxAS1eTp6MnJDAQMy8VCF1QKbWZmlkx4agHDexihqmYyCujTYHqDAhm1hV26EET54NQ== +"@docusaurus/plugin-google-gtag@2.4.3": + version "2.4.3" + resolved "https://registry.yarnpkg.com/@docusaurus/plugin-google-gtag/-/plugin-google-gtag-2.4.3.tgz#e1a80b0696771b488562e5b60eff21c9932d9e1c" + integrity sha512-5FMg0rT7sDy4i9AGsvJC71MQrqQZwgLNdDetLEGDHLfSHLvJhQbTCUGbGXknUgWXQJckcV/AILYeJy+HhxeIFA== dependencies: - "@docusaurus/core" "2.2.0" - "@docusaurus/types" "2.2.0" - "@docusaurus/utils-validation" "2.2.0" + "@docusaurus/core" "2.4.3" + "@docusaurus/types" "2.4.3" + "@docusaurus/utils-validation" "2.4.3" tslib "^2.4.0" -"@docusaurus/plugin-sitemap@2.2.0": - version "2.2.0" - resolved "https://registry.yarnpkg.com/@docusaurus/plugin-sitemap/-/plugin-sitemap-2.2.0.tgz#876da60937886032d63143253d420db6a4b34773" - integrity sha512-0jAmyRDN/aI265CbWZNZuQpFqiZuo+5otk2MylU9iVrz/4J7gSc+ZJ9cy4EHrEsW7PV8s1w18hIEsmcA1YgkKg== - dependencies: - "@docusaurus/core" "2.2.0" - "@docusaurus/logger" "2.2.0" - "@docusaurus/types" "2.2.0" - "@docusaurus/utils" "2.2.0" - "@docusaurus/utils-common" "2.2.0" - "@docusaurus/utils-validation" "2.2.0" - fs-extra "^10.1.0" - sitemap "^7.1.1" +"@docusaurus/plugin-google-tag-manager@2.4.3": + version "2.4.3" + resolved "https://registry.yarnpkg.com/@docusaurus/plugin-google-tag-manager/-/plugin-google-tag-manager-2.4.3.tgz#e41fbf79b0ffc2de1cc4013eb77798cff0ad98e3" + integrity sha512-1jTzp71yDGuQiX9Bi0pVp3alArV0LSnHXempvQTxwCGAEzUWWaBg4d8pocAlTpbP9aULQQqhgzrs8hgTRPOM0A== + dependencies: + "@docusaurus/core" "2.4.3" + "@docusaurus/types" "2.4.3" + "@docusaurus/utils-validation" "2.4.3" tslib "^2.4.0" -"@docusaurus/plugin-sitemap@^2.4.3": +"@docusaurus/plugin-sitemap@2.4.3", "@docusaurus/plugin-sitemap@^2.4.3": version "2.4.3" resolved "https://registry.yarnpkg.com/@docusaurus/plugin-sitemap/-/plugin-sitemap-2.4.3.tgz#1b3930900a8f89670ce7e8f83fb4730cd3298c32" integrity sha512-LRQYrK1oH1rNfr4YvWBmRzTL0LN9UAPxBbghgeFRBm5yloF6P+zv1tm2pe2hQTX/QP5bSKdnajCvfnScgKXMZQ== @@ -1572,23 +1540,24 @@ sitemap "^7.1.1" tslib "^2.4.0" -"@docusaurus/preset-classic@^2.0.0-beta.15": - version "2.2.0" - resolved "https://registry.yarnpkg.com/@docusaurus/preset-classic/-/preset-classic-2.2.0.tgz#bece5a043eeb74430f7c6c7510000b9c43669eb7" - integrity sha512-yKIWPGNx7BT8v2wjFIWvYrS+nvN04W+UameSFf8lEiJk6pss0kL6SG2MRvyULiI3BDxH+tj6qe02ncpSPGwumg== - dependencies: - "@docusaurus/core" "2.2.0" - "@docusaurus/plugin-content-blog" "2.2.0" - "@docusaurus/plugin-content-docs" "2.2.0" - "@docusaurus/plugin-content-pages" "2.2.0" - "@docusaurus/plugin-debug" "2.2.0" - "@docusaurus/plugin-google-analytics" "2.2.0" - "@docusaurus/plugin-google-gtag" "2.2.0" - "@docusaurus/plugin-sitemap" "2.2.0" - "@docusaurus/theme-classic" "2.2.0" - "@docusaurus/theme-common" "2.2.0" - "@docusaurus/theme-search-algolia" "2.2.0" - "@docusaurus/types" "2.2.0" +"@docusaurus/preset-classic@^2.4.3": + version "2.4.3" + resolved "https://registry.yarnpkg.com/@docusaurus/preset-classic/-/preset-classic-2.4.3.tgz#074c57ebf29fa43d23bd1c8ce691226f542bc262" + integrity sha512-tRyMliepY11Ym6hB1rAFSNGwQDpmszvWYJvlK1E+md4SW8i6ylNHtpZjaYFff9Mdk3i/Pg8ItQq9P0daOJAvQw== + dependencies: + "@docusaurus/core" "2.4.3" + "@docusaurus/plugin-content-blog" "2.4.3" + "@docusaurus/plugin-content-docs" "2.4.3" + "@docusaurus/plugin-content-pages" "2.4.3" + "@docusaurus/plugin-debug" "2.4.3" + "@docusaurus/plugin-google-analytics" "2.4.3" + "@docusaurus/plugin-google-gtag" "2.4.3" + "@docusaurus/plugin-google-tag-manager" "2.4.3" + "@docusaurus/plugin-sitemap" "2.4.3" + "@docusaurus/theme-classic" "2.4.3" + "@docusaurus/theme-common" "2.4.3" + "@docusaurus/theme-search-algolia" "2.4.3" + "@docusaurus/types" "2.4.3" "@docusaurus/react-loadable@5.5.2", "react-loadable@npm:@docusaurus/react-loadable@5.5.2": version "5.5.2" @@ -1598,27 +1567,27 @@ "@types/react" "*" prop-types "^15.6.2" -"@docusaurus/theme-classic@2.2.0": - version "2.2.0" - resolved "https://registry.yarnpkg.com/@docusaurus/theme-classic/-/theme-classic-2.2.0.tgz#a048bb1bc077dee74b28bec25f4b84b481863742" - integrity sha512-kjbg/qJPwZ6H1CU/i9d4l/LcFgnuzeiGgMQlt6yPqKo0SOJIBMPuz7Rnu3r/WWbZFPi//o8acclacOzmXdUUEg== - dependencies: - "@docusaurus/core" "2.2.0" - "@docusaurus/mdx-loader" "2.2.0" - "@docusaurus/module-type-aliases" "2.2.0" - "@docusaurus/plugin-content-blog" "2.2.0" - "@docusaurus/plugin-content-docs" "2.2.0" - "@docusaurus/plugin-content-pages" "2.2.0" - "@docusaurus/theme-common" "2.2.0" - "@docusaurus/theme-translations" "2.2.0" - "@docusaurus/types" "2.2.0" - "@docusaurus/utils" "2.2.0" - "@docusaurus/utils-common" "2.2.0" - "@docusaurus/utils-validation" "2.2.0" +"@docusaurus/theme-classic@2.4.3": + version "2.4.3" + resolved "https://registry.yarnpkg.com/@docusaurus/theme-classic/-/theme-classic-2.4.3.tgz#29360f2eb03a0e1686eb19668633ef313970ee8f" + integrity sha512-QKRAJPSGPfDY2yCiPMIVyr+MqwZCIV2lxNzqbyUW0YkrlmdzzP3WuQJPMGLCjWgQp/5c9kpWMvMxjhpZx1R32Q== + dependencies: + "@docusaurus/core" "2.4.3" + "@docusaurus/mdx-loader" "2.4.3" + "@docusaurus/module-type-aliases" "2.4.3" + "@docusaurus/plugin-content-blog" "2.4.3" + "@docusaurus/plugin-content-docs" "2.4.3" + "@docusaurus/plugin-content-pages" "2.4.3" + "@docusaurus/theme-common" "2.4.3" + "@docusaurus/theme-translations" "2.4.3" + "@docusaurus/types" "2.4.3" + "@docusaurus/utils" "2.4.3" + "@docusaurus/utils-common" "2.4.3" + "@docusaurus/utils-validation" "2.4.3" "@mdx-js/react" "^1.6.22" clsx "^1.2.1" copy-text-to-clipboard "^3.0.1" - infima "0.2.0-alpha.42" + infima "0.2.0-alpha.43" lodash "^4.17.21" nprogress "^0.2.0" postcss "^8.4.14" @@ -1629,17 +1598,18 @@ tslib "^2.4.0" utility-types "^3.10.0" -"@docusaurus/theme-common@2.2.0": - version "2.2.0" - resolved "https://registry.yarnpkg.com/@docusaurus/theme-common/-/theme-common-2.2.0.tgz#2303498d80448aafdd588b597ce9d6f4cfa930e4" - integrity sha512-R8BnDjYoN90DCL75gP7qYQfSjyitXuP9TdzgsKDmSFPNyrdE3twtPNa2dIN+h+p/pr+PagfxwWbd6dn722A1Dw== - dependencies: - "@docusaurus/mdx-loader" "2.2.0" - "@docusaurus/module-type-aliases" "2.2.0" - "@docusaurus/plugin-content-blog" "2.2.0" - "@docusaurus/plugin-content-docs" "2.2.0" - "@docusaurus/plugin-content-pages" "2.2.0" - "@docusaurus/utils" "2.2.0" +"@docusaurus/theme-common@2.4.3": + version "2.4.3" + resolved "https://registry.yarnpkg.com/@docusaurus/theme-common/-/theme-common-2.4.3.tgz#bb31d70b6b67d0bdef9baa343192dcec49946a2e" + integrity sha512-7KaDJBXKBVGXw5WOVt84FtN8czGWhM0lbyWEZXGp8AFfL6sZQfRTluFp4QriR97qwzSyOfQb+nzcDZZU4tezUw== + dependencies: + "@docusaurus/mdx-loader" "2.4.3" + "@docusaurus/module-type-aliases" "2.4.3" + "@docusaurus/plugin-content-blog" "2.4.3" + "@docusaurus/plugin-content-docs" "2.4.3" + "@docusaurus/plugin-content-pages" "2.4.3" + "@docusaurus/utils" "2.4.3" + "@docusaurus/utils-common" "2.4.3" "@types/history" "^4.7.11" "@types/react" "*" "@types/react-router-config" "*" @@ -1647,52 +1617,39 @@ parse-numeric-range "^1.3.0" prism-react-renderer "^1.3.5" tslib "^2.4.0" + use-sync-external-store "^1.2.0" utility-types "^3.10.0" -"@docusaurus/theme-search-algolia@2.2.0": - version "2.2.0" - resolved "https://registry.yarnpkg.com/@docusaurus/theme-search-algolia/-/theme-search-algolia-2.2.0.tgz#77fd9f7a600917e6024fe3ac7fb6cfdf2ce84737" - integrity sha512-2h38B0tqlxgR2FZ9LpAkGrpDWVdXZ7vltfmTdX+4RsDs3A7khiNsmZB+x/x6sA4+G2V2CvrsPMlsYBy5X+cY1w== +"@docusaurus/theme-search-algolia@2.4.3": + version "2.4.3" + resolved "https://registry.yarnpkg.com/@docusaurus/theme-search-algolia/-/theme-search-algolia-2.4.3.tgz#32d4cbefc3deba4112068fbdb0bde11ac51ece53" + integrity sha512-jziq4f6YVUB5hZOB85ELATwnxBz/RmSLD3ksGQOLDPKVzat4pmI8tddNWtriPpxR04BNT+ZfpPUMFkNFetSW1Q== dependencies: "@docsearch/react" "^3.1.1" - "@docusaurus/core" "2.2.0" - "@docusaurus/logger" "2.2.0" - "@docusaurus/plugin-content-docs" "2.2.0" - "@docusaurus/theme-common" "2.2.0" - "@docusaurus/theme-translations" "2.2.0" - "@docusaurus/utils" "2.2.0" - "@docusaurus/utils-validation" "2.2.0" + "@docusaurus/core" "2.4.3" + "@docusaurus/logger" "2.4.3" + "@docusaurus/plugin-content-docs" "2.4.3" + "@docusaurus/theme-common" "2.4.3" + "@docusaurus/theme-translations" "2.4.3" + "@docusaurus/utils" "2.4.3" + "@docusaurus/utils-validation" "2.4.3" algoliasearch "^4.13.1" algoliasearch-helper "^3.10.0" clsx "^1.2.1" - eta "^1.12.3" + eta "^2.0.0" fs-extra "^10.1.0" lodash "^4.17.21" tslib "^2.4.0" utility-types "^3.10.0" -"@docusaurus/theme-translations@2.2.0": - version "2.2.0" - resolved "https://registry.yarnpkg.com/@docusaurus/theme-translations/-/theme-translations-2.2.0.tgz#5fbd4693679806f80c26eeae1381e1f2c23d83e7" - integrity sha512-3T140AG11OjJrtKlY4pMZ5BzbGRDjNs2co5hJ6uYJG1bVWlhcaFGqkaZ5lCgKflaNHD7UHBHU9Ec5f69jTdd6w== +"@docusaurus/theme-translations@2.4.3": + version "2.4.3" + resolved "https://registry.yarnpkg.com/@docusaurus/theme-translations/-/theme-translations-2.4.3.tgz#91ac73fc49b8c652b7a54e88b679af57d6ac6102" + integrity sha512-H4D+lbZbjbKNS/Zw1Lel64PioUAIT3cLYYJLUf3KkuO/oc9e0QCVhIYVtUI2SfBCF2NNdlyhBDQEEMygsCedIg== dependencies: fs-extra "^10.1.0" tslib "^2.4.0" -"@docusaurus/types@2.2.0": - version "2.2.0" - resolved "https://registry.yarnpkg.com/@docusaurus/types/-/types-2.2.0.tgz#02c577a4041ab7d058a3c214ccb13647e21a9857" - integrity sha512-b6xxyoexfbRNRI8gjblzVOnLr4peCJhGbYGPpJ3LFqpi5nsFfoK4mmDLvWdeah0B7gmJeXabN7nQkFoqeSdmOw== - dependencies: - "@types/history" "^4.7.11" - "@types/react" "*" - commander "^5.1.0" - joi "^17.6.0" - react-helmet-async "^1.3.0" - utility-types "^3.10.0" - webpack "^5.73.0" - webpack-merge "^5.8.0" - "@docusaurus/types@2.4.3": version "2.4.3" resolved "https://registry.yarnpkg.com/@docusaurus/types/-/types-2.4.3.tgz#4aead281ca09f721b3c0a9b926818450cfa3db31" @@ -1707,13 +1664,6 @@ webpack "^5.73.0" webpack-merge "^5.8.0" -"@docusaurus/utils-common@2.2.0": - version "2.2.0" - resolved "https://registry.yarnpkg.com/@docusaurus/utils-common/-/utils-common-2.2.0.tgz#a401c1b93a8697dd566baf6ac64f0fdff1641a78" - integrity sha512-qebnerHp+cyovdUseDQyYFvMW1n1nv61zGe5JJfoNQUnjKuApch3IVsz+/lZ9a38pId8kqehC1Ao2bW/s0ntDA== - dependencies: - tslib "^2.4.0" - "@docusaurus/utils-common@2.4.3": version "2.4.3" resolved "https://registry.yarnpkg.com/@docusaurus/utils-common/-/utils-common-2.4.3.tgz#30656c39ef1ce7e002af7ba39ea08330f58efcfb" @@ -1721,17 +1671,6 @@ dependencies: tslib "^2.4.0" -"@docusaurus/utils-validation@2.2.0": - version "2.2.0" - resolved "https://registry.yarnpkg.com/@docusaurus/utils-validation/-/utils-validation-2.2.0.tgz#04d4d103137ad0145883971d3aa497f4a1315f25" - integrity sha512-I1hcsG3yoCkasOL5qQAYAfnmVoLei7apugT6m4crQjmDGxq+UkiRrq55UqmDDyZlac/6ax/JC0p+usZ6W4nVyg== - dependencies: - "@docusaurus/logger" "2.2.0" - "@docusaurus/utils" "2.2.0" - joi "^17.6.0" - js-yaml "^4.1.0" - tslib "^2.4.0" - "@docusaurus/utils-validation@2.4.3": version "2.4.3" resolved "https://registry.yarnpkg.com/@docusaurus/utils-validation/-/utils-validation-2.4.3.tgz#8122c394feef3e96c73f6433987837ec206a63fb" @@ -1743,27 +1682,6 @@ js-yaml "^4.1.0" tslib "^2.4.0" -"@docusaurus/utils@2.2.0": - version "2.2.0" - resolved "https://registry.yarnpkg.com/@docusaurus/utils/-/utils-2.2.0.tgz#3d6f9b7a69168d5c92d371bf21c556a4f50d1da6" - integrity sha512-oNk3cjvx7Tt1Lgh/aeZAmFpGV2pDr5nHKrBVx6hTkzGhrnMuQqLt6UPlQjdYQ3QHXwyF/ZtZMO1D5Pfi0lu7SA== - dependencies: - "@docusaurus/logger" "2.2.0" - "@svgr/webpack" "^6.2.1" - file-loader "^6.2.0" - fs-extra "^10.1.0" - github-slugger "^1.4.0" - globby "^11.1.0" - gray-matter "^4.0.3" - js-yaml "^4.1.0" - lodash "^4.17.21" - micromatch "^4.0.5" - resolve-pathname "^3.0.0" - shelljs "^0.8.5" - tslib "^2.4.0" - url-loader "^4.1.1" - webpack "^5.73.0" - "@docusaurus/utils@2.4.3": version "2.4.3" resolved "https://registry.yarnpkg.com/@docusaurus/utils/-/utils-2.4.3.tgz#52b000d989380a2125831b84e3a7327bef471e89" @@ -1786,89 +1704,81 @@ url-loader "^4.1.1" webpack "^5.73.0" -"@hapi/hoek@^9.0.0": +"@hapi/hoek@^9.0.0", "@hapi/hoek@^9.3.0": version "9.3.0" resolved "https://registry.yarnpkg.com/@hapi/hoek/-/hoek-9.3.0.tgz#8368869dcb735be2e7f5cb7647de78e167a251fb" integrity sha512-/c6rf4UJlmHlC9b5BaNvzAcFv7HZ2QHaV0D4/HNlBdvFnvQq8RI4kYdhyPCl7Xj+oWvTWQ8ujhqS53LIgAe6KQ== -"@hapi/topo@^5.0.0": +"@hapi/topo@^5.1.0": version "5.1.0" resolved "https://registry.yarnpkg.com/@hapi/topo/-/topo-5.1.0.tgz#dc448e332c6c6e37a4dc02fd84ba8d44b9afb012" integrity sha512-foQZKJig7Ob0BMAYBfcJk8d77QtOe7Wo4ox7ff1lQYoNNAb6jwcY1ncdoy2e9wQZzvNy7ODZCYJkK8kzmcAnAg== dependencies: "@hapi/hoek" "^9.0.0" -"@jest/schemas@^29.0.0": - version "29.0.0" - resolved "https://registry.yarnpkg.com/@jest/schemas/-/schemas-29.0.0.tgz#5f47f5994dd4ef067fb7b4188ceac45f77fe952a" - integrity sha512-3Ab5HgYIIAnS0HjqJHQYZS+zXc4tUmTmBH3z83ajI6afXp8X3ZtdLX+nXx+I7LNkJD7uN9LAVhgnjDgZa2z0kA== +"@jest/schemas@^29.6.3": + version "29.6.3" + resolved "https://registry.yarnpkg.com/@jest/schemas/-/schemas-29.6.3.tgz#430b5ce8a4e0044a7e3819663305a7b3091c8e03" + integrity sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA== dependencies: - "@sinclair/typebox" "^0.24.1" + "@sinclair/typebox" "^0.27.8" -"@jest/types@^29.3.1": - version "29.3.1" - resolved "https://registry.yarnpkg.com/@jest/types/-/types-29.3.1.tgz#7c5a80777cb13e703aeec6788d044150341147e3" - integrity sha512-d0S0jmmTpjnhCmNpApgX3jrUZgZ22ivKJRvL2lli5hpCRoNnp1f85r2/wpKfXuYu8E7Jjh1hGfhPyup1NM5AmA== +"@jest/types@^29.6.3": + version "29.6.3" + resolved "https://registry.yarnpkg.com/@jest/types/-/types-29.6.3.tgz#1131f8cf634e7e84c5e77bab12f052af585fba59" + integrity sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw== dependencies: - "@jest/schemas" "^29.0.0" + "@jest/schemas" "^29.6.3" "@types/istanbul-lib-coverage" "^2.0.0" "@types/istanbul-reports" "^3.0.0" "@types/node" "*" "@types/yargs" "^17.0.8" chalk "^4.0.0" -"@jridgewell/gen-mapping@^0.1.0": - version "0.1.1" - resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz#e5d2e450306a9491e3bd77e323e38d7aff315996" - integrity sha512-sQXCasFk+U8lWYEe66WxRDOE9PjVz4vSM51fTu3Hw+ClTpUSQb718772vH3pyS5pShp6lvQM7SxgIDXXXmOX7w== - dependencies: - "@jridgewell/set-array" "^1.0.0" - "@jridgewell/sourcemap-codec" "^1.4.10" - -"@jridgewell/gen-mapping@^0.3.0", "@jridgewell/gen-mapping@^0.3.2": - version "0.3.2" - resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz#c1aedc61e853f2bb9f5dfe6d4442d3b565b253b9" - integrity sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A== +"@jridgewell/gen-mapping@^0.3.5": + version "0.3.5" + resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz#dcce6aff74bdf6dad1a95802b69b04a2fcb1fb36" + integrity sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg== dependencies: - "@jridgewell/set-array" "^1.0.1" + "@jridgewell/set-array" "^1.2.1" "@jridgewell/sourcemap-codec" "^1.4.10" - "@jridgewell/trace-mapping" "^0.3.9" + "@jridgewell/trace-mapping" "^0.3.24" -"@jridgewell/resolve-uri@3.1.0": - version "3.1.0" - resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz#2203b118c157721addfe69d47b70465463066d78" - integrity sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w== +"@jridgewell/resolve-uri@^3.1.0": + version "3.1.2" + resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz#7a0ee601f60f99a20c7c7c5ff0c80388c1189bd6" + integrity sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw== -"@jridgewell/set-array@^1.0.0", "@jridgewell/set-array@^1.0.1": - version "1.1.2" - resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.1.2.tgz#7c6cf998d6d20b914c0a55a91ae928ff25965e72" - integrity sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw== +"@jridgewell/set-array@^1.2.1": + version "1.2.1" + resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.2.1.tgz#558fb6472ed16a4c850b889530e6b36438c49280" + integrity sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A== -"@jridgewell/source-map@^0.3.2": - version "0.3.2" - resolved "https://registry.yarnpkg.com/@jridgewell/source-map/-/source-map-0.3.2.tgz#f45351aaed4527a298512ec72f81040c998580fb" - integrity sha512-m7O9o2uR8k2ObDysZYzdfhb08VuEml5oWGiosa1VdaPZ/A6QyPkAJuwN0Q1lhULOf6B7MtQmHENS743hWtCrgw== +"@jridgewell/source-map@^0.3.3": + version "0.3.6" + resolved "https://registry.yarnpkg.com/@jridgewell/source-map/-/source-map-0.3.6.tgz#9d71ca886e32502eb9362c9a74a46787c36df81a" + integrity sha512-1ZJTZebgqllO79ue2bm3rIGud/bOe0pP5BjSRCRxxYkEZS8STV7zN84UBbiYu7jy+eCKSnVIUgoWWE/tt+shMQ== dependencies: - "@jridgewell/gen-mapping" "^0.3.0" - "@jridgewell/trace-mapping" "^0.3.9" + "@jridgewell/gen-mapping" "^0.3.5" + "@jridgewell/trace-mapping" "^0.3.25" -"@jridgewell/sourcemap-codec@1.4.14", "@jridgewell/sourcemap-codec@^1.4.10": - version "1.4.14" - resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz#add4c98d341472a289190b424efbdb096991bb24" - integrity sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw== +"@jridgewell/sourcemap-codec@^1.4.10", "@jridgewell/sourcemap-codec@^1.4.14": + version "1.5.0" + resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz#3188bcb273a414b0d215fd22a58540b989b9409a" + integrity sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ== -"@jridgewell/trace-mapping@^0.3.14", "@jridgewell/trace-mapping@^0.3.9": - version "0.3.17" - resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.17.tgz#793041277af9073b0951a7fe0f0d8c4c98c36985" - integrity sha512-MCNzAp77qzKca9+W/+I0+sEpaUnZoeasnghNeVc41VZCEKaCH73Vq3BZZ/SzWIgrqE4H4ceI+p+b6C0mHf9T4g== +"@jridgewell/trace-mapping@^0.3.20", "@jridgewell/trace-mapping@^0.3.24", "@jridgewell/trace-mapping@^0.3.25": + version "0.3.25" + resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz#15f190e98895f3fc23276ee14bc76b675c2e50f0" + integrity sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ== dependencies: - "@jridgewell/resolve-uri" "3.1.0" - "@jridgewell/sourcemap-codec" "1.4.14" + "@jridgewell/resolve-uri" "^3.1.0" + "@jridgewell/sourcemap-codec" "^1.4.14" "@leichtgewicht/ip-codec@^2.0.1": - version "2.0.4" - resolved "https://registry.yarnpkg.com/@leichtgewicht/ip-codec/-/ip-codec-2.0.4.tgz#b2ac626d6cb9c8718ab459166d4bb405b8ffa78b" - integrity sha512-Hcv+nVC0kZnQ3tD9GVu5xSMR4VVYOteQIr/hwFPVEvPdlXqgGEuRjiheChHgdM+JyqdgNcmzZOX/tnl0JOiI7A== + version "2.0.5" + resolved "https://registry.yarnpkg.com/@leichtgewicht/ip-codec/-/ip-codec-2.0.5.tgz#4fc56c15c580b9adb7dc3c333a134e540b44bfb1" + integrity sha512-Vo+PSpZG2/fmgmiNzYK9qWRh8h/CHrwD0mo1h1DzL4yzHNSfWYujGTYsWGreD000gcgmZ7K4Ys6Tx9TxtsKdDw== "@mdx-js/mdx@^1.6.22": version "1.6.22" @@ -1926,32 +1836,32 @@ "@nodelib/fs.scandir" "2.1.5" fastq "^1.6.0" -"@polka/url@^1.0.0-next.20": - version "1.0.0-next.21" - resolved "https://registry.yarnpkg.com/@polka/url/-/url-1.0.0-next.21.tgz#5de5a2385a35309427f6011992b544514d559aa1" - integrity sha512-a5Sab1C4/icpTZVzZc5Ghpz88yQtGOyNqYXcZgOssB2uuAr+wF/MvN6bgtW32q7HHrvBki+BsZ0OuNv6EV3K9g== +"@polka/url@^1.0.0-next.24": + version "1.0.0-next.25" + resolved "https://registry.yarnpkg.com/@polka/url/-/url-1.0.0-next.25.tgz#f077fdc0b5d0078d30893396ff4827a13f99e817" + integrity sha512-j7P6Rgr3mmtdkeDGTe0E/aYyWEWVtc5yFXtHCRHs28/jptDEWfaVOc5T7cblqy1XKPPfCxJc/8DwQ5YgLOZOVQ== -"@sideway/address@^4.1.3": - version "4.1.4" - resolved "https://registry.yarnpkg.com/@sideway/address/-/address-4.1.4.tgz#03dccebc6ea47fdc226f7d3d1ad512955d4783f0" - integrity sha512-7vwq+rOHVWjyXxVlR76Agnvhy8I9rpzjosTESvmhNeXOXdZZB15Fl+TI9x1SiHZH5Jv2wTGduSxFDIaq0m3DUw== +"@sideway/address@^4.1.5": + version "4.1.5" + resolved "https://registry.yarnpkg.com/@sideway/address/-/address-4.1.5.tgz#4bc149a0076623ced99ca8208ba780d65a99b9d5" + integrity sha512-IqO/DUQHUkPeixNQ8n0JA6102hT9CmaljNTPmQ1u8MEhBo/R4Q8eKLN/vGZxuebwOroDB4cbpjheD4+/sKFK4Q== dependencies: "@hapi/hoek" "^9.0.0" -"@sideway/formula@^3.0.0": - version "3.0.0" - resolved "https://registry.yarnpkg.com/@sideway/formula/-/formula-3.0.0.tgz#fe158aee32e6bd5de85044be615bc08478a0a13c" - integrity sha512-vHe7wZ4NOXVfkoRb8T5otiENVlT7a3IAiw7H5M2+GO+9CDgcVUUsX1zalAztCmwyOr2RUTGJdgB+ZvSVqmdHmg== +"@sideway/formula@^3.0.1": + version "3.0.1" + resolved "https://registry.yarnpkg.com/@sideway/formula/-/formula-3.0.1.tgz#80fcbcbaf7ce031e0ef2dd29b1bfc7c3f583611f" + integrity sha512-/poHZJJVjx3L+zVD6g9KgHfYnb443oi7wLu/XKojDviHy6HOEOA6z1Trk5aR1dGcmPenJEgb2sK2I80LeS3MIg== "@sideway/pinpoint@^2.0.0": version "2.0.0" resolved "https://registry.yarnpkg.com/@sideway/pinpoint/-/pinpoint-2.0.0.tgz#cff8ffadc372ad29fd3f78277aeb29e632cc70df" integrity sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ== -"@sinclair/typebox@^0.24.1": - version "0.24.51" - resolved "https://registry.yarnpkg.com/@sinclair/typebox/-/typebox-0.24.51.tgz#645f33fe4e02defe26f2f5c0410e1c094eac7f5f" - integrity sha512-1P1OROm/rdubP5aFDSZQILU0vrLCJ4fvHt6EoqHEM+2D/G5MK3bIaymUKLit8Js9gbns5UyJnkP/TZROLw4tUA== +"@sinclair/typebox@^0.27.8": + version "0.27.8" + resolved "https://registry.yarnpkg.com/@sinclair/typebox/-/typebox-0.27.8.tgz#6667fac16c436b5434a387a34dedb013198f6e6e" + integrity sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA== "@sindresorhus/is@^0.14.0": version "0.14.0" @@ -1973,14 +1883,14 @@ integrity sha512-9PYGcXrAxitycIjRmZB+Q0JaN07GZIWaTBIGQzfaZv+qr1n8X1XUEJ5rZ/vx6OVD9RRYlrNnXWExQXcmZeD/BQ== "@svgr/babel-plugin-remove-jsx-attribute@*": - version "6.5.0" - resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-remove-jsx-attribute/-/babel-plugin-remove-jsx-attribute-6.5.0.tgz#652bfd4ed0a0699843585cda96faeb09d6e1306e" - integrity sha512-8zYdkym7qNyfXpWvu4yq46k41pyNM9SOstoWhKlm+IfdCE1DdnRKeMUPsWIEO/DEkaWxJ8T9esNdG3QwQ93jBA== + version "8.0.0" + resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-remove-jsx-attribute/-/babel-plugin-remove-jsx-attribute-8.0.0.tgz#69177f7937233caca3a1afb051906698f2f59186" + integrity sha512-BcCkm/STipKvbCl6b7QFrMh/vx00vIP63k2eM66MfHJzPr6O2U0jYEViXkHJWqXqQYjdeA9cuCl5KWmlwjDvbA== "@svgr/babel-plugin-remove-jsx-empty-expression@*": - version "6.5.0" - resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-remove-jsx-empty-expression/-/babel-plugin-remove-jsx-empty-expression-6.5.0.tgz#4b78994ab7d39032c729903fc2dd5c0fa4565cb8" - integrity sha512-NFdxMq3xA42Kb1UbzCVxplUc0iqSyM9X8kopImvFnB+uSDdzIHOdbs1op8ofAvVRtbg4oZiyRl3fTYeKcOe9Iw== + version "8.0.0" + resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-remove-jsx-empty-expression/-/babel-plugin-remove-jsx-empty-expression-8.0.0.tgz#c2c48104cfd7dcd557f373b70a56e9e3bdae1d44" + integrity sha512-5BcGCBfBxB5+XSDSWnhTThfI9jcO5f0Ai2V24gZpG+wXF14BzwxxdDb4g6trdOux0rhibGs385BeFMSmxtS3uA== "@svgr/babel-plugin-replace-jsx-attribute-value@^6.5.1": version "6.5.1" @@ -2091,86 +2001,82 @@ integrity sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA== "@types/body-parser@*": - version "1.19.2" - resolved "https://registry.yarnpkg.com/@types/body-parser/-/body-parser-1.19.2.tgz#aea2059e28b7658639081347ac4fab3de166e6f0" - integrity sha512-ALYone6pm6QmwZoAgeyNksccT9Q4AWZQ6PvfwR37GT6r6FWUPguq6sUmNGSMV2Wr761oQoBxwGGa6DR5o1DC9g== + version "1.19.5" + resolved "https://registry.yarnpkg.com/@types/body-parser/-/body-parser-1.19.5.tgz#04ce9a3b677dc8bd681a17da1ab9835dc9d3ede4" + integrity sha512-fB3Zu92ucau0iQ0JMCFQE7b/dv8Ot07NI3KaZIkIUNXq82k4eBAqUaneXfleGY9JWskeS9y+u0nXMyspcuQrCg== dependencies: "@types/connect" "*" "@types/node" "*" "@types/bonjour@^3.5.9": - version "3.5.10" - resolved "https://registry.yarnpkg.com/@types/bonjour/-/bonjour-3.5.10.tgz#0f6aadfe00ea414edc86f5d106357cda9701e275" - integrity sha512-p7ienRMiS41Nu2/igbJxxLDWrSZ0WxM8UQgCeO9KhoVF7cOVFkrKsiDr1EsJIla8vV3oEEjGcz11jc5yimhzZw== + version "3.5.13" + resolved "https://registry.yarnpkg.com/@types/bonjour/-/bonjour-3.5.13.tgz#adf90ce1a105e81dd1f9c61fdc5afda1bfb92956" + integrity sha512-z9fJ5Im06zvUL548KvYNecEVlA7cVDkGUi6kZusb04mpyEFKCIZJvloCcmpmLaIahDpOQGHaHmG6imtPMmPXGQ== dependencies: "@types/node" "*" "@types/connect-history-api-fallback@^1.3.5": - version "1.3.5" - resolved "https://registry.yarnpkg.com/@types/connect-history-api-fallback/-/connect-history-api-fallback-1.3.5.tgz#d1f7a8a09d0ed5a57aee5ae9c18ab9b803205dae" - integrity sha512-h8QJa8xSb1WD4fpKBDcATDNGXghFj6/3GRWG6dhmRcu0RX1Ubasur2Uvx5aeEwlf0MwblEC2bMzzMQntxnw/Cw== + version "1.5.4" + resolved "https://registry.yarnpkg.com/@types/connect-history-api-fallback/-/connect-history-api-fallback-1.5.4.tgz#7de71645a103056b48ac3ce07b3520b819c1d5b3" + integrity sha512-n6Cr2xS1h4uAulPRdlw6Jl6s1oG8KrVilPN2yUITEs+K48EzMJJ3W1xy8K5eWuFvjp3R74AOIGSmp2UfBJ8HFw== dependencies: "@types/express-serve-static-core" "*" "@types/node" "*" "@types/connect@*": - version "3.4.35" - resolved "https://registry.yarnpkg.com/@types/connect/-/connect-3.4.35.tgz#5fcf6ae445e4021d1fc2219a4873cc73a3bb2ad1" - integrity sha512-cdeYyv4KWoEgpBISTxWvqYsVy444DOqehiF3fM3ne10AmJ62RSyNkUnxMJXHQWRQQX2eR94m5y1IZyDwBjV9FQ== + version "3.4.38" + resolved "https://registry.yarnpkg.com/@types/connect/-/connect-3.4.38.tgz#5ba7f3bc4fbbdeaff8dded952e5ff2cc53f8d858" + integrity sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug== dependencies: "@types/node" "*" "@types/eslint-scope@^3.7.3": - version "3.7.4" - resolved "https://registry.yarnpkg.com/@types/eslint-scope/-/eslint-scope-3.7.4.tgz#37fc1223f0786c39627068a12e94d6e6fc61de16" - integrity sha512-9K4zoImiZc3HlIp6AVUDE4CWYx22a+lhSZMYNpbjW04+YF0KWj4pJXnEMjdnFTiQibFFmElcsasJXDbdI/EPhA== + version "3.7.7" + resolved "https://registry.yarnpkg.com/@types/eslint-scope/-/eslint-scope-3.7.7.tgz#3108bd5f18b0cdb277c867b3dd449c9ed7079ac5" + integrity sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg== dependencies: "@types/eslint" "*" "@types/estree" "*" "@types/eslint@*": - version "8.4.10" - resolved "https://registry.yarnpkg.com/@types/eslint/-/eslint-8.4.10.tgz#19731b9685c19ed1552da7052b6f668ed7eb64bb" - integrity sha512-Sl/HOqN8NKPmhWo2VBEPm0nvHnu2LL3v9vKo8MEq0EtbJ4eVzGPl41VNPvn5E1i5poMk4/XD8UriLHpJvEP/Nw== + version "9.6.0" + resolved "https://registry.yarnpkg.com/@types/eslint/-/eslint-9.6.0.tgz#51d4fe4d0316da9e9f2c80884f2c20ed5fb022ff" + integrity sha512-gi6WQJ7cHRgZxtkQEoyHMppPjq9Kxo5Tjn2prSKDSmZrCz8TZ3jSRCeTJm+WoM+oB0WG37bRqLzaaU3q7JypGg== dependencies: "@types/estree" "*" "@types/json-schema" "*" -"@types/estree@*": - version "1.0.0" - resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.0.tgz#5fb2e536c1ae9bf35366eed879e827fa59ca41c2" - integrity sha512-WulqXMDUTYAXCjZnk6JtIHPigp55cVtDgDrO2gHRwhyJto21+1zbVCtOYB2L1F9w4qCQ0rOGWBnBe0FNTiEJIQ== - -"@types/estree@^0.0.51": - version "0.0.51" - resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.51.tgz#cfd70924a25a3fd32b218e5e420e6897e1ac4f40" - integrity sha512-CuPgU6f3eT/XgKKPqKd/gLZV1Xmvf1a2R5POBOGQa6uv82xpls89HU5zKeVoyR8XzHd1RGNOlQlvUe3CFkjWNQ== +"@types/estree@*", "@types/estree@^1.0.5": + version "1.0.5" + resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.5.tgz#a6ce3e556e00fd9895dd872dd172ad0d4bd687f4" + integrity sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw== -"@types/express-serve-static-core@*", "@types/express-serve-static-core@^4.17.18": - version "4.17.31" - resolved "https://registry.yarnpkg.com/@types/express-serve-static-core/-/express-serve-static-core-4.17.31.tgz#a1139efeab4e7323834bb0226e62ac019f474b2f" - integrity sha512-DxMhY+NAsTwMMFHBTtJFNp5qiHKJ7TeqOo23zVEM9alT1Ml27Q3xcTH0xwxn7Q0BbMcVEJOs/7aQtUWupUQN3Q== +"@types/express-serve-static-core@*", "@types/express-serve-static-core@^4.17.33": + version "4.19.5" + resolved "https://registry.yarnpkg.com/@types/express-serve-static-core/-/express-serve-static-core-4.19.5.tgz#218064e321126fcf9048d1ca25dd2465da55d9c6" + integrity sha512-y6W03tvrACO72aijJ5uF02FRq5cgDR9lUxddQ8vyF+GvmjJQqbzDcJngEjURc+ZsG31VI3hODNZJ2URj86pzmg== dependencies: "@types/node" "*" "@types/qs" "*" "@types/range-parser" "*" + "@types/send" "*" "@types/express@*", "@types/express@^4.17.13": - version "4.17.14" - resolved "https://registry.yarnpkg.com/@types/express/-/express-4.17.14.tgz#143ea0557249bc1b3b54f15db4c81c3d4eb3569c" - integrity sha512-TEbt+vaPFQ+xpxFLFssxUDXj5cWCxZJjIcB7Yg0k0GMHGtgtQgpvx/MUQUeAkNbA9AAGrwkAsoeItdTgS7FMyg== + version "4.17.21" + resolved "https://registry.yarnpkg.com/@types/express/-/express-4.17.21.tgz#c26d4a151e60efe0084b23dc3369ebc631ed192d" + integrity sha512-ejlPM315qwLpaQlQDTjPdsUFSc6ZsP4AN6AlWnogPjQ7CVi7PYF3YVz+CY3jE2pwYf7E/7HlDAN0rV2GxTG0HQ== dependencies: "@types/body-parser" "*" - "@types/express-serve-static-core" "^4.17.18" + "@types/express-serve-static-core" "^4.17.33" "@types/qs" "*" "@types/serve-static" "*" "@types/hast@^2.0.0": - version "2.3.4" - resolved "https://registry.yarnpkg.com/@types/hast/-/hast-2.3.4.tgz#8aa5ef92c117d20d974a82bdfb6a648b08c0bafc" - integrity sha512-wLEm0QvaoawEDoTRwzTXp4b4jpwiJDvR5KMnFnVodm3scufTlBOWRD6N1OBf9TZMhjlNsSfcO5V+7AF4+Vy+9g== + version "2.3.10" + resolved "https://registry.yarnpkg.com/@types/hast/-/hast-2.3.10.tgz#5c9d9e0b304bbb8879b857225c5ebab2d81d7643" + integrity sha512-McWspRw8xx8J9HurkVBfYj0xKoE25tOFlHGdx4MJ5xORQrMGZNqJhVQWaIbm6Oyla5kYOXtDiopzKRJzEOkwJw== dependencies: - "@types/unist" "*" + "@types/unist" "^2" "@types/history@^4.7.11": version "4.7.11" @@ -2182,36 +2088,41 @@ resolved "https://registry.yarnpkg.com/@types/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz#4fc33a00c1d0c16987b1a20cf92d20614c55ac35" integrity sha512-oh/6byDPnL1zeNXFrDXFLyZjkr1MsBG667IM792caf1L2UPOOMf65NFzjUH/ltyfwjAGfs1rsX1eftK0jC/KIg== +"@types/http-errors@*": + version "2.0.4" + resolved "https://registry.yarnpkg.com/@types/http-errors/-/http-errors-2.0.4.tgz#7eb47726c391b7345a6ec35ad7f4de469cf5ba4f" + integrity sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA== + "@types/http-proxy@^1.17.8": - version "1.17.9" - resolved "https://registry.yarnpkg.com/@types/http-proxy/-/http-proxy-1.17.9.tgz#7f0e7931343761efde1e2bf48c40f02f3f75705a" - integrity sha512-QsbSjA/fSk7xB+UXlCT3wHBy5ai9wOcNDWwZAtud+jXhwOM3l+EYZh8Lng4+/6n8uar0J7xILzqftJdJ/Wdfkw== + version "1.17.14" + resolved "https://registry.yarnpkg.com/@types/http-proxy/-/http-proxy-1.17.14.tgz#57f8ccaa1c1c3780644f8a94f9c6b5000b5e2eec" + integrity sha512-SSrD0c1OQzlFX7pGu1eXxSEjemej64aaNPRhhVYUGqXh0BtldAAx37MG8btcumvpgKyZp1F5Gn3JkktdxiFv6w== dependencies: "@types/node" "*" "@types/istanbul-lib-coverage@*", "@types/istanbul-lib-coverage@^2.0.0": - version "2.0.4" - resolved "https://registry.yarnpkg.com/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz#8467d4b3c087805d63580480890791277ce35c44" - integrity sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g== + version "2.0.6" + resolved "https://registry.yarnpkg.com/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz#7739c232a1fee9b4d3ce8985f314c0c6d33549d7" + integrity sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w== "@types/istanbul-lib-report@*": - version "3.0.0" - resolved "https://registry.yarnpkg.com/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz#c14c24f18ea8190c118ee7562b7ff99a36552686" - integrity sha512-plGgXAPfVKFoYfa9NpYDAkseG+g6Jr294RqeqcqDixSbU34MZVJRi/P+7Y8GDpzkEwLaGZZOpKIEmeVZNtKsrg== + version "3.0.3" + resolved "https://registry.yarnpkg.com/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.3.tgz#53047614ae72e19fc0401d872de3ae2b4ce350bf" + integrity sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA== dependencies: "@types/istanbul-lib-coverage" "*" "@types/istanbul-reports@^3.0.0": - version "3.0.1" - resolved "https://registry.yarnpkg.com/@types/istanbul-reports/-/istanbul-reports-3.0.1.tgz#9153fe98bba2bd565a63add9436d6f0d7f8468ff" - integrity sha512-c3mAZEuK0lvBp8tmuL74XRKn1+y2dcwOUpH7x4WrF6gk1GIgiluDRgMYQtw2OFcBvAJWlt6ASU3tSqxp0Uu0Aw== + version "3.0.4" + resolved "https://registry.yarnpkg.com/@types/istanbul-reports/-/istanbul-reports-3.0.4.tgz#0f03e3d2f670fbdac586e34b433783070cc16f54" + integrity sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ== dependencies: "@types/istanbul-lib-report" "*" "@types/json-schema@*", "@types/json-schema@^7.0.4", "@types/json-schema@^7.0.5", "@types/json-schema@^7.0.8", "@types/json-schema@^7.0.9": - version "7.0.11" - resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.11.tgz#d421b6c527a3037f7c84433fd2c4229e016863d3" - integrity sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ== + version "7.0.15" + resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.15.tgz#596a1747233694d50f6ad8a7869fcb6f56cf5841" + integrity sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA== "@types/katex@^0.11.0": version "0.11.1" @@ -2224,21 +2135,30 @@ integrity sha512-y0WSZBtBNQwcYipTU/BhgeFu1EZNlFvUNCmkMXV9kBQZq7/o5z82dNVyH3yy2Xv5zzeNeQoHSL4Xm06+EQiH+g== "@types/mdast@^3.0.0": - version "3.0.10" - resolved "https://registry.yarnpkg.com/@types/mdast/-/mdast-3.0.10.tgz#4724244a82a4598884cbbe9bcfd73dff927ee8af" - integrity sha512-W864tg/Osz1+9f4lrGTZpCSO5/z4608eUp19tbozkq2HJK6i3z1kT0H9tlADXuYIb1YYOBByU4Jsqkk75q48qA== + version "3.0.15" + resolved "https://registry.yarnpkg.com/@types/mdast/-/mdast-3.0.15.tgz#49c524a263f30ffa28b71ae282f813ed000ab9f5" + integrity sha512-LnwD+mUEfxWMa1QpDraczIn6k0Ee3SMicuYSSzS6ZYl2gKS09EClnJYGd8Du6rfc5r/GZEk5o1mRb8TaTj03sQ== dependencies: - "@types/unist" "*" + "@types/unist" "^2" -"@types/mime@*": - version "3.0.1" - resolved "https://registry.yarnpkg.com/@types/mime/-/mime-3.0.1.tgz#5f8f2bca0a5863cb69bc0b0acd88c96cb1d4ae10" - integrity sha512-Y4XFY5VJAuw0FgAqPNd6NNoV44jbq9Bz2L7Rh/J6jLTiHBSBJa9fxqQIvkIld4GsoDOcCbvzOUAbLPsSKKg+uA== +"@types/mime@^1": + version "1.3.5" + resolved "https://registry.yarnpkg.com/@types/mime/-/mime-1.3.5.tgz#1ef302e01cf7d2b5a0fa526790c9123bf1d06690" + integrity sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w== + +"@types/node-forge@^1.3.0": + version "1.3.11" + resolved "https://registry.yarnpkg.com/@types/node-forge/-/node-forge-1.3.11.tgz#0972ea538ddb0f4d9c2fa0ec5db5724773a604da" + integrity sha512-FQx220y22OKNTqaByeBGqHWYz4cl94tpcxeFdvBo3wjG6XPBuZ0BNgNZRV5J5TFmmcsJ4IzsLkmGRiQbnYsBEQ== + dependencies: + "@types/node" "*" "@types/node@*": - version "18.11.9" - resolved "https://registry.yarnpkg.com/@types/node/-/node-18.11.9.tgz#02d013de7058cea16d36168ef2fc653464cfbad4" - integrity sha512-CRpX21/kGdzjOpFsZSkcrXMGIBWMGNIHXXBVFSH+ggkftxg+XYP20TESbh+zFvFj3EQOl5byk0HTRn1IL6hbqg== + version "20.14.12" + resolved "https://registry.yarnpkg.com/@types/node/-/node-20.14.12.tgz#129d7c3a822cb49fc7ff661235f19cfefd422b49" + integrity sha512-r7wNXakLeSsGT0H1AU863vS2wa5wBOK4bWMjZz2wj+8nBx+m5PeIn0k8AloSLpRuiwdRQZwarZqHE4FNArPuJQ== + dependencies: + undici-types "~5.26.4" "@types/node@^17.0.5": version "17.0.45" @@ -2246,9 +2166,9 @@ integrity sha512-w+tIMs3rq2afQdsPJlODhoUEKzFP1ayaoyl1CcnwtIlsVe7K7bA1NGm4s3PraqTLlXnbIN84zuBlxBWo1u9BLw== "@types/parse-json@^4.0.0": - version "4.0.0" - resolved "https://registry.yarnpkg.com/@types/parse-json/-/parse-json-4.0.0.tgz#2f8bb441434d163b35fb8ffdccd7138927ffb8c0" - integrity sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA== + version "4.0.2" + resolved "https://registry.yarnpkg.com/@types/parse-json/-/parse-json-4.0.2.tgz#5950e50960793055845e956c427fc2b0d70c5239" + integrity sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw== "@types/parse5@^5.0.0": version "5.0.3" @@ -2256,28 +2176,28 @@ integrity sha512-kUNnecmtkunAoQ3CnjmMkzNU/gtxG8guhi+Fk2U/kOpIKjIMKnXGp4IJCgQJrXSgMsWYimYG4TGjz/UzbGEBTw== "@types/prop-types@*": - version "15.7.5" - resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.5.tgz#5f19d2b85a98e9558036f6a3cacc8819420f05cf" - integrity sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w== + version "15.7.12" + resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.12.tgz#12bb1e2be27293c1406acb6af1c3f3a1481d98c6" + integrity sha512-5zvhXYtRNRluoE/jAp4GVsSduVUzNWKkOZrCDBWYtE7biZywwdC2AcEzg+cSMLFRfVgeAFqpfNabiPjxFddV1Q== "@types/qs@*": - version "6.9.7" - resolved "https://registry.yarnpkg.com/@types/qs/-/qs-6.9.7.tgz#63bb7d067db107cc1e457c303bc25d511febf6cb" - integrity sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw== + version "6.9.15" + resolved "https://registry.yarnpkg.com/@types/qs/-/qs-6.9.15.tgz#adde8a060ec9c305a82de1babc1056e73bd64dce" + integrity sha512-uXHQKES6DQKKCLh441Xv/dwxOq1TVS3JPUMlEqoEglvlhR6Mxnlew/Xq/LRVHpLyk7iK3zODe1qYHIMltO7XGg== "@types/range-parser@*": - version "1.2.4" - resolved "https://registry.yarnpkg.com/@types/range-parser/-/range-parser-1.2.4.tgz#cd667bcfdd025213aafb7ca5915a932590acdcdc" - integrity sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw== + version "1.2.7" + resolved "https://registry.yarnpkg.com/@types/range-parser/-/range-parser-1.2.7.tgz#50ae4353eaaddc04044279812f52c8c65857dbcb" + integrity sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ== "@types/react-router-config@*", "@types/react-router-config@^5.0.6": - version "5.0.6" - resolved "https://registry.yarnpkg.com/@types/react-router-config/-/react-router-config-5.0.6.tgz#87c5c57e72d241db900d9734512c50ccec062451" - integrity sha512-db1mx37a1EJDf1XeX8jJN7R3PZABmJQXR8r28yUjVMFSjkmnQo6X6pOEEmNl+Tp2gYQOGPdYbFIipBtdElZ3Yg== + version "5.0.11" + resolved "https://registry.yarnpkg.com/@types/react-router-config/-/react-router-config-5.0.11.tgz#2761a23acc7905a66a94419ee40294a65aaa483a" + integrity sha512-WmSAg7WgqW7m4x8Mt4N6ZyKz0BubSj/2tVUMsAHp+Yd2AMwcSbeFq9WympT19p5heCFmF97R9eD5uUR/t4HEqw== dependencies: "@types/history" "^4.7.11" "@types/react" "*" - "@types/react-router" "*" + "@types/react-router" "^5.1.0" "@types/react-router-dom@*": version "5.3.3" @@ -2288,21 +2208,20 @@ "@types/react" "*" "@types/react-router" "*" -"@types/react-router@*": - version "5.1.19" - resolved "https://registry.yarnpkg.com/@types/react-router/-/react-router-5.1.19.tgz#9b404246fba7f91474d7008a3d48c17b6e075ad6" - integrity sha512-Fv/5kb2STAEMT3wHzdKQK2z8xKq38EDIGVrutYLmQVVLe+4orDFquU52hQrULnEHinMKv9FSA6lf9+uNT1ITtA== +"@types/react-router@*", "@types/react-router@^5.1.0": + version "5.1.20" + resolved "https://registry.yarnpkg.com/@types/react-router/-/react-router-5.1.20.tgz#88eccaa122a82405ef3efbcaaa5dcdd9f021387c" + integrity sha512-jGjmu/ZqS7FjSH6owMcD5qpq19+1RS9DeVRqfl1FeBMxTDQAGwlMWOcs52NDoXaNKyG3d1cYQFMs9rCrb88o9Q== dependencies: "@types/history" "^4.7.11" "@types/react" "*" "@types/react@*": - version "18.0.25" - resolved "https://registry.yarnpkg.com/@types/react/-/react-18.0.25.tgz#8b1dcd7e56fe7315535a4af25435e0bb55c8ae44" - integrity sha512-xD6c0KDT4m7n9uD4ZHi02lzskaiqcBxf4zi+tXZY98a04wvc0hi/TcCPC2FOESZi51Nd7tlUeOJY8RofL799/g== + version "18.3.3" + resolved "https://registry.yarnpkg.com/@types/react/-/react-18.3.3.tgz#9679020895318b0915d7a3ab004d92d33375c45f" + integrity sha512-hti/R0pS0q1/xx+TsI73XIqk26eBsISZ2R0wUijXIngRK9R/e7Xw/cXVxQK7R5JjW+SV4zGcn5hXjudkN/pLIw== dependencies: "@types/prop-types" "*" - "@types/scheduler" "*" csstype "^3.0.2" "@types/retry@0.12.0": @@ -2311,187 +2230,186 @@ integrity sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA== "@types/sax@^1.2.1": - version "1.2.4" - resolved "https://registry.yarnpkg.com/@types/sax/-/sax-1.2.4.tgz#8221affa7f4f3cb21abd22f244cfabfa63e6a69e" - integrity sha512-pSAff4IAxJjfAXUG6tFkO7dsSbTmf8CtUpfhhZ5VhkRpC4628tJhh3+V6H1E+/Gs9piSzYKT5yzHO5M4GG9jkw== + version "1.2.7" + resolved "https://registry.yarnpkg.com/@types/sax/-/sax-1.2.7.tgz#ba5fe7df9aa9c89b6dff7688a19023dd2963091d" + integrity sha512-rO73L89PJxeYM3s3pPPjiPgVVcymqU490g0YO5n5By0k2Erzj6tay/4lr1CHAAU4JyOWd1rpQ8bCf6cZfHU96A== dependencies: "@types/node" "*" -"@types/scheduler@*": - version "0.16.2" - resolved "https://registry.yarnpkg.com/@types/scheduler/-/scheduler-0.16.2.tgz#1a62f89525723dde24ba1b01b092bf5df8ad4d39" - integrity sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew== +"@types/send@*": + version "0.17.4" + resolved "https://registry.yarnpkg.com/@types/send/-/send-0.17.4.tgz#6619cd24e7270793702e4e6a4b958a9010cfc57a" + integrity sha512-x2EM6TJOybec7c52BX0ZspPodMsQUd5L6PRwOunVyVUhXiBSKf3AezDL8Dgvgt5o0UfKNfuA0eMLr2wLT4AiBA== + dependencies: + "@types/mime" "^1" + "@types/node" "*" "@types/serve-index@^1.9.1": - version "1.9.1" - resolved "https://registry.yarnpkg.com/@types/serve-index/-/serve-index-1.9.1.tgz#1b5e85370a192c01ec6cec4735cf2917337a6278" - integrity sha512-d/Hs3nWDxNL2xAczmOVZNj92YZCS6RGxfBPjKzuu/XirCgXdpKEb88dYNbrYGint6IVWLNP+yonwVAuRC0T2Dg== + version "1.9.4" + resolved "https://registry.yarnpkg.com/@types/serve-index/-/serve-index-1.9.4.tgz#e6ae13d5053cb06ed36392110b4f9a49ac4ec898" + integrity sha512-qLpGZ/c2fhSs5gnYsQxtDEq3Oy8SXPClIXkW5ghvAvsNuVSA8k+gCONcUCS/UjLEYvYps+e8uBtfgXgvhwfNug== dependencies: "@types/express" "*" "@types/serve-static@*", "@types/serve-static@^1.13.10": - version "1.15.0" - resolved "https://registry.yarnpkg.com/@types/serve-static/-/serve-static-1.15.0.tgz#c7930ff61afb334e121a9da780aac0d9b8f34155" - integrity sha512-z5xyF6uh8CbjAu9760KDKsH2FcDxZ2tFCsA4HIMWE6IkiYMXfVoa+4f9KX+FN0ZLsaMw1WNG2ETLA6N+/YA+cg== + version "1.15.7" + resolved "https://registry.yarnpkg.com/@types/serve-static/-/serve-static-1.15.7.tgz#22174bbd74fb97fe303109738e9b5c2f3064f714" + integrity sha512-W8Ym+h8nhuRwaKPaDw34QUkwsGi6Rc4yYqvKFo5rm2FUEhCFbzVWrxXUxuKK8TASjWsysJY0nsmNCGhCOIsrOw== dependencies: - "@types/mime" "*" + "@types/http-errors" "*" "@types/node" "*" + "@types/send" "*" "@types/sockjs@^0.3.33": - version "0.3.33" - resolved "https://registry.yarnpkg.com/@types/sockjs/-/sockjs-0.3.33.tgz#570d3a0b99ac995360e3136fd6045113b1bd236f" - integrity sha512-f0KEEe05NvUnat+boPTZ0dgaLZ4SfSouXUgv5noUiefG2ajgKjmETo9ZJyuqsl7dfl2aHlLJUiki6B4ZYldiiw== + version "0.3.36" + resolved "https://registry.yarnpkg.com/@types/sockjs/-/sockjs-0.3.36.tgz#ce322cf07bcc119d4cbf7f88954f3a3bd0f67535" + integrity sha512-MK9V6NzAS1+Ud7JV9lJLFqW85VbC9dq3LmwZCuBe4wBDgKC0Kj/jd8Xl+nSviU+Qc3+m7umHHyHg//2KSa0a0Q== dependencies: "@types/node" "*" -"@types/unist@*", "@types/unist@^2.0.0", "@types/unist@^2.0.2", "@types/unist@^2.0.3": - version "2.0.6" - resolved "https://registry.yarnpkg.com/@types/unist/-/unist-2.0.6.tgz#250a7b16c3b91f672a24552ec64678eeb1d3a08d" - integrity sha512-PBjIUxZHOuj0R15/xuwJYjFi+KZdNFrehocChv4g5hu6aFroHue8m0lBP0POdK2nKzbw0cgV1mws8+V/JAcEkQ== - -"@types/web@^0.0.46": - version "0.0.46" - resolved "https://registry.yarnpkg.com/@types/web/-/web-0.0.46.tgz#7f447e5eb3c511dbdc6f69e435f7ec4311d18b48" - integrity sha512-ki0OmbjSdAEfvmy5AYWFpMkRsPW+6h4ibQ4tzk8SJsS9dkrrD3B/U1eVvdNNWxAzntjq6o2sjSia6UBCoPH+Yg== +"@types/unist@^2", "@types/unist@^2.0.0", "@types/unist@^2.0.2", "@types/unist@^2.0.3": + version "2.0.10" + resolved "https://registry.yarnpkg.com/@types/unist/-/unist-2.0.10.tgz#04ffa7f406ab628f7f7e97ca23e290cd8ab15efc" + integrity sha512-IfYcSBWE3hLpBg8+X2SEa8LVkJdJEkT2Ese2aaLs3ptGdVtABxndrMaxuFlQ1qdFf9Q5rDvDpxI3WwgvKFAsQA== -"@types/ws@^8.5.1": - version "8.5.3" - resolved "https://registry.yarnpkg.com/@types/ws/-/ws-8.5.3.tgz#7d25a1ffbecd3c4f2d35068d0b283c037003274d" - integrity sha512-6YOoWjruKj1uLf3INHH7D3qTXwFfEsg1kf3c0uDdSBJwfa/llkwIjrAGV7j7mVgGNbzTQ3HiHKKDXl6bJPD97w== +"@types/ws@^8.5.5": + version "8.5.11" + resolved "https://registry.yarnpkg.com/@types/ws/-/ws-8.5.11.tgz#90ad17b3df7719ce3e6bc32f83ff954d38656508" + integrity sha512-4+q7P5h3SpJxaBft0Dzpbr6lmMaqh0Jr2tbhJZ/luAwvD7ohSCniYkwz/pLxuT2h0EOa6QADgJj1Ko+TzRfZ+w== dependencies: "@types/node" "*" "@types/yargs-parser@*": - version "21.0.0" - resolved "https://registry.yarnpkg.com/@types/yargs-parser/-/yargs-parser-21.0.0.tgz#0c60e537fa790f5f9472ed2776c2b71ec117351b" - integrity sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA== + version "21.0.3" + resolved "https://registry.yarnpkg.com/@types/yargs-parser/-/yargs-parser-21.0.3.tgz#815e30b786d2e8f0dcd85fd5bcf5e1a04d008f15" + integrity sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ== "@types/yargs@^17.0.8": - version "17.0.13" - resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-17.0.13.tgz#34cced675ca1b1d51fcf4d34c3c6f0fa142a5c76" - integrity sha512-9sWaruZk2JGxIQU+IhI1fhPYRcQ0UuTNuKuCW9bR5fp7qi2Llf7WDzNa17Cy7TKnh3cdxDOiyTu6gaLS0eDatg== + version "17.0.32" + resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-17.0.32.tgz#030774723a2f7faafebf645f4e5a48371dca6229" + integrity sha512-xQ67Yc/laOG5uMfX/093MRlGGCIBzZMarVa+gfNKJxWAIgykYpVGkBdbqEzGDDfCrVUj6Hiff4mTZ5BA6TmAog== dependencies: "@types/yargs-parser" "*" -"@webassemblyjs/ast@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.11.1.tgz#2bfd767eae1a6996f432ff7e8d7fc75679c0b6a7" - integrity sha512-ukBh14qFLjxTQNTXocdyksN5QdM28S1CxHt2rdskFyL+xFV7VremuBLVbmCePj+URalXBENx/9Lm7lnhihtCSw== +"@webassemblyjs/ast@1.12.1", "@webassemblyjs/ast@^1.12.1": + version "1.12.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.12.1.tgz#bb16a0e8b1914f979f45864c23819cc3e3f0d4bb" + integrity sha512-EKfMUOPRRUTy5UII4qJDGPpqfwjOmZ5jeGFwid9mnoqIFK+e0vqoi1qH56JpmZSzEL53jKnNzScdmftJyG5xWg== dependencies: - "@webassemblyjs/helper-numbers" "1.11.1" - "@webassemblyjs/helper-wasm-bytecode" "1.11.1" + "@webassemblyjs/helper-numbers" "1.11.6" + "@webassemblyjs/helper-wasm-bytecode" "1.11.6" -"@webassemblyjs/floating-point-hex-parser@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.1.tgz#f6c61a705f0fd7a6aecaa4e8198f23d9dc179e4f" - integrity sha512-iGRfyc5Bq+NnNuX8b5hwBrRjzf0ocrJPI6GWFodBFzmFnyvrQ83SHKhmilCU/8Jv67i4GJZBMhEzltxzcNagtQ== +"@webassemblyjs/floating-point-hex-parser@1.11.6": + version "1.11.6" + resolved "https://registry.yarnpkg.com/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.6.tgz#dacbcb95aff135c8260f77fa3b4c5fea600a6431" + integrity sha512-ejAj9hfRJ2XMsNHk/v6Fu2dGS+i4UaXBXGemOfQ/JfQ6mdQg/WXtwleQRLLS4OvfDhv8rYnVwH27YJLMyYsxhw== -"@webassemblyjs/helper-api-error@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.1.tgz#1a63192d8788e5c012800ba6a7a46c705288fd16" - integrity sha512-RlhS8CBCXfRUR/cwo2ho9bkheSXG0+NwooXcc3PAILALf2QLdFyj7KGsKRbVc95hZnhnERon4kW/D3SZpp6Tcg== +"@webassemblyjs/helper-api-error@1.11.6": + version "1.11.6" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.6.tgz#6132f68c4acd59dcd141c44b18cbebbd9f2fa768" + integrity sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q== -"@webassemblyjs/helper-buffer@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.1.tgz#832a900eb444884cde9a7cad467f81500f5e5ab5" - integrity sha512-gwikF65aDNeeXa8JxXa2BAk+REjSyhrNC9ZwdT0f8jc4dQQeDQ7G4m0f2QCLPJiMTTO6wfDmRmj/pW0PsUvIcA== +"@webassemblyjs/helper-buffer@1.12.1": + version "1.12.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-buffer/-/helper-buffer-1.12.1.tgz#6df20d272ea5439bf20ab3492b7fb70e9bfcb3f6" + integrity sha512-nzJwQw99DNDKr9BVCOZcLuJJUlqkJh+kVzVl6Fmq/tI5ZtEyWT1KZMyOXltXLZJmDtvLCDgwsyrkohEtopTXCw== -"@webassemblyjs/helper-numbers@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.1.tgz#64d81da219fbbba1e3bd1bfc74f6e8c4e10a62ae" - integrity sha512-vDkbxiB8zfnPdNK9Rajcey5C0w+QJugEglN0of+kmO8l7lDb77AnlKYQF7aarZuCrv+l0UvqL+68gSDr3k9LPQ== +"@webassemblyjs/helper-numbers@1.11.6": + version "1.11.6" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.6.tgz#cbce5e7e0c1bd32cf4905ae444ef64cea919f1b5" + integrity sha512-vUIhZ8LZoIWHBohiEObxVm6hwP034jwmc9kuq5GdHZH0wiLVLIPcMCdpJzG4C11cHoQ25TFIQj9kaVADVX7N3g== dependencies: - "@webassemblyjs/floating-point-hex-parser" "1.11.1" - "@webassemblyjs/helper-api-error" "1.11.1" + "@webassemblyjs/floating-point-hex-parser" "1.11.6" + "@webassemblyjs/helper-api-error" "1.11.6" "@xtuc/long" "4.2.2" -"@webassemblyjs/helper-wasm-bytecode@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.1.tgz#f328241e41e7b199d0b20c18e88429c4433295e1" - integrity sha512-PvpoOGiJwXeTrSf/qfudJhwlvDQxFgelbMqtq52WWiXC6Xgg1IREdngmPN3bs4RoO83PnL/nFrxucXj1+BX62Q== +"@webassemblyjs/helper-wasm-bytecode@1.11.6": + version "1.11.6" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.6.tgz#bb2ebdb3b83aa26d9baad4c46d4315283acd51e9" + integrity sha512-sFFHKwcmBprO9e7Icf0+gddyWYDViL8bpPjJJl0WHxCdETktXdmtWLGVzoHbqUcY4Be1LkNfwTmXOJUFZYSJdA== -"@webassemblyjs/helper-wasm-section@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.1.tgz#21ee065a7b635f319e738f0dd73bfbda281c097a" - integrity sha512-10P9No29rYX1j7F3EVPX3JvGPQPae+AomuSTPiF9eBQeChHI6iqjMIwR9JmOJXwpnn/oVGDk7I5IlskuMwU/pg== +"@webassemblyjs/helper-wasm-section@1.12.1": + version "1.12.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.12.1.tgz#3da623233ae1a60409b509a52ade9bc22a37f7bf" + integrity sha512-Jif4vfB6FJlUlSbgEMHUyk1j234GTNG9dBJ4XJdOySoj518Xj0oGsNi59cUQF4RRMS9ouBUxDDdyBVfPTypa5g== dependencies: - "@webassemblyjs/ast" "1.11.1" - "@webassemblyjs/helper-buffer" "1.11.1" - "@webassemblyjs/helper-wasm-bytecode" "1.11.1" - "@webassemblyjs/wasm-gen" "1.11.1" + "@webassemblyjs/ast" "1.12.1" + "@webassemblyjs/helper-buffer" "1.12.1" + "@webassemblyjs/helper-wasm-bytecode" "1.11.6" + "@webassemblyjs/wasm-gen" "1.12.1" -"@webassemblyjs/ieee754@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/ieee754/-/ieee754-1.11.1.tgz#963929e9bbd05709e7e12243a099180812992614" - integrity sha512-hJ87QIPtAMKbFq6CGTkZYJivEwZDbQUgYd3qKSadTNOhVY7p+gfP6Sr0lLRVTaG1JjFj+r3YchoqRYxNH3M0GQ== +"@webassemblyjs/ieee754@1.11.6": + version "1.11.6" + resolved "https://registry.yarnpkg.com/@webassemblyjs/ieee754/-/ieee754-1.11.6.tgz#bb665c91d0b14fffceb0e38298c329af043c6e3a" + integrity sha512-LM4p2csPNvbij6U1f19v6WR56QZ8JcHg3QIJTlSwzFcmx6WSORicYj6I63f9yU1kEUtrpG+kjkiIAkevHpDXrg== dependencies: "@xtuc/ieee754" "^1.2.0" -"@webassemblyjs/leb128@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/leb128/-/leb128-1.11.1.tgz#ce814b45574e93d76bae1fb2644ab9cdd9527aa5" - integrity sha512-BJ2P0hNZ0u+Th1YZXJpzW6miwqQUGcIHT1G/sf72gLVD9DZ5AdYTqPNbHZh6K1M5VmKvFXwGSWZADz+qBWxeRw== +"@webassemblyjs/leb128@1.11.6": + version "1.11.6" + resolved "https://registry.yarnpkg.com/@webassemblyjs/leb128/-/leb128-1.11.6.tgz#70e60e5e82f9ac81118bc25381a0b283893240d7" + integrity sha512-m7a0FhE67DQXgouf1tbN5XQcdWoNgaAuoULHIfGFIEVKA6tu/edls6XnIlkmS6FrXAquJRPni3ZZKjw6FSPjPQ== dependencies: "@xtuc/long" "4.2.2" -"@webassemblyjs/utf8@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/utf8/-/utf8-1.11.1.tgz#d1f8b764369e7c6e6bae350e854dec9a59f0a3ff" - integrity sha512-9kqcxAEdMhiwQkHpkNiorZzqpGrodQQ2IGrHHxCy+Ozng0ofyMA0lTqiLkVs1uzTRejX+/O0EOT7KxqVPuXosQ== - -"@webassemblyjs/wasm-edit@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.1.tgz#ad206ebf4bf95a058ce9880a8c092c5dec8193d6" - integrity sha512-g+RsupUC1aTHfR8CDgnsVRVZFJqdkFHpsHMfJuWQzWU3tvnLC07UqHICfP+4XyL2tnr1amvl1Sdp06TnYCmVkA== - dependencies: - "@webassemblyjs/ast" "1.11.1" - "@webassemblyjs/helper-buffer" "1.11.1" - "@webassemblyjs/helper-wasm-bytecode" "1.11.1" - "@webassemblyjs/helper-wasm-section" "1.11.1" - "@webassemblyjs/wasm-gen" "1.11.1" - "@webassemblyjs/wasm-opt" "1.11.1" - "@webassemblyjs/wasm-parser" "1.11.1" - "@webassemblyjs/wast-printer" "1.11.1" - -"@webassemblyjs/wasm-gen@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.1.tgz#86c5ea304849759b7d88c47a32f4f039ae3c8f76" - integrity sha512-F7QqKXwwNlMmsulj6+O7r4mmtAlCWfO/0HdgOxSklZfQcDu0TpLiD1mRt/zF25Bk59FIjEuGAIyn5ei4yMfLhA== - dependencies: - "@webassemblyjs/ast" "1.11.1" - "@webassemblyjs/helper-wasm-bytecode" "1.11.1" - "@webassemblyjs/ieee754" "1.11.1" - "@webassemblyjs/leb128" "1.11.1" - "@webassemblyjs/utf8" "1.11.1" - -"@webassemblyjs/wasm-opt@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.1.tgz#657b4c2202f4cf3b345f8a4c6461c8c2418985f2" - integrity sha512-VqnkNqnZlU5EB64pp1l7hdm3hmQw7Vgqa0KF/KCNO9sIpI6Fk6brDEiX+iCOYrvMuBWDws0NkTOxYEb85XQHHw== - dependencies: - "@webassemblyjs/ast" "1.11.1" - "@webassemblyjs/helper-buffer" "1.11.1" - "@webassemblyjs/wasm-gen" "1.11.1" - "@webassemblyjs/wasm-parser" "1.11.1" - -"@webassemblyjs/wasm-parser@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.1.tgz#86ca734534f417e9bd3c67c7a1c75d8be41fb199" - integrity sha512-rrBujw+dJu32gYB7/Lup6UhdkPx9S9SnobZzRVL7VcBH9Bt9bCBLEuX/YXOOtBsOZ4NQrRykKhffRWHvigQvOA== - dependencies: - "@webassemblyjs/ast" "1.11.1" - "@webassemblyjs/helper-api-error" "1.11.1" - "@webassemblyjs/helper-wasm-bytecode" "1.11.1" - "@webassemblyjs/ieee754" "1.11.1" - "@webassemblyjs/leb128" "1.11.1" - "@webassemblyjs/utf8" "1.11.1" - -"@webassemblyjs/wast-printer@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wast-printer/-/wast-printer-1.11.1.tgz#d0c73beda8eec5426f10ae8ef55cee5e7084c2f0" - integrity sha512-IQboUWM4eKzWW+N/jij2sRatKMh99QEelo3Eb2q0qXkvPRISAj8Qxtmw5itwqK+TTkBuUIE45AxYPToqPtL5gg== - dependencies: - "@webassemblyjs/ast" "1.11.1" +"@webassemblyjs/utf8@1.11.6": + version "1.11.6" + resolved "https://registry.yarnpkg.com/@webassemblyjs/utf8/-/utf8-1.11.6.tgz#90f8bc34c561595fe156603be7253cdbcd0fab5a" + integrity sha512-vtXf2wTQ3+up9Zsg8sa2yWiQpzSsMyXj0qViVP6xKGCUT8p8YJ6HqI7l5eCnWx1T/FYdsv07HQs2wTFbbof/RA== + +"@webassemblyjs/wasm-edit@^1.12.1": + version "1.12.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-edit/-/wasm-edit-1.12.1.tgz#9f9f3ff52a14c980939be0ef9d5df9ebc678ae3b" + integrity sha512-1DuwbVvADvS5mGnXbE+c9NfA8QRcZ6iKquqjjmR10k6o+zzsRVesil54DKexiowcFCPdr/Q0qaMgB01+SQ1u6g== + dependencies: + "@webassemblyjs/ast" "1.12.1" + "@webassemblyjs/helper-buffer" "1.12.1" + "@webassemblyjs/helper-wasm-bytecode" "1.11.6" + "@webassemblyjs/helper-wasm-section" "1.12.1" + "@webassemblyjs/wasm-gen" "1.12.1" + "@webassemblyjs/wasm-opt" "1.12.1" + "@webassemblyjs/wasm-parser" "1.12.1" + "@webassemblyjs/wast-printer" "1.12.1" + +"@webassemblyjs/wasm-gen@1.12.1": + version "1.12.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-gen/-/wasm-gen-1.12.1.tgz#a6520601da1b5700448273666a71ad0a45d78547" + integrity sha512-TDq4Ojh9fcohAw6OIMXqiIcTq5KUXTGRkVxbSo1hQnSy6lAM5GSdfwWeSxpAo0YzgsgF182E/U0mDNhuA0tW7w== + dependencies: + "@webassemblyjs/ast" "1.12.1" + "@webassemblyjs/helper-wasm-bytecode" "1.11.6" + "@webassemblyjs/ieee754" "1.11.6" + "@webassemblyjs/leb128" "1.11.6" + "@webassemblyjs/utf8" "1.11.6" + +"@webassemblyjs/wasm-opt@1.12.1": + version "1.12.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-opt/-/wasm-opt-1.12.1.tgz#9e6e81475dfcfb62dab574ac2dda38226c232bc5" + integrity sha512-Jg99j/2gG2iaz3hijw857AVYekZe2SAskcqlWIZXjji5WStnOpVoat3gQfT/Q5tb2djnCjBtMocY/Su1GfxPBg== + dependencies: + "@webassemblyjs/ast" "1.12.1" + "@webassemblyjs/helper-buffer" "1.12.1" + "@webassemblyjs/wasm-gen" "1.12.1" + "@webassemblyjs/wasm-parser" "1.12.1" + +"@webassemblyjs/wasm-parser@1.12.1", "@webassemblyjs/wasm-parser@^1.12.1": + version "1.12.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-parser/-/wasm-parser-1.12.1.tgz#c47acb90e6f083391e3fa61d113650eea1e95937" + integrity sha512-xikIi7c2FHXysxXe3COrVUPSheuBtpcfhbpFj4gmu7KRLYOzANztwUU0IbsqvMqzuNK2+glRGWCEqZo1WCLyAQ== + dependencies: + "@webassemblyjs/ast" "1.12.1" + "@webassemblyjs/helper-api-error" "1.11.6" + "@webassemblyjs/helper-wasm-bytecode" "1.11.6" + "@webassemblyjs/ieee754" "1.11.6" + "@webassemblyjs/leb128" "1.11.6" + "@webassemblyjs/utf8" "1.11.6" + +"@webassemblyjs/wast-printer@1.12.1": + version "1.12.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wast-printer/-/wast-printer-1.12.1.tgz#bcecf661d7d1abdaf989d8341a4833e33e2b31ac" + integrity sha512-+X4WAlOisVWQMikjbcvY2e0rwPsKQ9F688lksZhBcPycBBuii3O7m8FACbDMWDojpAqvjIncrG8J0XHKyQfVeA== + dependencies: + "@webassemblyjs/ast" "1.12.1" "@xtuc/long" "4.2.2" "@xtuc/ieee754@^1.2.0": @@ -2504,7 +2422,7 @@ resolved "https://registry.yarnpkg.com/@xtuc/long/-/long-4.2.2.tgz#d291c6a4e97989b5c61d9acf396ae4fe133a718d" integrity sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ== -abab@^2.0.5, abab@^2.0.6: +abab@^2.0.6: version "2.0.6" resolved "https://registry.yarnpkg.com/abab/-/abab-2.0.6.tgz#41b80f2c871d19686216b82309231cfd3cb3d291" integrity sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA== @@ -2517,43 +2435,35 @@ accepts@~1.3.4, accepts@~1.3.5, accepts@~1.3.8: mime-types "~2.1.34" negotiator "0.6.3" -acorn-globals@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/acorn-globals/-/acorn-globals-6.0.0.tgz#46cdd39f0f8ff08a876619b55f5ac8a6dc770b45" - integrity sha512-ZQl7LOWaF5ePqqcX4hLuv/bLXYQNfNWw2c0/yX/TsPRKamzHcTGQnlCjHT3TsmkOUVEPS3crCxiPfdzE/Trlhg== +acorn-globals@^7.0.0: + version "7.0.1" + resolved "https://registry.yarnpkg.com/acorn-globals/-/acorn-globals-7.0.1.tgz#0dbf05c44fa7c94332914c02066d5beff62c40c3" + integrity sha512-umOSDSDrfHbTNPuNpC2NSnnA3LUrqpevPb4T9jRx4MagXNS0rs+gwiTcAvqCRmsD6utzsrzNt+ebm00SNWiC3Q== dependencies: - acorn "^7.1.1" - acorn-walk "^7.1.1" - -acorn-import-assertions@^1.7.6: - version "1.8.0" - resolved "https://registry.yarnpkg.com/acorn-import-assertions/-/acorn-import-assertions-1.8.0.tgz#ba2b5939ce62c238db6d93d81c9b111b29b855e9" - integrity sha512-m7VZ3jwz4eK6A4Vtt8Ew1/mNbP24u0FhdyfA7fSvnJR6LMdfOYnmuIrrJAgrYfYJ10F/otaHTtrtrtmHdMNzEw== - -acorn-walk@^7.1.1: - version "7.2.0" - resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-7.2.0.tgz#0de889a601203909b0fbe07b8938dc21d2e967bc" - integrity sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA== + acorn "^8.1.0" + acorn-walk "^8.0.2" -acorn-walk@^8.0.0: - version "8.2.0" - resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-8.2.0.tgz#741210f2e2426454508853a2f44d0ab83b7f69c1" - integrity sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA== +acorn-import-attributes@^1.9.5: + version "1.9.5" + resolved "https://registry.yarnpkg.com/acorn-import-attributes/-/acorn-import-attributes-1.9.5.tgz#7eb1557b1ba05ef18b5ed0ec67591bfab04688ef" + integrity sha512-n02Vykv5uA3eHGM/Z2dQrcD56kL8TyDb2p1+0P83PClMnC/nc+anbQRhIOWnSq4Ke/KvDPrY3C9hDtC/A3eHnQ== -acorn@^7.1.1: - version "7.4.1" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.4.1.tgz#feaed255973d2e77555b83dbc08851a6c63520fa" - integrity sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A== +acorn-walk@^8.0.0, acorn-walk@^8.0.2: + version "8.3.3" + resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-8.3.3.tgz#9caeac29eefaa0c41e3d4c65137de4d6f34df43e" + integrity sha512-MxXdReSRhGO7VlFe1bRG/oI7/mdLV9B9JJT0N8vZOhF7gFRR5l3M8W9G8JxmKV+JC5mGqJ0QvqfSOLsCPa4nUw== + dependencies: + acorn "^8.11.0" -acorn@^8.0.4, acorn@^8.5.0, acorn@^8.7.1: - version "8.8.1" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.8.1.tgz#0a3f9cbecc4ec3bea6f0a80b66ae8dd2da250b73" - integrity sha512-7zFpHzhnqYKrkYdUjF1HI1bzd0VygEGX8lFk4k5zVMqHEoES+P+7TKI+EvLO9WVMJ8eekdO0aDEK044xTXwPPA== +acorn@^8.0.4, acorn@^8.1.0, acorn@^8.11.0, acorn@^8.7.1, acorn@^8.8.1, acorn@^8.8.2: + version "8.12.1" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.12.1.tgz#71616bdccbe25e27a54439e0046e89ca76df2248" + integrity sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg== address@^1.0.1, address@^1.1.2: - version "1.2.1" - resolved "https://registry.yarnpkg.com/address/-/address-1.2.1.tgz#25bb61095b7522d65b357baa11bc05492d4c8acd" - integrity sha512-B+6bi5D34+fDYENiH5qOlA0cV2rAGKuWZ9LeyUUehbXy8e0VS9e498yO0Jeeh+iM+6KbfudHTFjXw2MmJD4QRA== + version "1.2.2" + resolved "https://registry.yarnpkg.com/address/-/address-1.2.2.tgz#2b5248dac5485a6390532c6a517fda2e3faac89e" + integrity sha512-4B/qKCfeE/ODUaAUpSwfzazo5x29WD4r3vXiWsB7I2mSDAihwEqKO+g8GELZUQSSAo5e1XTYh3ZVfLyxBc12nA== agent-base@6: version "6.0.2" @@ -2582,7 +2492,7 @@ ajv-keywords@^3.4.1, ajv-keywords@^3.5.2: resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-3.5.2.tgz#31f29da5ab6e00d1c2d329acf7b5929614d5014d" integrity sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ== -ajv-keywords@^5.0.0: +ajv-keywords@^5.1.0: version "5.1.0" resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-5.1.0.tgz#69d4d385a4733cdbeab44964a1170a88f87f0e16" integrity sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw== @@ -2599,42 +2509,43 @@ ajv@^6.12.2, ajv@^6.12.4, ajv@^6.12.5: json-schema-traverse "^0.4.1" uri-js "^4.2.2" -ajv@^8.0.0, ajv@^8.8.0: - version "8.11.2" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.11.2.tgz#aecb20b50607acf2569b6382167b65a96008bb78" - integrity sha512-E4bfmKAhGiSTvMfL1Myyycaub+cUEU2/IvpylXkUu7CHBkBj1f/ikdzbD7YQ6FKUbixDxeYvB/xY4fvyroDlQg== +ajv@^8.0.0, ajv@^8.9.0: + version "8.17.1" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.17.1.tgz#37d9a5c776af6bc92d7f4f9510eba4c0a60d11a6" + integrity sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g== dependencies: - fast-deep-equal "^3.1.1" + fast-deep-equal "^3.1.3" + fast-uri "^3.0.1" json-schema-traverse "^1.0.0" require-from-string "^2.0.2" - uri-js "^4.2.2" algoliasearch-helper@^3.10.0: - version "3.11.1" - resolved "https://registry.yarnpkg.com/algoliasearch-helper/-/algoliasearch-helper-3.11.1.tgz#d83ab7f1a2a374440686ef7a144b3c288b01188a" - integrity sha512-mvsPN3eK4E0bZG0/WlWJjeqe/bUD2KOEVOl0GyL/TGXn6wcpZU8NOuztGHCUKXkyg5gq6YzUakVTmnmSSO5Yiw== + version "3.22.3" + resolved "https://registry.yarnpkg.com/algoliasearch-helper/-/algoliasearch-helper-3.22.3.tgz#7c67a1a87c3adb0b52ef726a3de3c0b0edcbb5d1" + integrity sha512-2eoEz8mG4KHE+DzfrBTrCmDPxVXv7aZZWPojAJFtARpxxMO6lkos1dJ+XDCXdPvq7q3tpYWRi6xXmVQikejtpA== dependencies: "@algolia/events" "^4.0.1" -algoliasearch@^4.0.0, algoliasearch@^4.13.1: - version "4.14.2" - resolved "https://registry.yarnpkg.com/algoliasearch/-/algoliasearch-4.14.2.tgz#63f142583bfc3a9bd3cd4a1b098bf6fe58e56f6c" - integrity sha512-ngbEQonGEmf8dyEh5f+uOIihv4176dgbuOZspiuhmTTBRBuzWu3KCGHre6uHj5YyuC7pNvQGzB6ZNJyZi0z+Sg== - dependencies: - "@algolia/cache-browser-local-storage" "4.14.2" - "@algolia/cache-common" "4.14.2" - "@algolia/cache-in-memory" "4.14.2" - "@algolia/client-account" "4.14.2" - "@algolia/client-analytics" "4.14.2" - "@algolia/client-common" "4.14.2" - "@algolia/client-personalization" "4.14.2" - "@algolia/client-search" "4.14.2" - "@algolia/logger-common" "4.14.2" - "@algolia/logger-console" "4.14.2" - "@algolia/requester-browser-xhr" "4.14.2" - "@algolia/requester-common" "4.14.2" - "@algolia/requester-node-http" "4.14.2" - "@algolia/transporter" "4.14.2" +algoliasearch@^4.13.1, algoliasearch@^4.19.1: + version "4.24.0" + resolved "https://registry.yarnpkg.com/algoliasearch/-/algoliasearch-4.24.0.tgz#b953b3e2309ef8f25da9de311b95b994ac918275" + integrity sha512-bf0QV/9jVejssFBmz2HQLxUadxk574t4iwjCKp5E7NBzwKkrDEhKPISIIjAU/p6K5qDx3qoeh4+26zWN1jmw3g== + dependencies: + "@algolia/cache-browser-local-storage" "4.24.0" + "@algolia/cache-common" "4.24.0" + "@algolia/cache-in-memory" "4.24.0" + "@algolia/client-account" "4.24.0" + "@algolia/client-analytics" "4.24.0" + "@algolia/client-common" "4.24.0" + "@algolia/client-personalization" "4.24.0" + "@algolia/client-search" "4.24.0" + "@algolia/logger-common" "4.24.0" + "@algolia/logger-console" "4.24.0" + "@algolia/recommend" "4.24.0" + "@algolia/requester-browser-xhr" "4.24.0" + "@algolia/requester-common" "4.24.0" + "@algolia/requester-node-http" "4.24.0" + "@algolia/transporter" "4.24.0" ansi-align@^3.0.0, ansi-align@^3.0.1: version "3.0.1" @@ -2678,9 +2589,9 @@ ansi-styles@^6.1.0: integrity sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug== anymatch@~3.1.2: - version "3.1.2" - resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.2.tgz#c0557c096af32f106198f4f4e2a383537e378716" - integrity sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg== + version "3.1.3" + resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.3.tgz#790c58b19ba1720a84205b57c618d5ad8524973e" + integrity sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw== dependencies: normalize-path "^3.0.0" picomatch "^2.0.4" @@ -2707,11 +2618,6 @@ array-flatten@1.1.1: resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2" integrity sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg== -array-flatten@^2.1.2: - version "2.1.2" - resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-2.1.2.tgz#24ef80a28c1a893617e2149b0c6d0d788293b099" - integrity sha512-hNfzcOV8W4NdualtqBFPyVO+54DSJuZGY9qT4pRroB6S9e3iiido2ISIC5h9R2sPJ8H3FHCIiEnsv1lPXO3KtQ== - array-union@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/array-union/-/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d" @@ -2733,13 +2639,13 @@ at-least-node@^1.0.0: integrity sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg== autoprefixer@^10.4.12, autoprefixer@^10.4.7: - version "10.4.13" - resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-10.4.13.tgz#b5136b59930209a321e9fa3dca2e7c4d223e83a8" - integrity sha512-49vKpMqcZYsJjwotvt4+h/BCjJVnhGwcLpDt5xkcaOG3eLrG/HUYLagrihYsQ+qrIBgIzX1Rw7a6L8I/ZA1Atg== + version "10.4.19" + resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-10.4.19.tgz#ad25a856e82ee9d7898c59583c1afeb3fa65f89f" + integrity sha512-BaENR2+zBZ8xXhM4pUaKUxlVdxZ0EZhjvbopwnXmxRUfqDmwSpC2lAi/QXvx7NRdPCo1WKEcEF6mV64si1z4Ew== dependencies: - browserslist "^4.21.4" - caniuse-lite "^1.0.30001426" - fraction.js "^4.2.0" + browserslist "^4.23.0" + caniuse-lite "^1.0.30001599" + fraction.js "^4.3.7" normalize-range "^0.1.2" picocolors "^1.0.0" postcss-value-parser "^4.2.0" @@ -2783,29 +2689,29 @@ babel-plugin-extract-import-names@1.6.22: dependencies: "@babel/helper-plugin-utils" "7.10.4" -babel-plugin-polyfill-corejs2@^0.3.3: - version "0.3.3" - resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.3.3.tgz#5d1bd3836d0a19e1b84bbf2d9640ccb6f951c122" - integrity sha512-8hOdmFYFSZhqg2C/JgLUQ+t52o5nirNwaWM2B9LWteozwIvM14VSwdsCAUET10qT+kmySAlseadmfeeSWFCy+Q== +babel-plugin-polyfill-corejs2@^0.4.10: + version "0.4.11" + resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.11.tgz#30320dfe3ffe1a336c15afdcdafd6fd615b25e33" + integrity sha512-sMEJ27L0gRHShOh5G54uAAPaiCOygY/5ratXuiyb2G46FmlSpc9eFCzYVyDiPxfNbwzA7mYahmjQc5q+CZQ09Q== dependencies: - "@babel/compat-data" "^7.17.7" - "@babel/helper-define-polyfill-provider" "^0.3.3" - semver "^6.1.1" + "@babel/compat-data" "^7.22.6" + "@babel/helper-define-polyfill-provider" "^0.6.2" + semver "^6.3.1" -babel-plugin-polyfill-corejs3@^0.6.0: - version "0.6.0" - resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.6.0.tgz#56ad88237137eade485a71b52f72dbed57c6230a" - integrity sha512-+eHqR6OPcBhJOGgsIar7xoAB1GcSwVUA3XjAd7HJNzOXT4wv6/H7KIdA/Nc60cvUlDbKApmqNvD1B1bzOt4nyA== +babel-plugin-polyfill-corejs3@^0.10.1, babel-plugin-polyfill-corejs3@^0.10.4: + version "0.10.4" + resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.10.4.tgz#789ac82405ad664c20476d0233b485281deb9c77" + integrity sha512-25J6I8NGfa5YkCDogHRID3fVCadIR8/pGl1/spvCkzb6lVn6SR3ojpx9nOn9iEBcUsjY24AmdKm5khcfKdylcg== dependencies: - "@babel/helper-define-polyfill-provider" "^0.3.3" - core-js-compat "^3.25.1" + "@babel/helper-define-polyfill-provider" "^0.6.1" + core-js-compat "^3.36.1" -babel-plugin-polyfill-regenerator@^0.4.1: - version "0.4.1" - resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.4.1.tgz#390f91c38d90473592ed43351e801a9d3e0fd747" - integrity sha512-NtQGmyQDXjQqQ+IzRkBVwEOz9lQ4zxAQZgoAYEtU9dJjnl1Oc98qnN7jcp+bE7O7aYzVpavXE3/VKXNzUbh7aw== +babel-plugin-polyfill-regenerator@^0.6.1: + version "0.6.2" + resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.6.2.tgz#addc47e240edd1da1058ebda03021f382bba785e" + integrity sha512-2R25rQZWP63nGwaAswvDazbPXfrM3HwVoBXK6HcqeKrSrL/JqcC/rDcf95l4r7LXLyxDXc8uQDa064GubtCABg== dependencies: - "@babel/helper-define-polyfill-provider" "^0.3.3" + "@babel/helper-define-polyfill-provider" "^0.6.2" bail@^1.0.0: version "1.0.5" @@ -2838,17 +2744,17 @@ big.js@^5.2.2: integrity sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ== binary-extensions@^2.0.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d" - integrity sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA== + version "2.3.0" + resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.3.0.tgz#f6e14a97858d327252200242d4ccfe522c445522" + integrity sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw== -body-parser@1.20.1: - version "1.20.1" - resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.20.1.tgz#b1812a8912c195cd371a3ee5e66faa2338a5c668" - integrity sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw== +body-parser@1.20.2: + version "1.20.2" + resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.20.2.tgz#6feb0e21c4724d06de7ff38da36dad4f57a747fd" + integrity sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA== dependencies: bytes "3.1.2" - content-type "~1.0.4" + content-type "~1.0.5" debug "2.6.9" depd "2.0.0" destroy "1.2.0" @@ -2856,17 +2762,15 @@ body-parser@1.20.1: iconv-lite "0.4.24" on-finished "2.4.1" qs "6.11.0" - raw-body "2.5.1" + raw-body "2.5.2" type-is "~1.6.18" unpipe "1.0.0" bonjour-service@^1.0.11: - version "1.0.14" - resolved "https://registry.yarnpkg.com/bonjour-service/-/bonjour-service-1.0.14.tgz#c346f5bc84e87802d08f8d5a60b93f758e514ee7" - integrity sha512-HIMbgLnk1Vqvs6B4Wq5ep7mxvj9sGz5d1JJyDNSGNIdA/w2MCz6GTjWTdjqOJV1bEPj+6IkxDvWNFKEBxNt4kQ== + version "1.2.1" + resolved "https://registry.yarnpkg.com/bonjour-service/-/bonjour-service-1.2.1.tgz#eb41b3085183df3321da1264719fbada12478d02" + integrity sha512-oSzCS2zV14bh2kji6vNe7vrpJYCHGvcZnlffFQ1MEoX/WOeQ/teD8SYWKR942OI3INjq8OMNJlbPK5LLLUxFDw== dependencies: - array-flatten "^2.1.2" - dns-equal "^1.0.0" fast-deep-equal "^3.1.3" multicast-dns "^7.2.5" @@ -2911,27 +2815,22 @@ brace-expansion@^1.1.7: balanced-match "^1.0.0" concat-map "0.0.1" -braces@^3.0.2, braces@~3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" - integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== +braces@^3.0.3, braces@~3.0.2: + version "3.0.3" + resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.3.tgz#490332f40919452272d55a8480adc0c441358789" + integrity sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA== dependencies: - fill-range "^7.0.1" - -browser-process-hrtime@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/browser-process-hrtime/-/browser-process-hrtime-1.0.0.tgz#3c9b4b7d782c8121e56f10106d84c0d0ffc94626" - integrity sha512-9o5UecI3GhkpM6DrXr69PblIuWxPKk9Y0jHBRhdocZ2y7YECBFCsHm79Pr3OyR2AvjhDkabFJaDJMYRazHgsow== + fill-range "^7.1.1" -browserslist@^4.0.0, browserslist@^4.14.5, browserslist@^4.16.6, browserslist@^4.18.1, browserslist@^4.21.3, browserslist@^4.21.4: - version "4.21.4" - resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.21.4.tgz#e7496bbc67b9e39dd0f98565feccdcb0d4ff6987" - integrity sha512-CBHJJdDmgjl3daYjN5Cp5kbTf1mUhZoS+beLklHIvkOWscs83YAhLlF3Wsh/lciQYAcbBJgTOD44VtG31ZM4Hw== +browserslist@^4.0.0, browserslist@^4.18.1, browserslist@^4.21.10, browserslist@^4.21.4, browserslist@^4.23.0, browserslist@^4.23.1: + version "4.23.2" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.23.2.tgz#244fe803641f1c19c28c48c4b6ec9736eb3d32ed" + integrity sha512-qkqSyistMYdxAcw+CzbZwlBy8AGmS/eEWs+sEV5TnLRGDOL+C5M2EnH6tlZyg0YoAxGJAFKh61En9BR941GnHA== dependencies: - caniuse-lite "^1.0.30001400" - electron-to-chromium "^1.4.251" - node-releases "^2.0.6" - update-browserslist-db "^1.0.9" + caniuse-lite "^1.0.30001640" + electron-to-chromium "^1.4.820" + node-releases "^2.0.14" + update-browserslist-db "^1.1.0" buffer-from@^1.0.0: version "1.1.2" @@ -2961,13 +2860,16 @@ cacheable-request@^6.0.0: normalize-url "^4.1.0" responselike "^1.0.2" -call-bind@^1.0.0, call-bind@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.2.tgz#b1d4e89e688119c3c9a903ad30abb2f6a919be3c" - integrity sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA== +call-bind@^1.0.5, call-bind@^1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.7.tgz#06016599c40c56498c18769d2730be242b6fa3b9" + integrity sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w== dependencies: - function-bind "^1.1.1" - get-intrinsic "^1.0.2" + es-define-property "^1.0.0" + es-errors "^1.3.0" + function-bind "^1.1.2" + get-intrinsic "^1.2.4" + set-function-length "^1.2.1" callsites@^3.0.0: version "3.1.0" @@ -3002,17 +2904,17 @@ caniuse-api@^3.0.0: lodash.memoize "^4.1.2" lodash.uniq "^4.5.0" -caniuse-lite@^1.0.0, caniuse-lite@^1.0.30001400, caniuse-lite@^1.0.30001426: - version "1.0.30001434" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001434.tgz#ec1ec1cfb0a93a34a0600d37903853030520a4e5" - integrity sha512-aOBHrLmTQw//WFa2rcF1If9fa3ypkC1wzqqiKHgfdrXTWcU8C4gKVZT77eQAPWN1APys3+uQ0Df07rKauXGEYA== +caniuse-lite@^1.0.0, caniuse-lite@^1.0.30001599, caniuse-lite@^1.0.30001640: + version "1.0.30001643" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001643.tgz#9c004caef315de9452ab970c3da71085f8241dbd" + integrity sha512-ERgWGNleEilSrHM6iUz/zJNSQTP8Mr21wDWpdgvRwcTXGAq6jMtOUPP4dqFPTdKqZ2wKTdtB+uucZ3MRpAUSmg== ccount@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/ccount/-/ccount-1.1.0.tgz#246687debb6014735131be8abab2d93898f8d043" integrity sha512-vlNK021QdI7PNeiUh/lKkC/mNHHfV0m/Ad5JoI0TYtlBnJAslM/JIkm/tGC88bkLIwO6OQ5uV6ztS6kVAtCDlg== -chalk@^2.0.0: +chalk@^2.4.2: version "2.4.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== @@ -3070,9 +2972,9 @@ cheerio@^1.0.0-rc.12: parse5-htmlparser2-tree-adapter "^7.0.0" chokidar@^3.4.2, chokidar@^3.5.3: - version "3.5.3" - resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.3.tgz#1cf37c8707b932bd1af1ae22c0432e2acd1903bd" - integrity sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw== + version "3.6.0" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.6.0.tgz#197c6cc669ef2a8dc5e7b4d97ee4e092c3eb0d5b" + integrity sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw== dependencies: anymatch "~3.1.2" braces "~3.0.2" @@ -3085,9 +2987,9 @@ chokidar@^3.4.2, chokidar@^3.5.3: fsevents "~2.3.2" chrome-trace-event@^1.0.2: - version "1.0.3" - resolved "https://registry.yarnpkg.com/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz#1015eced4741e15d06664a957dbbf50d041e26ac" - integrity sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg== + version "1.0.4" + resolved "https://registry.yarnpkg.com/chrome-trace-event/-/chrome-trace-event-1.0.4.tgz#05bffd7ff928465093314708c93bdfa9bd1f0f5b" + integrity sha512-rNjApaLzuwaOTjCiT8lSDdGN1APCiqkChLMJxJPWLunPAt5fy8xgU9/jNOchV84wfIxrA0lRQB7oCT8jrn/wrQ== ci-info@^2.0.0: version "2.0.0" @@ -3095,14 +2997,14 @@ ci-info@^2.0.0: integrity sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ== ci-info@^3.2.0: - version "3.6.1" - resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-3.6.1.tgz#7594f1c95cb7fdfddee7af95a13af7dbc67afdcf" - integrity sha512-up5ggbaDqOqJ4UqLKZ2naVkyqSJQgJi5lwD6b6mM748ysrghDBX0bx/qJTUHzw7zu6Mq4gycviSF5hJnwceD8w== + version "3.9.0" + resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-3.9.0.tgz#4279a62028a7b1f262f3473fc9605f5e218c59b4" + integrity sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ== clean-css@^5.2.2, clean-css@^5.3.0: - version "5.3.1" - resolved "https://registry.yarnpkg.com/clean-css/-/clean-css-5.3.1.tgz#d0610b0b90d125196a2894d35366f734e5d7aa32" - integrity sha512-lCr8OHhiWCTw4v8POJovCoh4T7I9U11yVsPjMWWnnMmp9ZowCxyad1Pathle/9HjaDp+fdQKjO9fQydE6RHTZg== + version "5.3.3" + resolved "https://registry.yarnpkg.com/clean-css/-/clean-css-5.3.3.tgz#b330653cd3bd6b75009cc25c714cae7b93351ccd" + integrity sha512-D5J+kHaVb/wKSFcyyV75uCn8fiY4sV38XJoe4CUyGQ+mOU/fMVYUdH1hJC+CJQ5uY3EnW27SbJYS4X8BiLrAFg== dependencies: source-map "~0.6.0" @@ -3122,9 +3024,9 @@ cli-boxes@^3.0.0: integrity sha512-/lzGpEWL/8PfI0BmBOPRwp0c/wFNX1RdUML3jK/RcSBA9T8mZDdQpqYBKtCFTOfQbwPqWEOpjqW+Fnayc0969g== cli-table3@^0.6.2: - version "0.6.3" - resolved "https://registry.yarnpkg.com/cli-table3/-/cli-table3-0.6.3.tgz#61ab765aac156b52f222954ffc607a6f01dbeeb2" - integrity sha512-w5Jac5SykAeZJKntOxJCrm63Eg5/4dhMWIcuTbo9rpE+brgaSZo0RuNJZeOyMgsUdhDeojvgyQLmjI+K50ZGyg== + version "0.6.5" + resolved "https://registry.yarnpkg.com/cli-table3/-/cli-table3-0.6.5.tgz#013b91351762739c16a9567c21a04632e449bf2f" + integrity sha512-+W/5efTR7y5HRD7gACw9yQjqMVvEMLBHmboM/kPWam+H+Hmyrgjh6YncVKK122YZkXrLudzTuAukUw9FnMf7IQ== dependencies: string-width "^4.2.0" optionalDependencies: @@ -3186,14 +3088,14 @@ colord@^2.9.1: integrity sha512-jeC1axXpnb0/2nn/Y1LPuLdgXBLH7aDcHu4KEKfqw3CUhX7ZpfBSlPKyqXE6btIgEzfWtrX3/tyBCaCvXvMkOw== colorette@^2.0.10: - version "2.0.19" - resolved "https://registry.yarnpkg.com/colorette/-/colorette-2.0.19.tgz#cdf044f47ad41a0f4b56b3a0d5b4e6e1a2d5a798" - integrity sha512-3tlv/dIP7FWvj3BsbHrGLJ6l/oKh1O3TcgBqMn+yyCagOxc23fyzDS6HypQbgxWbkpDnf52p1LuR4eWDQ/K9WQ== + version "2.0.20" + resolved "https://registry.yarnpkg.com/colorette/-/colorette-2.0.20.tgz#9eb793e6833067f7235902fcd3b09917a000a95a" + integrity sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w== combine-promises@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/combine-promises/-/combine-promises-1.1.0.tgz#72db90743c0ca7aab7d0d8d2052fd7b0f674de71" - integrity sha512-ZI9jvcLDxqwaXEixOhArm3r7ReIivsXkpbyEWyeOhzz1QS0iSgBPnWvEqvIQtYyamGCYA88gFhmUrs9hrrQ0pg== + version "1.2.0" + resolved "https://registry.yarnpkg.com/combine-promises/-/combine-promises-1.2.0.tgz#5f2e68451862acf85761ded4d9e2af7769c2ca6a" + integrity sha512-VcQB1ziGD0NXrhKxiwyNbCDmRzs/OShMs2GqW2DlU2A/Sd0nQxE1oWDAE5O0ygSx5mgQOn9eIFh7yKPgFRVkPQ== combined-stream@^1.0.8: version "1.0.8" @@ -3301,30 +3203,35 @@ content-disposition@0.5.4: dependencies: safe-buffer "5.2.1" -content-type@~1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.4.tgz#e138cc75e040c727b1966fe5e5f8c9aee256fe3b" - integrity sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA== +content-type@~1.0.4, content-type@~1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.5.tgz#8b773162656d1d1086784c8f23a54ce6d73d7918" + integrity sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA== convert-source-map@^1.7.0: version "1.9.0" resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.9.0.tgz#7faae62353fb4213366d0ca98358d22e8368b05f" integrity sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A== +convert-source-map@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-2.0.0.tgz#4b560f649fc4e918dd0ab75cf4961e8bc882d82a" + integrity sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg== + cookie-signature@1.0.6: version "1.0.6" resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c" integrity sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ== -cookie@0.5.0: - version "0.5.0" - resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.5.0.tgz#d1f5d71adec6558c58f389987c366aa47e994f8b" - integrity sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw== +cookie@0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.6.0.tgz#2798b04b071b0ecbff0dbb62a505a8efa4e19051" + integrity sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw== copy-text-to-clipboard@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/copy-text-to-clipboard/-/copy-text-to-clipboard-3.0.1.tgz#8cbf8f90e0a47f12e4a24743736265d157bce69c" - integrity sha512-rvVsHrpFcL4F2P8ihsoLdFHmd404+CMg71S756oRSeQgqk51U3kicGdnvfkrxva0xXH92SjGS62B0XIJsbh+9Q== + version "3.2.0" + resolved "https://registry.yarnpkg.com/copy-text-to-clipboard/-/copy-text-to-clipboard-3.2.0.tgz#0202b2d9bdae30a49a53f898626dcc3b49ad960b" + integrity sha512-RnJFp1XR/LOBDckxTib5Qjr/PMfkatD0MUCQgdpqS8MdKiNUzBjAQBEN6oUy+jW7LI93BBG3DtMB2KOOKpGs2Q== copy-webpack-plugin@^11.0.0: version "11.0.0" @@ -3338,22 +3245,22 @@ copy-webpack-plugin@^11.0.0: schema-utils "^4.0.0" serialize-javascript "^6.0.0" -core-js-compat@^3.25.1: - version "3.26.1" - resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.26.1.tgz#0e710b09ebf689d719545ac36e49041850f943df" - integrity sha512-622/KzTudvXCDLRw70iHW4KKs1aGpcRcowGWyYJr2DEBfRrd6hNJybxSWJFuZYD4ma86xhrwDDHxmDaIq4EA8A== +core-js-compat@^3.36.1, core-js-compat@^3.37.1: + version "3.37.1" + resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.37.1.tgz#c844310c7852f4bdf49b8d339730b97e17ff09ee" + integrity sha512-9TNiImhKvQqSUkOvk/mMRZzOANTiEVC7WaBNhHcKM7x+/5E1l5NvsysR19zuDQScE8k+kfQXWRN3AtS/eOSHpg== dependencies: - browserslist "^4.21.4" + browserslist "^4.23.0" -core-js-pure@^3.25.1: - version "3.26.1" - resolved "https://registry.yarnpkg.com/core-js-pure/-/core-js-pure-3.26.1.tgz#653f4d7130c427820dcecd3168b594e8bb095a33" - integrity sha512-VVXcDpp/xJ21KdULRq/lXdLzQAtX7+37LzpyfFM973il0tWSsDEoyzG38G14AjTpK9VTfiNM9jnFauq/CpaWGQ== +core-js-pure@^3.30.2: + version "3.37.1" + resolved "https://registry.yarnpkg.com/core-js-pure/-/core-js-pure-3.37.1.tgz#2b4b34281f54db06c9a9a5bd60105046900553bd" + integrity sha512-J/r5JTHSmzTxbiYYrzXg9w1VpqrYt+gexenBE9pugeyhwPZTAEJddyiReJWsLO6uNQ8xJZFbod6XC7KKwatCiA== core-js@^3.23.3: - version "3.26.1" - resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.26.1.tgz#7a9816dabd9ee846c1c0fe0e8fcad68f3709134e" - integrity sha512-21491RRQVzUn0GGM9Z1Jrpr6PNPxPi+Za8OM9q4tksTSnlbXXGKK1nXNg/QvwFYettXvSX6zWKCtHHfjN4puyA== + version "3.37.1" + resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.37.1.tgz#d21751ddb756518ac5a00e4d66499df981a62db9" + integrity sha512-Xn6qmxrQZyB0FFY8E3bgRXei3lWDJHhvI+u0q9TKIYM49G8pAr0FgnnrFRAmsbptZL1yxRADVXn+x5AGsbBfyw== core-util-is@~1.0.0: version "1.0.3" @@ -3371,7 +3278,7 @@ cosmiconfig@^6.0.0: path-type "^4.0.0" yaml "^1.7.2" -cosmiconfig@^7.0.0, cosmiconfig@^7.0.1: +cosmiconfig@^7.0.1: version "7.1.0" resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-7.1.0.tgz#1443b9afa596b670082ea46cbd8f6a62b84635f6" integrity sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA== @@ -3382,12 +3289,22 @@ cosmiconfig@^7.0.0, cosmiconfig@^7.0.1: path-type "^4.0.0" yaml "^1.10.0" +cosmiconfig@^8.3.5: + version "8.3.6" + resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-8.3.6.tgz#060a2b871d66dba6c8538ea1118ba1ac16f5fae3" + integrity sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA== + dependencies: + import-fresh "^3.3.0" + js-yaml "^4.1.0" + parse-json "^5.2.0" + path-type "^4.0.0" + cross-fetch@^3.1.5: - version "3.1.5" - resolved "https://registry.yarnpkg.com/cross-fetch/-/cross-fetch-3.1.5.tgz#e1389f44d9e7ba767907f7af8454787952ab534f" - integrity sha512-lvb1SBsI0Z7GDwmuid+mU3kWVBwTVUbe7S0H52yaaAdQOXq2YktTCZdlAcNKFzE6QtRz0snpw9bNiPeOIkkQvw== + version "3.1.8" + resolved "https://registry.yarnpkg.com/cross-fetch/-/cross-fetch-3.1.8.tgz#0327eba65fd68a7d119f8fb2bf9334a1a7956f82" + integrity sha512-cvA+JwZoU0Xq+h6WkMvAUqPEYy92Obet6UdKLfW60qn99ftItKjB5T+BkyWOFWe2pUyfQ+IJHmpOTznqk1M6Kg== dependencies: - node-fetch "2.6.7" + node-fetch "^2.6.12" cross-spawn@^7.0.3: version "7.0.3" @@ -3404,23 +3321,23 @@ crypto-random-string@^2.0.0: integrity sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA== css-declaration-sorter@^6.3.1: - version "6.3.1" - resolved "https://registry.yarnpkg.com/css-declaration-sorter/-/css-declaration-sorter-6.3.1.tgz#be5e1d71b7a992433fb1c542c7a1b835e45682ec" - integrity sha512-fBffmak0bPAnyqc/HO8C3n2sHrp9wcqQz6ES9koRF2/mLOVAx9zIQ3Y7R29sYCteTPqMCwns4WYQoCX91Xl3+w== + version "6.4.1" + resolved "https://registry.yarnpkg.com/css-declaration-sorter/-/css-declaration-sorter-6.4.1.tgz#28beac7c20bad7f1775be3a7129d7eae409a3a71" + integrity sha512-rtdthzxKuyq6IzqX6jEcIzQF/YqccluefyCYheovBOLhFT/drQA9zj/UbRAa9J7C0o6EG6u3E6g+vKkay7/k3g== css-loader@^6.7.1: - version "6.7.2" - resolved "https://registry.yarnpkg.com/css-loader/-/css-loader-6.7.2.tgz#26bc22401b5921686a10fbeba75d124228302304" - integrity sha512-oqGbbVcBJkm8QwmnNzrFrWTnudnRZC+1eXikLJl0n4ljcfotgRifpg2a1lKy8jTrc4/d9A/ap1GFq1jDKG7J+Q== + version "6.11.0" + resolved "https://registry.yarnpkg.com/css-loader/-/css-loader-6.11.0.tgz#33bae3bf6363d0a7c2cf9031c96c744ff54d85ba" + integrity sha512-CTJ+AEQJjq5NzLga5pE39qdiSV56F8ywCIsqNIRF0r7BDgWsN25aazToqAFg7ZrtA/U016xudB3ffgweORxX7g== dependencies: icss-utils "^5.1.0" - postcss "^8.4.18" - postcss-modules-extract-imports "^3.0.0" - postcss-modules-local-by-default "^4.0.0" - postcss-modules-scope "^3.0.0" + postcss "^8.4.33" + postcss-modules-extract-imports "^3.1.0" + postcss-modules-local-by-default "^4.0.5" + postcss-modules-scope "^3.2.0" postcss-modules-values "^4.0.0" postcss-value-parser "^4.2.0" - semver "^7.3.8" + semver "^7.5.4" css-minimizer-webpack-plugin@^4.0.0: version "4.2.2" @@ -3475,33 +3392,33 @@ cssesc@^3.0.0: integrity sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg== cssnano-preset-advanced@^5.3.8: - version "5.3.9" - resolved "https://registry.yarnpkg.com/cssnano-preset-advanced/-/cssnano-preset-advanced-5.3.9.tgz#99e1cdf81a467a5e6c366cfc6d874a166c4d9a67" - integrity sha512-njnh4pp1xCsibJcEHnWZb4EEzni0ePMqPuPNyuWT4Z+YeXmsgqNuTPIljXFEXhxGsWs9183JkXgHxc1TcsahIg== + version "5.3.10" + resolved "https://registry.yarnpkg.com/cssnano-preset-advanced/-/cssnano-preset-advanced-5.3.10.tgz#25558a1fbf3a871fb6429ce71e41be7f5aca6eef" + integrity sha512-fnYJyCS9jgMU+cmHO1rPSPf9axbQyD7iUhLO5Df6O4G+fKIOMps+ZbU0PdGFejFBBZ3Pftf18fn1eG7MAPUSWQ== dependencies: autoprefixer "^10.4.12" - cssnano-preset-default "^5.2.13" + cssnano-preset-default "^5.2.14" postcss-discard-unused "^5.1.0" postcss-merge-idents "^5.1.1" postcss-reduce-idents "^5.2.0" postcss-zindex "^5.1.0" -cssnano-preset-default@^5.2.13: - version "5.2.13" - resolved "https://registry.yarnpkg.com/cssnano-preset-default/-/cssnano-preset-default-5.2.13.tgz#e7353b0c57975d1bdd97ac96e68e5c1b8c68e990" - integrity sha512-PX7sQ4Pb+UtOWuz8A1d+Rbi+WimBIxJTRyBdgGp1J75VU0r/HFQeLnMYgHiCAp6AR4rqrc7Y4R+1Rjk3KJz6DQ== +cssnano-preset-default@^5.2.14: + version "5.2.14" + resolved "https://registry.yarnpkg.com/cssnano-preset-default/-/cssnano-preset-default-5.2.14.tgz#309def4f7b7e16d71ab2438052093330d9ab45d8" + integrity sha512-t0SFesj/ZV2OTylqQVOrFgEh5uanxbO6ZAdeCrNsUQ6fVuXwYTxJPNAGvGTxHbD68ldIJNec7PyYZDBrfDQ+6A== dependencies: css-declaration-sorter "^6.3.1" cssnano-utils "^3.1.0" postcss-calc "^8.2.3" - postcss-colormin "^5.3.0" + postcss-colormin "^5.3.1" postcss-convert-values "^5.1.3" postcss-discard-comments "^5.1.2" postcss-discard-duplicates "^5.1.0" postcss-discard-empty "^5.1.1" postcss-discard-overridden "^5.1.0" postcss-merge-longhand "^5.1.7" - postcss-merge-rules "^5.1.3" + postcss-merge-rules "^5.1.4" postcss-minify-font-values "^5.1.0" postcss-minify-gradients "^5.1.1" postcss-minify-params "^5.1.4" @@ -3516,7 +3433,7 @@ cssnano-preset-default@^5.2.13: postcss-normalize-url "^5.1.0" postcss-normalize-whitespace "^5.1.1" postcss-ordered-values "^5.1.3" - postcss-reduce-initial "^5.1.1" + postcss-reduce-initial "^5.1.2" postcss-reduce-transforms "^5.1.0" postcss-svgo "^5.1.0" postcss-unique-selectors "^5.1.1" @@ -3527,11 +3444,11 @@ cssnano-utils@^3.1.0: integrity sha512-JQNR19/YZhz4psLX/rQ9M83e3z2Wf/HdJbryzte4a3NSuafyp9w/I4U+hx5C2S9g41qlstH7DEWnZaaj83OuEA== cssnano@^5.1.12, cssnano@^5.1.8: - version "5.1.14" - resolved "https://registry.yarnpkg.com/cssnano/-/cssnano-5.1.14.tgz#07b0af6da73641276fe5a6d45757702ebae2eb05" - integrity sha512-Oou7ihiTocbKqi0J1bB+TRJIQX5RMR3JghA8hcWSw9mjBLQ5Y3RWqEDoYG3sRNlAbCIXpqMoZGbq5KDR3vdzgw== + version "5.1.15" + resolved "https://registry.yarnpkg.com/cssnano/-/cssnano-5.1.15.tgz#ded66b5480d5127fcb44dac12ea5a983755136bf" + integrity sha512-j+BKgDcLDQA+eDifLx0EO4XSA56b7uut3BQFH+wbSaSTuGLuiyTa/wbRYthUXX8LC9mLg+WWKe8h+qJuwTAbHw== dependencies: - cssnano-preset-default "^5.2.13" + cssnano-preset-default "^5.2.14" lilconfig "^2.0.3" yaml "^1.10.2" @@ -3560,11 +3477,11 @@ cssstyle@^2.3.0: cssom "~0.3.6" csstype@^3.0.2: - version "3.1.1" - resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.1.1.tgz#841b532c45c758ee546a11d5bd7b7b473c8c30b9" - integrity sha512-DJR/VvkAvSZW9bTouZue2sSxDwdTN92uHjqeKVm+0dAqdfNykRzQ95tay8aXMBAAPpUiq4Qcug2L7neoRh2Egw== + version "3.1.3" + resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.1.3.tgz#d80ff294d114fb0e6ac500fbf85b60137d7eff81" + integrity sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw== -data-urls@^3.0.1: +data-urls@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/data-urls/-/data-urls-3.0.2.tgz#9cf24a477ae22bcef5cd5f6f0bfbc1d2d3be9143" integrity sha512-Jy/tj3ldjZJo63sVAvg6LHt2mHvl4V6AgRAmNDtLdm7faqtsx+aJG42rsyCo9JCoRVKwPFzKlIPx3DIibwSIaQ== @@ -3573,6 +3490,11 @@ data-urls@^3.0.1: whatwg-mimetype "^3.0.0" whatwg-url "^11.0.0" +debounce@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/debounce/-/debounce-1.2.1.tgz#38881d8f4166a5c5848020c11827b834bcb3e0a5" + integrity sha512-XRRe6Glud4rd/ZGQfiV1ruXSfbvfJedlV9Y6zOlP+2K04vBYiJEte6stfFkCP03aMnY5tsipamumUjL14fofug== + debug@2.6.9, debug@^2.6.0: version "2.6.9" resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" @@ -3580,17 +3502,17 @@ debug@2.6.9, debug@^2.6.0: dependencies: ms "2.0.0" -debug@4, debug@^4.1.0, debug@^4.1.1: - version "4.3.4" - resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" - integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== +debug@4, debug@^4.1.0, debug@^4.1.1, debug@^4.3.1: + version "4.3.5" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.5.tgz#e83444eceb9fedd4a1da56d671ae2446a01a6e1e" + integrity sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg== dependencies: ms "2.1.2" -decimal.js@^10.3.1: - version "10.4.2" - resolved "https://registry.yarnpkg.com/decimal.js/-/decimal.js-10.4.2.tgz#0341651d1d997d86065a2ce3a441fbd0d8e8b98e" - integrity sha512-ic1yEvwT6GuvaYwBLLY6/aFFgjZdySKTE8en/fkU3QICTmRtgtSlFn0u0BXN06InZwtfCelR7j8LRiDI/02iGA== +decimal.js@^10.4.2: + version "10.4.3" + resolved "https://registry.yarnpkg.com/decimal.js/-/decimal.js-10.4.3.tgz#1044092884d245d1b7f65725fa4ad4c6f781cc23" + integrity sha512-VBBaLc1MgL5XpzgIP7ny5Z6Nx3UrRkIViUkPUdtl9aya5amy3De1gsUUSB1g3+3sExYNjCAsAznmukyxCb1GRA== decompress-response@^3.3.0: version "3.3.0" @@ -3604,15 +3526,10 @@ deep-extend@^0.6.0: resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac" integrity sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA== -deep-is@~0.1.3: - version "0.1.4" - resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.4.tgz#a6f2dce612fadd2ef1f519b73551f17e85199831" - integrity sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ== - deepmerge@^4.2.2: - version "4.2.2" - resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-4.2.2.tgz#44d2ea3679b8f4d4ffba33f03d865fc1e7bf4955" - integrity sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg== + version "4.3.1" + resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-4.3.1.tgz#44b5f2147cd3b00d4b56137685966f26fd25dd4a" + integrity sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A== default-gateway@^6.0.3: version "6.0.3" @@ -3626,16 +3543,26 @@ defer-to-connect@^1.0.1: resolved "https://registry.yarnpkg.com/defer-to-connect/-/defer-to-connect-1.1.3.tgz#331ae050c08dcf789f8c83a7b81f0ed94f4ac591" integrity sha512-0ISdNousHvZT2EiFlZeZAHBUvSxmKswVCEf8hW7KWgG4a8MVEu/3Vb6uWYozkjylyCxe0JBIiRB1jV45S70WVQ== +define-data-property@^1.0.1, define-data-property@^1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/define-data-property/-/define-data-property-1.1.4.tgz#894dc141bb7d3060ae4366f6a0107e68fbe48c5e" + integrity sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A== + dependencies: + es-define-property "^1.0.0" + es-errors "^1.3.0" + gopd "^1.0.1" + define-lazy-prop@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz#3f7ae421129bcaaac9bc74905c98a0009ec9ee7f" integrity sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og== -define-properties@^1.1.4: - version "1.1.4" - resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.4.tgz#0b14d7bd7fbeb2f3572c3a7eda80ea5d57fb05b1" - integrity sha512-uckOqKcfaVvtBdsVkdPv3XjveQJsNQqmhXgRi8uhvWWuPYZCNlzT8qAyblUgNoXdHdjMTzAqeGjAoli8f+bzPA== +define-properties@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.2.1.tgz#10781cc616eb951a80a034bafcaa7377f6af2b6c" + integrity sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg== dependencies: + define-data-property "^1.0.1" has-property-descriptors "^1.0.0" object-keys "^1.1.1" @@ -3694,9 +3621,9 @@ detect-port-alt@^1.1.6: debug "^2.6.0" detect-port@^1.3.0: - version "1.5.1" - resolved "https://registry.yarnpkg.com/detect-port/-/detect-port-1.5.1.tgz#451ca9b6eaf20451acb0799b8ab40dff7718727b" - integrity sha512-aBzdj76lueB6uUst5iAs7+0H/oOjqI5D16XUWxlWMIMROhcM0rfsNVk93zTngq1dDNpoXRr++Sus7ETAExppAQ== + version "1.6.1" + resolved "https://registry.yarnpkg.com/detect-port/-/detect-port-1.6.1.tgz#45e4073997c5f292b957cb678fb0bb8ed4250a67" + integrity sha512-CmnVc+Hek2egPx1PeTFVta2W78xy2K/9Rkf6cC4T59S50tVnzKj+tnx5mmx5lwvCkujZ4uRrpRSuV+IVs3f90Q== dependencies: address "^1.0.1" debug "4" @@ -3708,15 +3635,10 @@ dir-glob@^3.0.1: dependencies: path-type "^4.0.0" -dns-equal@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/dns-equal/-/dns-equal-1.0.0.tgz#b39e7f1da6eb0a75ba9c17324b34753c47e0654d" - integrity sha512-z+paD6YUQsk+AbGCEM4PrOXSss5gd66QfcVBFTKR/HpFL9jCqikS94HYwKww6fQyO7IxrIIyUu+g0Ka9tUS2Cg== - dns-packet@^5.2.2: - version "5.4.0" - resolved "https://registry.yarnpkg.com/dns-packet/-/dns-packet-5.4.0.tgz#1f88477cf9f27e78a213fb6d118ae38e759a879b" - integrity sha512-EgqGeaBB8hLiHLZtp/IbaDQTL8pZ0+IvwzSHA6d7VyMDM+B9hgddEMa9xjK5oYnw0ci0JQ6g2XCD7/f6cafU6g== + version "5.6.1" + resolved "https://registry.yarnpkg.com/dns-packet/-/dns-packet-5.6.1.tgz#ae888ad425a9d1478a0674256ab866de1012cf2f" + integrity sha512-l4gcSouhcgIKRvyy99RNVOgxXiicE+2jZoNmaNmZ6JXiGajBOJAesk1OBlJuM5k2c+eudGdLxDqXuPCKIj6kpw== dependencies: "@leichtgewicht/ip-codec" "^2.0.1" @@ -3764,7 +3686,7 @@ domhandler@^4.0.0, domhandler@^4.2.0, domhandler@^4.3.1: dependencies: domelementtype "^2.2.0" -domhandler@^5.0.1, domhandler@^5.0.2, domhandler@^5.0.3: +domhandler@^5.0.2, domhandler@^5.0.3: version "5.0.3" resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-5.0.3.tgz#cc385f7f751f1d1fc650c21374804254538c7d31" integrity sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w== @@ -3781,13 +3703,13 @@ domutils@^2.5.2, domutils@^2.8.0: domhandler "^4.2.0" domutils@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/domutils/-/domutils-3.0.1.tgz#696b3875238338cb186b6c0612bd4901c89a4f1c" - integrity sha512-z08c1l761iKhDFtfXO04C7kTdPBLi41zwOZl00WS8b5eiaebNpY00HKbztwBq+e3vyqWNwWF3mP9YLUeqIrF+Q== + version "3.1.0" + resolved "https://registry.yarnpkg.com/domutils/-/domutils-3.1.0.tgz#c47f551278d3dc4b0b1ab8cbb42d751a6f0d824e" + integrity sha512-H78uMmQtI2AhgDJjWeQmHwJJ2bLPD3GMmO7Zja/ZZh84wkm+4ut+IUnUdRa8uCGX88DiVx1j6FRe1XfxEgjEZA== dependencies: dom-serializer "^2.0.0" domelementtype "^2.3.0" - domhandler "^5.0.1" + domhandler "^5.0.3" dot-case@^3.0.4: version "3.0.4" @@ -3824,10 +3746,10 @@ ee-first@1.1.1: resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" integrity sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow== -electron-to-chromium@^1.4.251: - version "1.4.284" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.284.tgz#61046d1e4cab3a25238f6bf7413795270f125592" - integrity sha512-M8WEXFuKXMYMVr45fo8mq0wUrrJHheiKZf6BArTKk9ZBYCKJEOU5H8cdWgDT+qCVZf7Na4lVUaZsA+h6uA9+PA== +electron-to-chromium@^1.4.820: + version "1.5.1" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.5.1.tgz#24640bd4dcfaccb6d82bb4c3f4c7311503241581" + integrity sha512-FKbOCOQ5QRB3VlIbl1LZQefWIYwszlBloaXcY2rbfpu9ioJnNh3TK03YtIDKDo3WKBi8u+YV4+Fn2CkEozgf4w== emoji-regex@^8.0.0: version "8.0.0" @@ -3861,10 +3783,10 @@ end-of-stream@^1.1.0: dependencies: once "^1.4.0" -enhanced-resolve@^5.10.0: - version "5.10.0" - resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.10.0.tgz#0dc579c3bb2a1032e357ac45b8f3a6f3ad4fb1e6" - integrity sha512-T0yTFjdpldGY8PmuXXR0PyQ1ufZpEGiHVrp7zHKB7jdR4qlmZHhONVM5AQOAWXuF/w3dnHbEQVrNptJgt7F+cQ== +enhanced-resolve@^5.17.0: + version "5.17.1" + resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.17.1.tgz#67bfbbcc2f81d511be77d686a90267ef7f898a15" + integrity sha512-LMHl3dXhTcfv8gM4kEzIUeTQ+7fpdA0l2tUf34BddXPkz2A5xJ5L/Pchd5BL6rdccM9QGvu0sWZzK1Z1t4wwyg== dependencies: graceful-fs "^4.2.4" tapable "^2.2.0" @@ -3874,10 +3796,10 @@ entities@^2.0.0: resolved "https://registry.yarnpkg.com/entities/-/entities-2.2.0.tgz#098dc90ebb83d8dffa089d55256b351d34c4da55" integrity sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A== -entities@^4.2.0, entities@^4.3.0, entities@^4.4.0: - version "4.4.0" - resolved "https://registry.yarnpkg.com/entities/-/entities-4.4.0.tgz#97bdaba170339446495e653cfd2db78962900174" - integrity sha512-oYp7156SP8LkeGD0GF85ad1X9Ai79WtRsZ2gxJqtBuzH+98YUV6jkHEKlZkMbcrjJjIVJNIDP/3WL9wQkoPbWA== +entities@^4.2.0, entities@^4.4.0: + version "4.5.0" + resolved "https://registry.yarnpkg.com/entities/-/entities-4.5.0.tgz#5d268ea5e7113ec74c4d033b79ea5a35a488fb48" + integrity sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw== error-ex@^1.3.1: version "1.3.2" @@ -3886,15 +3808,27 @@ error-ex@^1.3.1: dependencies: is-arrayish "^0.2.1" -es-module-lexer@^0.9.0: - version "0.9.3" - resolved "https://registry.yarnpkg.com/es-module-lexer/-/es-module-lexer-0.9.3.tgz#6f13db00cc38417137daf74366f535c8eb438f19" - integrity sha512-1HQ2M2sPtxwnvOvT1ZClHyQDiggdNjURWpY2we6aMKCQiUVxTmVs2UYPLIrD84sS+kMdUwfBSylbJPwNnBrnHQ== +es-define-property@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/es-define-property/-/es-define-property-1.0.0.tgz#c7faefbdff8b2696cf5f46921edfb77cc4ba3845" + integrity sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ== + dependencies: + get-intrinsic "^1.2.4" + +es-errors@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/es-errors/-/es-errors-1.3.0.tgz#05f75a25dab98e4fb1dcd5e1472c0546d5057c8f" + integrity sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw== -escalade@^3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" - integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw== +es-module-lexer@^1.2.1: + version "1.5.4" + resolved "https://registry.yarnpkg.com/es-module-lexer/-/es-module-lexer-1.5.4.tgz#a8efec3a3da991e60efa6b633a7cad6ab8d26b78" + integrity sha512-MVNK56NiMrOwitFB7cqDwq0CQutbw+0BvLshJSse0MUNU+y1FC3bUS/AQg7oUng+/wKrrki7JfmwtVHkVfPLlw== + +escalade@^3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.2.tgz#54076e9ab29ea5bf3d8f1ed62acffbb88272df27" + integrity sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA== escape-goat@^2.0.0: version "2.1.1" @@ -3917,14 +3851,13 @@ escape-string-regexp@^4.0.0: integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== escodegen@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-2.0.0.tgz#5e32b12833e8aa8fa35e1bf0befa89380484c7dd" - integrity sha512-mmHKys/C8BFUGI+MAWNcSYoORYLMdPzjrknd2Vc+bUsjN5bXcr8EhrNB+UTqfL1y3I9c4fw2ihgtMPQLBRiQxw== + version "2.1.0" + resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-2.1.0.tgz#ba93bbb7a43986d29d6041f99f5262da773e2e17" + integrity sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w== dependencies: esprima "^4.0.1" estraverse "^5.2.0" esutils "^2.0.2" - optionator "^0.8.1" optionalDependencies: source-map "~0.6.1" @@ -3968,11 +3901,6 @@ esutils@^2.0.2: resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== -eta@^1.12.3: - version "1.12.3" - resolved "https://registry.yarnpkg.com/eta/-/eta-1.12.3.tgz#2982d08adfbef39f9fa50e2fbd42d7337e7338b1" - integrity sha512-qHixwbDLtekO/d51Yr4glcaUJCIjGVJyTzuqV4GPlgZo1YpgOKG+avQynErZIYrfM6JIJdtiG2Kox8tbb+DoGg== - eta@^2.0.0: version "2.2.0" resolved "https://registry.yarnpkg.com/eta/-/eta-2.2.0.tgz#eb8b5f8c4e8b6306561a455e62cd7492fe3a9b8a" @@ -4017,16 +3945,16 @@ execa@^5.0.0: strip-final-newline "^2.0.0" express@^4.17.3: - version "4.18.2" - resolved "https://registry.yarnpkg.com/express/-/express-4.18.2.tgz#3fabe08296e930c796c19e3c516979386ba9fd59" - integrity sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ== + version "4.19.2" + resolved "https://registry.yarnpkg.com/express/-/express-4.19.2.tgz#e25437827a3aa7f2a827bc8171bbbb664a356465" + integrity sha512-5T6nhjsT+EOMzuck8JjBHARTHfMht0POzlA60WV2pMD3gyXw2LZnZ+ueGdNxG+0calOJcWKbpFcuzLZ91YWq9Q== dependencies: accepts "~1.3.8" array-flatten "1.1.1" - body-parser "1.20.1" + body-parser "1.20.2" content-disposition "0.5.4" content-type "~1.0.4" - cookie "0.5.0" + cookie "0.6.0" cookie-signature "1.0.6" debug "2.6.9" depd "2.0.0" @@ -4070,10 +3998,10 @@ fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== -fast-glob@^3.2.11, fast-glob@^3.2.9: - version "3.2.12" - resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.12.tgz#7f39ec99c2e6ab030337142da9e0c18f37afae80" - integrity sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w== +fast-glob@^3.2.11, fast-glob@^3.2.9, fast-glob@^3.3.0: + version "3.3.2" + resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.3.2.tgz#a904501e57cfdd2ffcded45e99a54fef55e46129" + integrity sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow== dependencies: "@nodelib/fs.stat" "^2.0.2" "@nodelib/fs.walk" "^1.2.3" @@ -4086,10 +4014,10 @@ fast-json-stable-stringify@^2.0.0: resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== -fast-levenshtein@~2.0.6: - version "2.0.6" - resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" - integrity sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw== +fast-uri@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/fast-uri/-/fast-uri-3.0.1.tgz#cddd2eecfc83a71c1be2cc2ef2061331be8a7134" + integrity sha512-MWipKbbYiYI0UC7cl8m/i/IWTqfC8YXsqjzybjddLsFjStroQzsHXkc73JutMvBiXmOvapk+axIl79ig5t55Bw== fast-url-parser@1.1.3: version "1.1.3" @@ -4099,9 +4027,9 @@ fast-url-parser@1.1.3: punycode "^1.3.2" fastq@^1.6.0: - version "1.13.0" - resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.13.0.tgz#616760f88a7526bdfc596b7cab8c18938c36b98c" - integrity sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw== + version "1.17.1" + resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.17.1.tgz#2a523f07a4e7b1e81a42b91b8bf2254107753b47" + integrity sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w== dependencies: reusify "^1.0.4" @@ -4125,9 +4053,9 @@ fbjs-css-vars@^1.0.0: integrity sha512-b2XGFAFdWZWg0phtAWLHCk836A1Xann+I+Dgd3Gk64MHKZO44FfoD1KxyvbSh0qZsIoXQGGlVztIY+oitJPpRQ== fbjs@^3.0.0, fbjs@^3.0.1: - version "3.0.4" - resolved "https://registry.yarnpkg.com/fbjs/-/fbjs-3.0.4.tgz#e1871c6bd3083bac71ff2da868ad5067d37716c6" - integrity sha512-ucV0tDODnGV3JCnnkmoszb5lf4bNpzjv80K41wd4k798Etq+UYD0y0TIfalLjZoKgjive6/adkRnszwapiDgBQ== + version "3.0.5" + resolved "https://registry.yarnpkg.com/fbjs/-/fbjs-3.0.5.tgz#aa0edb7d5caa6340011790bd9249dbef8a81128d" + integrity sha512-ztsSx77JBtkuMrEypfhgc3cI0+0h+svqeie7xHbh1k/IKdcydnvadp/mUaGgjAOXQmQSxsqgaRhS3q9fy+1kxg== dependencies: cross-fetch "^3.1.5" fbjs-css-vars "^1.0.0" @@ -4135,7 +4063,7 @@ fbjs@^3.0.0, fbjs@^3.0.1: object-assign "^4.1.0" promise "^7.1.1" setimmediate "^1.0.5" - ua-parser-js "^0.7.30" + ua-parser-js "^1.0.35" feed@^4.2.2: version "4.2.2" @@ -4157,10 +4085,10 @@ filesize@^8.0.6: resolved "https://registry.yarnpkg.com/filesize/-/filesize-8.0.7.tgz#695e70d80f4e47012c132d57a059e80c6b580bd8" integrity sha512-pjmC+bkIF8XI7fWaH8KxHcZL3DPybs1roSKP4rKDvy20tAWwIObE4+JIseG2byfGKhud5ZnM4YSGKBz7Sh0ndQ== -fill-range@^7.0.1: - version "7.0.1" - resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40" - integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ== +fill-range@^7.1.1: + version "7.1.1" + resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.1.1.tgz#44265d3cac07e3ea7dc247516380643754a05292" + integrity sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg== dependencies: to-regex-range "^5.0.1" @@ -4209,23 +4137,28 @@ find-up@^5.0.0: locate-path "^6.0.0" path-exists "^4.0.0" +flat@^5.0.2: + version "5.0.2" + resolved "https://registry.yarnpkg.com/flat/-/flat-5.0.2.tgz#8ca6fe332069ffa9d324c327198c598259ceb241" + integrity sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ== + flux@^4.0.1: - version "4.0.3" - resolved "https://registry.yarnpkg.com/flux/-/flux-4.0.3.tgz#573b504a24982c4768fdfb59d8d2ea5637d72ee7" - integrity sha512-yKAbrp7JhZhj6uiT1FTuVMlIAT1J4jqEyBpFApi1kxpGZCvacMVc/t1pMQyotqHhAgvoE3bNvAykhCo2CLjnYw== + version "4.0.4" + resolved "https://registry.yarnpkg.com/flux/-/flux-4.0.4.tgz#9661182ea81d161ee1a6a6af10d20485ef2ac572" + integrity sha512-NCj3XlayA2UsapRpM7va6wU1+9rE5FIL7qoMcmxWHRzbp0yujihMBm9BBHZ1MDIk5h5o2Bl6eGiCe8rYELAmYw== dependencies: fbemitter "^3.0.0" fbjs "^3.0.1" follow-redirects@^1.0.0, follow-redirects@^1.14.7: - version "1.15.2" - resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.2.tgz#b460864144ba63f2681096f274c4e57026da2c13" - integrity sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA== + version "1.15.6" + resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.6.tgz#7f815c0cda4249c74ff09e95ef97c23b5fd0399b" + integrity sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA== fork-ts-checker-webpack-plugin@^6.5.0: - version "6.5.2" - resolved "https://registry.yarnpkg.com/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-6.5.2.tgz#4f67183f2f9eb8ba7df7177ce3cf3e75cdafb340" - integrity sha512-m5cUmF30xkZ7h4tWUgTAcEaKmUW7tfyUyTqNNOz7OxWJ0v1VWKTcOvH8FWHUwSjlW/356Ijc9vi3XfcPstpQKA== + version "6.5.3" + resolved "https://registry.yarnpkg.com/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-6.5.3.tgz#eda2eff6e22476a2688d10661688c47f611b37f3" + integrity sha512-SbH/l9ikmMWycd5puHJKTkZJKddF4iRLyW3DeZ08HTI7NGyLS38MXd/KGgeWumQO7YNQbW2u/NtPT2YowbPaGQ== dependencies: "@babel/code-frame" "^7.8.3" "@types/json-schema" "^7.0.5" @@ -4255,10 +4188,10 @@ forwarded@0.2.0: resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.2.0.tgz#2269936428aad4c15c7ebe9779a84bf0b2a81811" integrity sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow== -fraction.js@^4.2.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/fraction.js/-/fraction.js-4.2.0.tgz#448e5109a313a3527f5a3ab2119ec4cf0e0e2950" - integrity sha512-MhLuK+2gUcnZe8ZHlaaINnQLl0xRIGRfcGk2yl8xoQAfHrSsL3rYu6FCmBdkdbhc9EPlwyGHewaRsvwRMJtAlA== +fraction.js@^4.3.7: + version "4.3.7" + resolved "https://registry.yarnpkg.com/fraction.js/-/fraction.js-4.3.7.tgz#06ca0085157e42fda7f9e726e79fefc4068840f7" + integrity sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew== fresh@0.5.2: version "0.5.2" @@ -4284,10 +4217,10 @@ fs-extra@^9.0.0: jsonfile "^6.0.1" universalify "^2.0.0" -fs-monkey@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/fs-monkey/-/fs-monkey-1.0.3.tgz#ae3ac92d53bb328efe0e9a1d9541f6ad8d48e2d3" - integrity sha512-cybjIfiiE+pTWicSCLFHSrXZ6EilF30oh91FDP9S2B051prEa7QWfrVTQm10/dDpswBDXZugPa1Ogu8Yh+HV0Q== +fs-monkey@^1.0.4: + version "1.0.6" + resolved "https://registry.yarnpkg.com/fs-monkey/-/fs-monkey-1.0.6.tgz#8ead082953e88d992cf3ff844faa907b26756da2" + integrity sha512-b1FMfwetIKymC0eioW7mTywihSQE4oLzQn1dB6rZB5fx/3NpNEdAWeCSMB+60/AeT0TCXsxzAlcYVEFCTAksWg== fs.realpath@^1.0.0: version "1.0.0" @@ -4295,28 +4228,30 @@ fs.realpath@^1.0.0: integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw== fsevents@~2.3.2: - version "2.3.2" - resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a" - integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA== + version "2.3.3" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.3.tgz#cac6407785d03675a2a5e1a5305c697b347d90d6" + integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw== -function-bind@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" - integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== +function-bind@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.2.tgz#2c02d864d97f3ea6c8830c464cbd11ab6eab7a1c" + integrity sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA== gensync@^1.0.0-beta.1, gensync@^1.0.0-beta.2: version "1.0.0-beta.2" resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.2.tgz#32a6ee76c3d7f52d46b2b1ae5d93fea8580a25e0" integrity sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg== -get-intrinsic@^1.0.2, get-intrinsic@^1.1.1: - version "1.1.3" - resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.1.3.tgz#063c84329ad93e83893c7f4f243ef63ffa351385" - integrity sha512-QJVz1Tj7MS099PevUG5jvnt9tSkXN8K14dxQlikJuPt4uD9hHAHjLyLBiLR5zELelBdD9QNRAXZzsJx0WaDL9A== +get-intrinsic@^1.1.3, get-intrinsic@^1.2.4: + version "1.2.4" + resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.2.4.tgz#e385f5a4b5227d449c3eabbad05494ef0abbeadd" + integrity sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ== dependencies: - function-bind "^1.1.1" - has "^1.0.3" + es-errors "^1.3.0" + function-bind "^1.1.2" + has-proto "^1.0.1" has-symbols "^1.0.3" + hasown "^2.0.0" get-own-enumerable-property-symbols@^3.0.0: version "3.0.2" @@ -4424,16 +4359,23 @@ globby@^11.0.1, globby@^11.0.4, globby@^11.1.0: slash "^3.0.0" globby@^13.1.1: - version "13.1.2" - resolved "https://registry.yarnpkg.com/globby/-/globby-13.1.2.tgz#29047105582427ab6eca4f905200667b056da515" - integrity sha512-LKSDZXToac40u8Q1PQtZihbNdTYSNMuWe+K5l+oa6KgDzSvVrHXlJy40hUP522RjAIoNLJYBJi7ow+rbFpIhHQ== + version "13.2.2" + resolved "https://registry.yarnpkg.com/globby/-/globby-13.2.2.tgz#63b90b1bf68619c2135475cbd4e71e66aa090592" + integrity sha512-Y1zNGV+pzQdh7H39l9zgB4PJqjRNqydvdYCDG4HFXM4XuvSaQQlEc91IU1yALL8gUTDomgBAfz3XJdmUS+oo0w== dependencies: dir-glob "^3.0.1" - fast-glob "^3.2.11" - ignore "^5.2.0" + fast-glob "^3.3.0" + ignore "^5.2.4" merge2 "^1.4.1" slash "^4.0.0" +gopd@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/gopd/-/gopd-1.0.1.tgz#29ff76de69dac7489b7c0918a5788e56477c332c" + integrity sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA== + dependencies: + get-intrinsic "^1.1.3" + got@^9.6.0: version "9.6.0" resolved "https://registry.yarnpkg.com/got/-/got-9.6.0.tgz#edf45e7d67f99545705de1f7bbeeeb121765ed85" @@ -4451,10 +4393,10 @@ got@^9.6.0: to-readable-stream "^1.0.0" url-parse-lax "^3.0.0" -graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.4, graceful-fs@^4.2.6, graceful-fs@^4.2.9: - version "4.2.10" - resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.10.tgz#147d3a006da4ca3ce14728c7aefc287c367d7a6c" - integrity sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA== +graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.11, graceful-fs@^4.2.4, graceful-fs@^4.2.6, graceful-fs@^4.2.9: + version "4.2.11" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3" + integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ== gray-matter@^4.0.3: version "4.0.3" @@ -4488,12 +4430,17 @@ has-flag@^4.0.0: resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== -has-property-descriptors@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz#610708600606d36961ed04c196193b6a607fa861" - integrity sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ== +has-property-descriptors@^1.0.0, has-property-descriptors@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz#963ed7d071dc7bf5f084c5bfbe0d1b6222586854" + integrity sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg== dependencies: - get-intrinsic "^1.1.1" + es-define-property "^1.0.0" + +has-proto@^1.0.1: + version "1.0.3" + resolved "https://registry.yarnpkg.com/has-proto/-/has-proto-1.0.3.tgz#b31ddfe9b0e6e9914536a6ab286426d0214f77fd" + integrity sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q== has-symbols@^1.0.3: version "1.0.3" @@ -4505,12 +4452,12 @@ has-yarn@^2.1.0: resolved "https://registry.yarnpkg.com/has-yarn/-/has-yarn-2.1.0.tgz#137e11354a7b5bf11aa5cb649cf0c6f3ff2b2e77" integrity sha512-UqBRqi4ju7T+TqGNdqAO0PaSVGsDGJUBQvk9eUWNGRY1CFGDzYhLWoM7JQEemnlvVcv/YEmc2wNW8BC24EnUsw== -has@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" - integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw== +hasown@^2.0.0, hasown@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/hasown/-/hasown-2.0.2.tgz#003eaf91be7adc372e84ec59dc37252cedb80003" + integrity sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ== dependencies: - function-bind "^1.1.1" + function-bind "^1.1.2" hast-to-hyperscript@^9.0.0: version "9.0.1" @@ -4526,9 +4473,9 @@ hast-to-hyperscript@^9.0.0: web-namespaces "^1.0.0" hast-util-from-dom@^4.0.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/hast-util-from-dom/-/hast-util-from-dom-4.1.0.tgz#8a09b3bb9c624371e3d5fae114678f663f928d06" - integrity sha512-0EMIYQVIhRfiC1LVdTsvM4yTY0rM/v63wwoYmOYV02mIOASYeQrfQekG4Jhge2kOAMaNFbvppUma47rbeWWE5Q== + version "4.2.0" + resolved "https://registry.yarnpkg.com/hast-util-from-dom/-/hast-util-from-dom-4.2.0.tgz#25836ddecc3cc0849d32749c2a7aec03e94b59a7" + integrity sha512-t1RJW/OpJbCAJQeKi3Qrj1cAOLA0+av/iPFori112+0X7R3wng+jxLA+kXec8K4szqPRGI8vPxbbpEYvvpwaeQ== dependencies: hastscript "^7.0.0" web-namespaces "^2.0.0" @@ -4551,9 +4498,9 @@ hast-util-is-element@1.1.0, hast-util-is-element@^1.0.0: integrity sha512-oUmNua0bFbdrD/ELDSSEadRVtWZOf3iF6Lbv81naqsIV99RnSCieTbWuWCY8BAeEfKJTKl0gRdokv+dELutHGQ== hast-util-is-element@^2.0.0: - version "2.1.2" - resolved "https://registry.yarnpkg.com/hast-util-is-element/-/hast-util-is-element-2.1.2.tgz#fc0b0dc7cef3895e839b8d66979d57b0338c68f3" - integrity sha512-thjnlGAnwP8ef/GSO1Q8BfVk2gundnc2peGQqEg2kUt/IqesiGg/5mSwN2fE7nLzy61pg88NG6xV+UrGOrx9EA== + version "2.1.3" + resolved "https://registry.yarnpkg.com/hast-util-is-element/-/hast-util-is-element-2.1.3.tgz#cd3279cfefb70da6d45496068f020742256fc471" + integrity sha512-O1bKah6mhgEq2WtVMk+Ta5K7pPMqsBBlmzysLdcwKVrqzZQ0CHqUPiIVspNhAG1rvxpvJjtGee17XfauZYKqVA== dependencies: "@types/hast" "^2.0.0" "@types/unist" "^2.0.0" @@ -4564,9 +4511,9 @@ hast-util-parse-selector@^2.0.0: integrity sha512-7j6mrk/qqkSehsM92wQjdIgWM2/BW61u/53G6xmC8i1OmEdKLHbk419QKQUjz6LglWsfqoiHmyMRkP1BGjecNQ== hast-util-parse-selector@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/hast-util-parse-selector/-/hast-util-parse-selector-3.1.0.tgz#a519e27e8b61bd5a98fad494ed06131ce68d9c3f" - integrity sha512-AyjlI2pTAZEOeu7GeBPZhROx0RHBnydkQIXlhnFzDi0qfXTmGUWoCYZtomHbrdrheV4VFUlPcfJ6LMF5T6sQzg== + version "3.1.1" + resolved "https://registry.yarnpkg.com/hast-util-parse-selector/-/hast-util-parse-selector-3.1.1.tgz#25ab00ae9e75cbc62cf7a901f68a247eade659e2" + integrity sha512-jdlwBjEexy1oGz0aJ2f4GKMaVKkA9jwjr4MjAAI22E5fM/TXVZHuS5OpONtdeIkRKqAaryQ2E9xNQxijoThSZA== dependencies: "@types/hast" "^2.0.0" @@ -4607,11 +4554,12 @@ hast-util-to-text@^2.0.0: unist-util-find-after "^3.0.0" hast-util-to-text@^3.1.0: - version "3.1.1" - resolved "https://registry.yarnpkg.com/hast-util-to-text/-/hast-util-to-text-3.1.1.tgz#b7699a75f7a61af6e0befb67660cd78460d96dc6" - integrity sha512-7S3mOBxACy8syL45hCn3J7rHqYaXkxRfsX6LXEU5Shz4nt4GxdjtMUtG+T6G/ZLUHd7kslFAf14kAN71bz30xA== + version "3.1.2" + resolved "https://registry.yarnpkg.com/hast-util-to-text/-/hast-util-to-text-3.1.2.tgz#ecf30c47141f41e91a5d32d0b1e1859fd2ac04f2" + integrity sha512-tcllLfp23dJJ+ju5wCCZHVpzsQQ43+moJbqVX3jNWPB7z/KFC4FyZD6R7y94cHL6MQ33YtMZL8Z0aIXXI4XFTw== dependencies: "@types/hast" "^2.0.0" + "@types/unist" "^2.0.0" hast-util-is-element "^2.0.0" unist-util-find-after "^4.0.0" @@ -4627,9 +4575,9 @@ hastscript@^6.0.0: space-separated-tokens "^1.0.0" hastscript@^7.0.0: - version "7.1.0" - resolved "https://registry.yarnpkg.com/hastscript/-/hastscript-7.1.0.tgz#e402ed48f46161cf2f093badbff30583a5c3c315" - integrity sha512-uBjaTTLN0MkCZxY/R2fWUOcu7FRtUVzKRO5P/RAfgsu3yFiMB1JWCO4AjeVkgHxAira1f2UecHK5WfS9QurlWA== + version "7.2.0" + resolved "https://registry.yarnpkg.com/hastscript/-/hastscript-7.2.0.tgz#0eafb7afb153d047077fa2a833dc9b7ec604d10b" + integrity sha512-TtYPq24IldU8iKoJQqvZOuhi5CyCQRAbvDOX0x1eW6rsHSxa/1i2CCiptNTotGHJ3VoHRGmqiv6/D3q113ikkw== dependencies: "@types/hast" "^2.0.0" comma-separated-tokens "^2.0.0" @@ -4679,9 +4627,14 @@ html-encoding-sniffer@^3.0.0: whatwg-encoding "^2.0.0" html-entities@^2.3.2: - version "2.3.3" - resolved "https://registry.yarnpkg.com/html-entities/-/html-entities-2.3.3.tgz#117d7626bece327fc8baace8868fa6f5ef856e46" - integrity sha512-DV5Ln36z34NNTDgnz0EWGBLZENelNAtkiFA4kyNOG2tDI6Mz1uSWiq1wAKdyjnJwyDiDO7Fa2SO1CTxPXL8VxA== + version "2.5.2" + resolved "https://registry.yarnpkg.com/html-entities/-/html-entities-2.5.2.tgz#201a3cf95d3a15be7099521620d19dfb4f65359f" + integrity sha512-K//PSRMQk4FZ78Kyau+mZurHn3FH0Vwr+H36eE0rPbeYkRRi9YxceYPhuN60UwWorxyKHhqoAJl2OFKa4BVtaA== + +html-escaper@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/html-escaper/-/html-escaper-2.0.2.tgz#dfd60027da36a36dfcbe236262c00a5822681453" + integrity sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg== html-minifier-terser@^6.0.2, html-minifier-terser@^6.1.0: version "6.1.0" @@ -4697,9 +4650,9 @@ html-minifier-terser@^6.0.2, html-minifier-terser@^6.1.0: terser "^5.10.0" html-tags@^3.2.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/html-tags/-/html-tags-3.2.0.tgz#dbb3518d20b726524e4dd43de397eb0a95726961" - integrity sha512-vy7ClnArOZwCnqZgvv+ddgHgJiAFXe3Ge9ML5/mBctVJoUoYPCdxVucOywjDARn6CVoh3dRSFdPHy2sX80L0Wg== + version "3.3.1" + resolved "https://registry.yarnpkg.com/html-tags/-/html-tags-3.3.1.tgz#a04026a18c882e4bba8a01a3d39cfe465d40b5ce" + integrity sha512-ztqyC3kLto0e9WbNp0aeP+M3kTt+nbaIveGmUxAtZa+8iFgKLUOD4YKM5j+f3QD89bra7UeumolZHKuOXnTmeQ== html-void-elements@^1.0.0: version "1.0.5" @@ -4707,9 +4660,9 @@ html-void-elements@^1.0.0: integrity sha512-uE/TxKuyNIcx44cIWnjr/rfIATDH7ZaOMmstu0CwhFG1Dunhlp4OC6/NMbhiwoq5BpW0ubi303qnEk/PZj614w== html-webpack-plugin@^5.5.0: - version "5.5.0" - resolved "https://registry.yarnpkg.com/html-webpack-plugin/-/html-webpack-plugin-5.5.0.tgz#c3911936f57681c1f9f4d8b68c158cd9dfe52f50" - integrity sha512-sy88PC2cRTVxvETRgUHFrL4No3UxvcH8G1NepGhqaTT+GXN2kTamqasot0inS5hXeg1cMbFDt27zzo9p35lZVw== + version "5.6.0" + resolved "https://registry.yarnpkg.com/html-webpack-plugin/-/html-webpack-plugin-5.6.0.tgz#50a8fa6709245608cb00e811eacecb8e0d7b7ea0" + integrity sha512-iwaY4wzbe48AfKLZ/Cc8k0L+FKG6oSNRaZ8x5A/T/IVDGyXcbHncM9TdDa93wn0FsSm82FhTKW7f3vS61thXAw== dependencies: "@types/html-minifier-terser" "^6.0.0" html-minifier-terser "^6.0.2" @@ -4728,19 +4681,19 @@ htmlparser2@^6.1.0: entities "^2.0.0" htmlparser2@^8.0.1: - version "8.0.1" - resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-8.0.1.tgz#abaa985474fcefe269bc761a779b544d7196d010" - integrity sha512-4lVbmc1diZC7GUJQtRQ5yBAeUCL1exyMwmForWkRLnwyzWBFxN633SALPMGYaWZvKe9j1pRZJpauvmxENSp/EA== + version "8.0.2" + resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-8.0.2.tgz#f002151705b383e62433b5cf466f5b716edaec21" + integrity sha512-GYdjWKDkbRLkZ5geuHs5NY1puJ+PXwP7+fHPRz06Eirsb9ugf6d8kkXav6ADhcODhFFPMIXyxkxSuMf3D6NCFA== dependencies: domelementtype "^2.3.0" - domhandler "^5.0.2" + domhandler "^5.0.3" domutils "^3.0.1" - entities "^4.3.0" + entities "^4.4.0" http-cache-semantics@^4.0.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz#49e91c5cbf36c9b94bcfcd71c23d5249ec74e390" - integrity sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ== + version "4.1.1" + resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz#abe02fcb2985460bf0323be664436ec3476a6d5a" + integrity sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ== http-deceiver@^1.2.7: version "1.2.7" @@ -4802,7 +4755,7 @@ http-proxy@^1.18.1: follow-redirects "^1.0.0" requires-port "^1.0.0" -https-proxy-agent@^5.0.0: +https-proxy-agent@^5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz#c59ef224a04fe8b754f3db0063a25ea30d0005d6" integrity sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA== @@ -4834,22 +4787,22 @@ icss-utils@^5.0.0, icss-utils@^5.1.0: resolved "https://registry.yarnpkg.com/icss-utils/-/icss-utils-5.1.0.tgz#c6be6858abd013d768e98366ae47e25d5887b1ae" integrity sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA== -ignore@^5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.2.0.tgz#6d3bac8fa7fe0d45d9f9be7bac2fc279577e345a" - integrity sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ== +ignore@^5.2.0, ignore@^5.2.4: + version "5.3.1" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.3.1.tgz#5073e554cd42c5b33b394375f538b8593e34d4ef" + integrity sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw== image-size@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/image-size/-/image-size-1.0.2.tgz#d778b6d0ab75b2737c1556dd631652eb963bc486" - integrity sha512-xfOoWjceHntRb3qFCrh5ZFORYH8XCdYpASltMhZ/Q0KZiOwjdE/Yl2QCiWdwD+lygV5bMCvauzgu5PxBX/Yerg== + version "1.1.1" + resolved "https://registry.yarnpkg.com/image-size/-/image-size-1.1.1.tgz#ddd67d4dc340e52ac29ce5f546a09f4e29e840ac" + integrity sha512-541xKlUw6jr/6gGuk92F+mYM5zaFAc5ahphvkqvNe2bQ6gVBkd6bfrmVJ2t4KDAfikAYZyIqTnktX3i6/aQDrQ== dependencies: queue "6.0.2" immer@^9.0.7: - version "9.0.16" - resolved "https://registry.yarnpkg.com/immer/-/immer-9.0.16.tgz#8e7caab80118c2b54b37ad43e05758cdefad0198" - integrity sha512-qenGE7CstVm1NrHQbMh8YaSzTZTFNP3zPqr3YU0S0UY441j4bJTg4A2Hh5KAhwgaiU6ZZ1Ar6y/2f4TblnMReQ== + version "9.0.21" + resolved "https://registry.yarnpkg.com/immer/-/immer-9.0.21.tgz#1e025ea31a40f24fb064f1fef23e931496330176" + integrity sha512-bc4NBHqOqSfRW7POMkHd51LvClaeMXpm8dx0e8oE2GORbq5aRK7Bxl4FyzVLdGtLmvLKL7BTDBG5ACQm4HWjTA== import-fresh@^3.1.0, import-fresh@^3.2.1, import-fresh@^3.3.0: version "3.3.0" @@ -4874,10 +4827,10 @@ indent-string@^4.0.0: resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-4.0.0.tgz#624f8f4497d619b2d9768531d58f4122854d7251" integrity sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg== -infima@0.2.0-alpha.42: - version "0.2.0-alpha.42" - resolved "https://registry.yarnpkg.com/infima/-/infima-0.2.0-alpha.42.tgz#f6e86a655ad40877c6b4d11b2ede681eb5470aa5" - integrity sha512-ift8OXNbQQwtbIt6z16KnSWP7uJ/SysSMFI4F87MNRTicypfl4Pv3E2OGVv6N3nSZFJvA8imYulCBS64iyHYww== +infima@0.2.0-alpha.43: + version "0.2.0-alpha.43" + resolved "https://registry.yarnpkg.com/infima/-/infima-0.2.0-alpha.43.tgz#f7aa1d7b30b6c08afef441c726bac6150228cbe0" + integrity sha512-2uw57LvUqW0rK/SWYnd/2rRfxNA5DDNOh33jxF7fy46VWoNhGxiUQyVZHbBMjQ33mQem0cjdDVwgWVAmlRfgyQ== inflight@^1.0.4: version "1.0.6" @@ -4930,9 +4883,9 @@ ipaddr.js@1.9.1: integrity sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g== ipaddr.js@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-2.0.1.tgz#eca256a7a877e917aeb368b0a7497ddf42ef81c0" - integrity sha512-1qTgH9NG+IIJ4yfKs2e6Pp1bZg8wbDbKHT21HrLIeYBTRLgMYKnMTPAuI3Lcs61nfx5h1xlXnbJtH1kX5/d/ng== + version "2.2.0" + resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-2.2.0.tgz#d33fa7bac284f4de7af949638c9d68157c6b92e8" + integrity sha512-Ag3wB2o37wslZS19hZqorUnrnzSkpOVy+IiiDEiTqNubEYpYuHWIf6K4psgN2ZWKExS4xhVCrRVfb/wfW8fWJA== is-alphabetical@1.0.4, is-alphabetical@^1.0.0: version "1.0.4" @@ -4971,12 +4924,12 @@ is-ci@^2.0.0: dependencies: ci-info "^2.0.0" -is-core-module@^2.9.0: - version "2.11.0" - resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.11.0.tgz#ad4cb3e3863e814523c96f3f58d26cc570ff0144" - integrity sha512-RRjxlvLDkD1YJwDbroBHMb+cukurkDWNyHx7D3oNB5x9rb5ogcksMC5wHCadcXoo67gVr/+3GFySh3134zi6rw== +is-core-module@^2.13.0: + version "2.15.0" + resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.15.0.tgz#71c72ec5442ace7e76b306e9d48db361f22699ea" + integrity sha512-Dd+Lb2/zvk9SKy1TGCt1wFJFo/MWBPMX5x7KcvLajWTGuomczdQX61PvY5yK6SVACwpoexWo81IfFyoKY2QnTA== dependencies: - has "^1.0.3" + hasown "^2.0.2" is-decimal@^1.0.0: version "1.0.4" @@ -5142,12 +5095,12 @@ isobject@^3.0.1: resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df" integrity sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg== -jest-util@^29.3.1: - version "29.3.1" - resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-29.3.1.tgz#1dda51e378bbcb7e3bc9d8ab651445591ed373e1" - integrity sha512-7YOVZaiX7RJLv76ZfHt4nbNEzzTRiMW/IiOG7ZOKmTXmoGBxUDefgMAxQubu6WPVqP5zSzAdZG0FfLcC7HOIFQ== +jest-util@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-29.7.0.tgz#23c2b62bfb22be82b44de98055802ff3710fc0bc" + integrity sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA== dependencies: - "@jest/types" "^29.3.1" + "@jest/types" "^29.6.3" "@types/node" "*" chalk "^4.0.0" ci-info "^3.2.0" @@ -5164,24 +5117,29 @@ jest-worker@^27.4.5: supports-color "^8.0.0" jest-worker@^29.1.2: - version "29.3.1" - resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-29.3.1.tgz#e9462161017a9bb176380d721cab022661da3d6b" - integrity sha512-lY4AnnmsEWeiXirAIA0c9SDPbuCBq8IYuDVL8PMm0MZ2PEs2yPvRA/J64QBXuZp7CYKrDM/rmNrc9/i3KJQncw== + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-29.7.0.tgz#acad073acbbaeb7262bd5389e1bcf43e10058d4a" + integrity sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw== dependencies: "@types/node" "*" - jest-util "^29.3.1" + jest-util "^29.7.0" merge-stream "^2.0.0" supports-color "^8.0.0" +jiti@^1.20.0: + version "1.21.6" + resolved "https://registry.yarnpkg.com/jiti/-/jiti-1.21.6.tgz#6c7f7398dd4b3142767f9a168af2f317a428d268" + integrity sha512-2yTgeWTWzMWkHu6Jp9NKgePDaYHbntiwvYuuJLbbN9vl7DC9DvXKOB2BC3ZZ92D3cvV/aflH0osDfwpHepQ53w== + joi@^17.6.0: - version "17.7.0" - resolved "https://registry.yarnpkg.com/joi/-/joi-17.7.0.tgz#591a33b1fe1aca2bc27f290bcad9b9c1c570a6b3" - integrity sha512-1/ugc8djfn93rTE3WRKdCzGGt/EtiYKxITMO4Wiv6q5JL1gl9ePt4kBsl1S499nbosspfctIQTpYIhSmHA3WAg== - dependencies: - "@hapi/hoek" "^9.0.0" - "@hapi/topo" "^5.0.0" - "@sideway/address" "^4.1.3" - "@sideway/formula" "^3.0.0" + version "17.13.3" + resolved "https://registry.yarnpkg.com/joi/-/joi-17.13.3.tgz#0f5cc1169c999b30d344366d384b12d92558bcec" + integrity sha512-otDA4ldcIx+ZXsKHWmp0YizCweVRZG96J10b0FevjfuncLO1oX59THoAmHkNubYJ+9gWsYsp5k8v4ib6oDv1fA== + dependencies: + "@hapi/hoek" "^9.3.0" + "@hapi/topo" "^5.1.0" + "@sideway/address" "^4.1.5" + "@sideway/formula" "^3.0.1" "@sideway/pinpoint" "^2.0.0" "js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0: @@ -5204,37 +5162,36 @@ js-yaml@^4.1.0: dependencies: argparse "^2.0.1" -jsdom@^18.0.0: - version "18.1.1" - resolved "https://registry.yarnpkg.com/jsdom/-/jsdom-18.1.1.tgz#15ec896f5ab7df9669a62375606f47c8c09551aa" - integrity sha512-NmJQbjQ/gpS/1at/ce3nCx89HbXL/f5OcenBe8wU1Eik0ROhyUc3LtmG3567dEHAGXkN8rmILW/qtCOPxPHQJw== +jsdom@^20.0.0: + version "20.0.3" + resolved "https://registry.yarnpkg.com/jsdom/-/jsdom-20.0.3.tgz#886a41ba1d4726f67a8858028c99489fed6ad4db" + integrity sha512-SYhBvTh89tTfCD/CRdSOm13mOBa42iTaTyfyEWBdKcGdPxPtLFBXuHR8XHb33YNYaP+lLbmSvBTsnoesCNJEsQ== dependencies: - abab "^2.0.5" - acorn "^8.5.0" - acorn-globals "^6.0.0" + abab "^2.0.6" + acorn "^8.8.1" + acorn-globals "^7.0.0" cssom "^0.5.0" cssstyle "^2.3.0" - data-urls "^3.0.1" - decimal.js "^10.3.1" + data-urls "^3.0.2" + decimal.js "^10.4.2" domexception "^4.0.0" escodegen "^2.0.0" form-data "^4.0.0" html-encoding-sniffer "^3.0.0" http-proxy-agent "^5.0.0" - https-proxy-agent "^5.0.0" + https-proxy-agent "^5.0.1" is-potential-custom-element-name "^1.0.1" - nwsapi "^2.2.0" - parse5 "6.0.1" - saxes "^5.0.1" + nwsapi "^2.2.2" + parse5 "^7.1.1" + saxes "^6.0.0" symbol-tree "^3.2.4" - tough-cookie "^4.0.0" - w3c-hr-time "^1.0.2" - w3c-xmlserializer "^3.0.0" + tough-cookie "^4.1.2" + w3c-xmlserializer "^4.0.0" webidl-conversions "^7.0.0" whatwg-encoding "^2.0.0" whatwg-mimetype "^3.0.0" - whatwg-url "^10.0.0" - ws "^8.2.3" + whatwg-url "^11.0.0" + ws "^8.11.0" xml-name-validator "^4.0.0" jsesc@^2.5.1: @@ -5267,10 +5224,10 @@ json-schema-traverse@^1.0.0: resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz#ae7bcb3656ab77a73ba5c49bf654f38e6b6860e2" integrity sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug== -json5@^2.1.2, json5@^2.2.1: - version "2.2.1" - resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.1.tgz#655d50ed1e6f95ad1a3caababd2b0efda10b395c" - integrity sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA== +json5@^2.1.2, json5@^2.2.3: + version "2.2.3" + resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.3.tgz#78cd6f1a19bdc12b73db5ad0c61efd66c1e29283" + integrity sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg== jsonfile@^6.0.1: version "6.1.0" @@ -5305,11 +5262,6 @@ kleur@^3.0.3: resolved "https://registry.yarnpkg.com/kleur/-/kleur-3.0.3.tgz#a79c9ecc86ee1ce3fa6206d1216c501f147fc07e" integrity sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w== -klona@^2.0.5: - version "2.0.5" - resolved "https://registry.yarnpkg.com/klona/-/klona-2.0.5.tgz#d166574d90076395d9963aa7a928fabb8d76afbc" - integrity sha512-pJiBpiXMbt7dkzXe8Ghj/u4FfXOOa98fPW+bihOJ4SjnoijweJrNThJfd3ifXpXhREjpoF2mZVH1GfS9LV3kHQ== - latest-version@^5.1.0: version "5.1.0" resolved "https://registry.yarnpkg.com/latest-version/-/latest-version-5.1.0.tgz#119dfe908fe38d15dfa43ecd13fa12ec8832face" @@ -5317,23 +5269,23 @@ latest-version@^5.1.0: dependencies: package-json "^6.3.0" +launch-editor@^2.6.0: + version "2.8.0" + resolved "https://registry.yarnpkg.com/launch-editor/-/launch-editor-2.8.0.tgz#7255d90bdba414448e2138faa770a74f28451305" + integrity sha512-vJranOAJrI/llyWGRQqiDM+adrw+k83fvmmx3+nV47g3+36xM15jE+zyZ6Ffel02+xSvuM0b2GDRosXZkbb6wA== + dependencies: + picocolors "^1.0.0" + shell-quote "^1.8.1" + leven@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/leven/-/leven-3.1.0.tgz#77891de834064cccba82ae7842bb6b14a13ed7f2" integrity sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A== -levn@~0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/levn/-/levn-0.3.0.tgz#3b09924edf9f083c0490fdd4c0bc4421e04764ee" - integrity sha512-0OO4y2iOHix2W6ujICbKIaEQXvFQHue65vUG3pb5EUomzPI90z9hsA1VsO/dbIIpC53J8gxM9Q4Oho0jrCM/yA== - dependencies: - prelude-ls "~1.1.2" - type-check "~0.3.2" - lilconfig@^2.0.3: - version "2.0.6" - resolved "https://registry.yarnpkg.com/lilconfig/-/lilconfig-2.0.6.tgz#32a384558bd58af3d4c6e077dd1ad1d397bc69d4" - integrity sha512-9JROoBW7pobfsx+Sq2JsASvCo6Pfo6WWoUW79HuB1BCoBXD4PLWJPqDF6fNj67pqBYTbAHkE57M1kS/+L1neOg== + version "2.1.0" + resolved "https://registry.yarnpkg.com/lilconfig/-/lilconfig-2.1.0.tgz#78e23ac89ebb7e1bfbf25b18043de756548e7f52" + integrity sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ== lines-and-columns@^1.1.6: version "1.2.4" @@ -5355,9 +5307,9 @@ loader-utils@^2.0.0: json5 "^2.1.2" loader-utils@^3.2.0: - version "3.2.1" - resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-3.2.1.tgz#4fb104b599daafd82ef3e1a41fb9265f87e1f576" - integrity sha512-ZvFw1KWS3GVyYBYb7qkmRM/WwL2TQQBxgCK62rlvm4WpVQ23Nb4tYjApUlfjrEGvOs7KHEsmyUn75OHZrJMWPw== + version "3.3.1" + resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-3.3.1.tgz#735b9a19fd63648ca7adbd31c2327dfe281304e5" + integrity sha512-FMJTLMXfCLMLfJxcX9PFqX5qD88Z5MRGaZCVzfuqeZSPsyiBzs+pahDQjbIWz2QIzPZz0NX9Zy4FX3lmK6YHIg== locate-path@^3.0.0: version "3.0.0" @@ -5435,12 +5387,12 @@ lowercase-keys@^2.0.0: resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-2.0.0.tgz#2603e78b7b4b0006cbca2fbcc8a3202558ac9479" integrity sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA== -lru-cache@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94" - integrity sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA== +lru-cache@^5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-5.1.1.tgz#1da27e6710271947695daf6848e847f01d84b920" + integrity sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w== dependencies: - yallist "^4.0.0" + yallist "^3.0.2" make-dir@^3.0.0, make-dir@^3.0.2, make-dir@^3.1.0: version "3.1.0" @@ -5513,11 +5465,11 @@ media-typer@0.3.0: integrity sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ== memfs@^3.1.2, memfs@^3.4.3: - version "3.4.12" - resolved "https://registry.yarnpkg.com/memfs/-/memfs-3.4.12.tgz#d00f8ad8dab132dc277c659dc85bfd14b07d03bd" - integrity sha512-BcjuQn6vfqP+k100e0E9m61Hyqa//Brp+I3f0OBmN0ATHlFA8vx3Lt8z57R3u2bPqe3WGDBC+nF72fTH7isyEw== + version "3.6.0" + resolved "https://registry.yarnpkg.com/memfs/-/memfs-3.6.0.tgz#d7a2110f86f79dd950a8b6df6d57bc984aa185f6" + integrity sha512-EGowvkkgbMcIChjMTMkESFDbZeSh8xZ7kNSF0hAiAN4Jh6jgHCRS0Ga/+C8y6Au+oqpezRHCfPsmJ2+DwAgiwQ== dependencies: - fs-monkey "^1.0.3" + fs-monkey "^1.0.4" merge-descriptors@1.0.1: version "1.0.1" @@ -5540,23 +5492,28 @@ methods@~1.1.2: integrity sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w== mhchemparser@^4.1.0: - version "4.1.1" - resolved "https://registry.yarnpkg.com/mhchemparser/-/mhchemparser-4.1.1.tgz#a2142fdab37a02ec8d1b48a445059287790becd5" - integrity sha512-R75CUN6O6e1t8bgailrF1qPq+HhVeFTM3XQ0uzI+mXTybmphy3b6h4NbLOYhemViQ3lUs+6CKRkC3Ws1TlYREA== + version "4.2.1" + resolved "https://registry.yarnpkg.com/mhchemparser/-/mhchemparser-4.2.1.tgz#d73982e66bc06170a85b1985600ee9dabe157cb0" + integrity sha512-kYmyrCirqJf3zZ9t/0wGgRZ4/ZJw//VwaRVGA75C4nhE60vtnIzhl9J9ndkX/h6hxSN7pjg/cE0VxbnNM+bnDQ== micromatch@^4.0.2, micromatch@^4.0.4, micromatch@^4.0.5: - version "4.0.5" - resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.5.tgz#bc8999a7cbbf77cdc89f132f6e467051b49090c6" - integrity sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA== + version "4.0.7" + resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.7.tgz#33e8190d9fe474a9895525f5618eee136d46c2e5" + integrity sha512-LPP/3KorzCwBxfeUuZmaR6bG2kdeHSbe0P2tY3FLRU4vYrjYz5hI4QZwV0njUx3jeuKe67YukQ1LSPZBKDqO/Q== dependencies: - braces "^3.0.2" + braces "^3.0.3" picomatch "^2.3.1" -mime-db@1.52.0, "mime-db@>= 1.43.0 < 2": +mime-db@1.52.0: version "1.52.0" resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70" integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== +"mime-db@>= 1.43.0 < 2": + version "1.53.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.53.0.tgz#3cb63cd820fc29896d9d4e8c32ab4fcd74ccb447" + integrity sha512-oHlN/w+3MQ3rba9rqFr6V/ypF10LSkdwUysQL7GkXoTgIWeV+tcXGA852TBxH+gsh8UWoyhR1hKcoMJTuWflpg== + mime-db@~1.33.0: version "1.33.0" resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.33.0.tgz#a3492050a5cb9b63450541e39d9788d2272783db" @@ -5592,11 +5549,12 @@ mimic-response@^1.0.0, mimic-response@^1.0.1: integrity sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ== mini-css-extract-plugin@^2.6.1: - version "2.7.0" - resolved "https://registry.yarnpkg.com/mini-css-extract-plugin/-/mini-css-extract-plugin-2.7.0.tgz#d7d9ba0c5b596d155e36e2b174082fc7f010dd64" - integrity sha512-auqtVo8KhTScMsba7MbijqZTfibbXiBNlPAQbsVt7enQfcDYLdgG57eGxMqwVU3mfeWANY4F1wUg+rMF+ycZgw== + version "2.9.0" + resolved "https://registry.yarnpkg.com/mini-css-extract-plugin/-/mini-css-extract-plugin-2.9.0.tgz#c73a1327ccf466f69026ac22a8e8fd707b78a235" + integrity sha512-Zs1YsZVfemekSZG+44vBsYTLQORkPMwnlv+aehcxK/NLKC+EGhDB39/YePYYqx/sTk6NnYpuqikhSn7+JIevTA== dependencies: schema-utils "^4.0.0" + tapable "^2.2.1" minimalistic-assert@^1.0.0: version "1.0.1" @@ -5611,19 +5569,19 @@ minimatch@3.1.2, minimatch@^3.0.4, minimatch@^3.0.5, minimatch@^3.1.1: brace-expansion "^1.1.7" minimist@^1.2.0, minimist@^1.2.5: - version "1.2.7" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.7.tgz#daa1c4d91f507390437c6a8bc01078e7000c4d18" - integrity sha512-bzfL1YUZsP41gmu/qjrEk0Q6i2ix/cVeAhbCbqH9u3zYutS1cLg00qhrD0M2MVdCcx4Sc0UpP2eBWo9rotpq6g== + version "1.2.8" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c" + integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA== mj-context-menu@^0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/mj-context-menu/-/mj-context-menu-0.6.1.tgz#a043c5282bf7e1cf3821de07b13525ca6f85aa69" integrity sha512-7NO5s6n10TIV96d4g2uDpG7ZDpIhMh0QNfGdJw/W47JswFcosz457wqz/b5sAKvl12sxINGFCn80NZHKwxQEXA== -mrmime@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/mrmime/-/mrmime-1.0.1.tgz#5f90c825fad4bdd41dc914eff5d1a8cfdaf24f27" - integrity sha512-hzzEagAgDyoU1Q6yg5uI+AorQgdvMCur3FcKf7NhMKWsaYg+RnbTyHRa/9IlLF9rf455MOCtcqqrQQ83pPP7Uw== +mrmime@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/mrmime/-/mrmime-2.0.0.tgz#151082a6e06e59a9a39b46b3e14d5cfe92b3abb4" + integrity sha512-eu38+hdgojoyq63s+yTpN4XMBdt5l8HhMhc4VKLO9KM5caLIBvUm4thi7fFaxyTmCKeNnXZ5pAlBwCUnhA09uw== ms@2.0.0: version "2.0.0" @@ -5648,10 +5606,10 @@ multicast-dns@^7.2.5: dns-packet "^5.2.2" thunky "^1.0.2" -nanoid@^3.3.4: - version "3.3.4" - resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.4.tgz#730b67e3cd09e2deacf03c027c81c9d9dbc5e8ab" - integrity sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw== +nanoid@^3.3.7: + version "3.3.7" + resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.7.tgz#d0c301a691bc8d54efa0a2226ccf3fe2fd656bd8" + integrity sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g== negotiator@0.6.3: version "0.6.3" @@ -5678,10 +5636,10 @@ node-emoji@^1.10.0: dependencies: lodash "^4.17.21" -node-fetch@2.6.7: - version "2.6.7" - resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.7.tgz#24de9fba827e3b4ae44dc8b20256a379160052ad" - integrity sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ== +node-fetch@^2.6.12: + version "2.7.0" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.7.0.tgz#d0f0fa6e3e2dc1d27efcd8ad99d550bda94d187d" + integrity sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A== dependencies: whatwg-url "^5.0.0" @@ -5690,10 +5648,10 @@ node-forge@^1: resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-1.3.1.tgz#be8da2af243b2417d5f646a770663a92b7e9ded3" integrity sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA== -node-releases@^2.0.6: - version "2.0.6" - resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.6.tgz#8a7088c63a55e493845683ebf3c828d8c51c5503" - integrity sha512-PiVXnNuFm5+iYkLBNeq5211hvO38y63T0i2KKh2KnUs3RpzJ+JtODFjkD8yjLwnDkTYF1eKXheUwdssR+NRZdg== +node-releases@^2.0.14: + version "2.0.18" + resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.18.tgz#f010e8d35e2fe8d6b2944f03f70213ecedc4ca3f" + integrity sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g== normalize-path@^3.0.0, normalize-path@~3.0.0: version "3.0.0" @@ -5734,20 +5692,20 @@ nth-check@^2.0.1: dependencies: boolbase "^1.0.0" -nwsapi@^2.2.0: - version "2.2.2" - resolved "https://registry.yarnpkg.com/nwsapi/-/nwsapi-2.2.2.tgz#e5418863e7905df67d51ec95938d67bf801f0bb0" - integrity sha512-90yv+6538zuvUMnN+zCr8LuV6bPFdq50304114vJYJ8RDyK8D5O9Phpbd6SZWgI7PwzmmfN1upeOJlvybDSgCw== +nwsapi@^2.2.2: + version "2.2.12" + resolved "https://registry.yarnpkg.com/nwsapi/-/nwsapi-2.2.12.tgz#fb6af5c0ec35b27b4581eb3bbad34ec9e5c696f8" + integrity sha512-qXDmcVlZV4XRtKFzddidpfVP4oMSGhga+xdMc25mv8kaLUHtgzCDhUxkrN8exkGdTlLNaXj7CV3GtON7zuGZ+w== object-assign@^4.1.0, object-assign@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" integrity sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg== -object-inspect@^1.9.0: - version "1.12.2" - resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.12.2.tgz#c0641f26394532f28ab8d796ab954e43c009a8ea" - integrity sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ== +object-inspect@^1.13.1: + version "1.13.2" + resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.13.2.tgz#dea0088467fb991e67af4058147a24824a3043ff" + integrity sha512-IRZSRuzJiynemAXPYtPe5BoI/RESNYR7TYm50MC5Mqbd3Jmw5y790sErYw3V6SryFJD64b74qQQs9wn5Bg/k3g== object-keys@^1.1.1: version "1.1.1" @@ -5755,12 +5713,12 @@ object-keys@^1.1.1: integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA== object.assign@^4.1.0: - version "4.1.4" - resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.4.tgz#9673c7c7c351ab8c4d0b516f4343ebf4dfb7799f" - integrity sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ== + version "4.1.5" + resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.5.tgz#3a833f9ab7fdb80fc9e8d2300c803d216d8fdbb0" + integrity sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ== dependencies: - call-bind "^1.0.2" - define-properties "^1.1.4" + call-bind "^1.0.5" + define-properties "^1.2.1" has-symbols "^1.0.3" object-keys "^1.1.1" @@ -5796,9 +5754,9 @@ onetime@^5.1.2: mimic-fn "^2.1.0" open@^8.0.9, open@^8.4.0: - version "8.4.0" - resolved "https://registry.yarnpkg.com/open/-/open-8.4.0.tgz#345321ae18f8138f82565a910fdc6b39e8c244f8" - integrity sha512-XgFPPM+B28FtCCgSb9I+s9szOC1vZRSwgWsRUA5ylIxRTgKozqjOCrVOqGsYABPYK5qnfqClxZTFBa8PKt2v6Q== + version "8.4.2" + resolved "https://registry.yarnpkg.com/open/-/open-8.4.2.tgz#5b5ffe2a8f793dcd2aad73e550cb87b59cb084f9" + integrity sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ== dependencies: define-lazy-prop "^2.0.0" is-docker "^2.1.1" @@ -5809,18 +5767,6 @@ opener@^1.5.2: resolved "https://registry.yarnpkg.com/opener/-/opener-1.5.2.tgz#5d37e1f35077b9dcac4301372271afdeb2a13598" integrity sha512-ur5UIdyw5Y7yEj9wLzhqXiy6GZ3Mwx0yGI+5sMn2r0N0v3cKJvUmFH5yPP+WXh9e0xfyzyJX95D8l088DNFj7A== -optionator@^0.8.1: - version "0.8.3" - resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.3.tgz#84fa1d036fe9d3c7e21d99884b601167ec8fb495" - integrity sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA== - dependencies: - deep-is "~0.1.3" - fast-levenshtein "~2.0.6" - levn "~0.3.0" - prelude-ls "~1.1.2" - type-check "~0.3.2" - word-wrap "~1.2.3" - p-cancelable@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-1.1.0.tgz#d078d15a3af409220c886f1d9a0ca2e441ab26cc" @@ -5918,7 +5864,7 @@ parse-entities@^2.0.0: is-decimal "^1.0.0" is-hexadecimal "^1.0.0" -parse-json@^5.0.0: +parse-json@^5.0.0, parse-json@^5.2.0: version "5.2.0" resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-5.2.0.tgz#c76fc66dee54231c962b22bcc8a72cf2f99753cd" integrity sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg== @@ -5941,12 +5887,12 @@ parse5-htmlparser2-tree-adapter@^7.0.0: domhandler "^5.0.2" parse5 "^7.0.0" -parse5@6.0.1, parse5@^6.0.0: +parse5@^6.0.0: version "6.0.1" resolved "https://registry.yarnpkg.com/parse5/-/parse5-6.0.1.tgz#e1a1c085c569b3dc08321184f19a39cc27f7c30b" integrity sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw== -parse5@^7.0.0: +parse5@^7.0.0, parse5@^7.1.1: version "7.1.2" resolved "https://registry.yarnpkg.com/parse5/-/parse5-7.1.2.tgz#0736bebbfd77793823240a23b7fc5e010b7f8e32" integrity sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw== @@ -6018,10 +5964,10 @@ path-type@^4.0.0: resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw== -picocolors@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c" - integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ== +picocolors@^1.0.0, picocolors@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.1.tgz#a8ad579b571952f0e5d25892de5445bcfe25aaa1" + integrity sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew== picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.2.3, picomatch@^2.3.1: version "2.3.1" @@ -6050,12 +5996,12 @@ postcss-calc@^8.2.3: postcss-selector-parser "^6.0.9" postcss-value-parser "^4.2.0" -postcss-colormin@^5.3.0: - version "5.3.0" - resolved "https://registry.yarnpkg.com/postcss-colormin/-/postcss-colormin-5.3.0.tgz#3cee9e5ca62b2c27e84fce63affc0cfb5901956a" - integrity sha512-WdDO4gOFG2Z8n4P8TWBpshnL3JpmNmJwdnfP2gbk2qBA8PWwOYcmjmI/t3CmMeL72a7Hkd+x/Mg9O2/0rD54Pg== +postcss-colormin@^5.3.1: + version "5.3.1" + resolved "https://registry.yarnpkg.com/postcss-colormin/-/postcss-colormin-5.3.1.tgz#86c27c26ed6ba00d96c79e08f3ffb418d1d1988f" + integrity sha512-UsWQG0AqTFQmpBegeLLc1+c3jIqBNB0zlDGRWR+dQ3pRKJL1oeMzyqmH3o2PIfn9MBdNrVPWhDbT769LxCTLJQ== dependencies: - browserslist "^4.16.6" + browserslist "^4.21.4" caniuse-api "^3.0.0" colord "^2.9.1" postcss-value-parser "^4.2.0" @@ -6096,13 +6042,13 @@ postcss-discard-unused@^5.1.0: postcss-selector-parser "^6.0.5" postcss-loader@^7.0.0: - version "7.0.1" - resolved "https://registry.yarnpkg.com/postcss-loader/-/postcss-loader-7.0.1.tgz#4c883cc0a1b2bfe2074377b7a74c1cd805684395" - integrity sha512-VRviFEyYlLjctSM93gAZtcJJ/iSkPZ79zWbN/1fSH+NisBByEiVLqpdVDrPLVSi8DX0oJo12kL/GppTBdKVXiQ== + version "7.3.4" + resolved "https://registry.yarnpkg.com/postcss-loader/-/postcss-loader-7.3.4.tgz#aed9b79ce4ed7e9e89e56199d25ad1ec8f606209" + integrity sha512-iW5WTTBSC5BfsBJ9daFMPVrLT36MrNiC6fqOZTTaHjBNX6Pfd5p+hSBqe/fEeNd7pc13QiAyGt7VdGMw4eRC4A== dependencies: - cosmiconfig "^7.0.0" - klona "^2.0.5" - semver "^7.3.7" + cosmiconfig "^8.3.5" + jiti "^1.20.0" + semver "^7.5.4" postcss-merge-idents@^5.1.1: version "5.1.1" @@ -6120,10 +6066,10 @@ postcss-merge-longhand@^5.1.7: postcss-value-parser "^4.2.0" stylehacks "^5.1.1" -postcss-merge-rules@^5.1.3: - version "5.1.3" - resolved "https://registry.yarnpkg.com/postcss-merge-rules/-/postcss-merge-rules-5.1.3.tgz#8f97679e67cc8d08677a6519afca41edf2220894" - integrity sha512-LbLd7uFC00vpOuMvyZop8+vvhnfRGpp2S+IMQKeuOZZapPRY4SMq5ErjQeHbHsjCUgJkRNrlU+LmxsKIqPKQlA== +postcss-merge-rules@^5.1.4: + version "5.1.4" + resolved "https://registry.yarnpkg.com/postcss-merge-rules/-/postcss-merge-rules-5.1.4.tgz#2f26fa5cacb75b1402e213789f6766ae5e40313c" + integrity sha512-0R2IuYpgU93y9lhVbO/OylTtKMVcHb67zjWIfCiKR9rWL3GUk1677LAqD/BcHizukdZEjT8Ru3oHRoAYoJy44g== dependencies: browserslist "^4.21.4" caniuse-api "^3.0.0" @@ -6162,24 +6108,24 @@ postcss-minify-selectors@^5.2.1: dependencies: postcss-selector-parser "^6.0.5" -postcss-modules-extract-imports@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.0.0.tgz#cda1f047c0ae80c97dbe28c3e76a43b88025741d" - integrity sha512-bdHleFnP3kZ4NYDhuGlVK+CMrQ/pqUm8bx/oGL93K6gVwiclvX5x0n76fYMKuIGKzlABOy13zsvqjb0f92TEXw== +postcss-modules-extract-imports@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.1.0.tgz#b4497cb85a9c0c4b5aabeb759bb25e8d89f15002" + integrity sha512-k3kNe0aNFQDAZGbin48pL2VNidTF0w4/eASDsxlyspobzU3wZQLOGj7L9gfRe0Jo9/4uud09DsjFNH7winGv8Q== -postcss-modules-local-by-default@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.0.0.tgz#ebbb54fae1598eecfdf691a02b3ff3b390a5a51c" - integrity sha512-sT7ihtmGSF9yhm6ggikHdV0hlziDTX7oFoXtuVWeDd3hHObNkcHRo9V3yg7vCAY7cONyxJC/XXCmmiHHcvX7bQ== +postcss-modules-local-by-default@^4.0.5: + version "4.0.5" + resolved "https://registry.yarnpkg.com/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.0.5.tgz#f1b9bd757a8edf4d8556e8d0f4f894260e3df78f" + integrity sha512-6MieY7sIfTK0hYfafw1OMEG+2bg8Q1ocHCpoWLqOKj3JXlKu4G7btkmM/B7lFubYkYWmRSPLZi5chid63ZaZYw== dependencies: icss-utils "^5.0.0" postcss-selector-parser "^6.0.2" postcss-value-parser "^4.1.0" -postcss-modules-scope@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/postcss-modules-scope/-/postcss-modules-scope-3.0.0.tgz#9ef3151456d3bbfa120ca44898dfca6f2fa01f06" - integrity sha512-hncihwFA2yPath8oZ15PZqvWGkWf+XUfQgUGamS4LqoP1anQLOsOJw0vr7J7IwLpoY9fatA2qiGUGmuZL0Iqlg== +postcss-modules-scope@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/postcss-modules-scope/-/postcss-modules-scope-3.2.0.tgz#a43d28289a169ce2c15c00c4e64c0858e43457d5" + integrity sha512-oq+g1ssrsZOsx9M96c5w8laRmvEu9C3adDSjI8oTcbfkrTE8hx/zfyobUoWIxaKPO8bt6S62kxpw5GqypEw1QQ== dependencies: postcss-selector-parser "^6.0.4" @@ -6268,10 +6214,10 @@ postcss-reduce-idents@^5.2.0: dependencies: postcss-value-parser "^4.2.0" -postcss-reduce-initial@^5.1.1: - version "5.1.1" - resolved "https://registry.yarnpkg.com/postcss-reduce-initial/-/postcss-reduce-initial-5.1.1.tgz#c18b7dfb88aee24b1f8e4936541c29adbd35224e" - integrity sha512-//jeDqWcHPuXGZLoolFrUXBDyuEGbr9S2rMo19bkTIjBQ4PqkaO+oI8wua5BOUxpfi97i3PCoInsiFIEBfkm9w== +postcss-reduce-initial@^5.1.2: + version "5.1.2" + resolved "https://registry.yarnpkg.com/postcss-reduce-initial/-/postcss-reduce-initial-5.1.2.tgz#798cd77b3e033eae7105c18c9d371d989e1382d6" + integrity sha512-dE/y2XRaqAi6OvjzD22pjTUQ8eOfc6m/natGHgKFBK9DxFmIm69YmaRVQrGgFlEfc1HePIurY0TmDeROK05rIg== dependencies: browserslist "^4.21.4" caniuse-api "^3.0.0" @@ -6284,17 +6230,17 @@ postcss-reduce-transforms@^5.1.0: postcss-value-parser "^4.2.0" postcss-selector-parser@^6.0.2, postcss-selector-parser@^6.0.4, postcss-selector-parser@^6.0.5, postcss-selector-parser@^6.0.9: - version "6.0.11" - resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-6.0.11.tgz#2e41dc39b7ad74046e1615185185cd0b17d0c8dc" - integrity sha512-zbARubNdogI9j7WY4nQJBiNqQf3sLS3wCP4WfOidu+p28LofJqDH1tcXypGrcmMHhDk2t9wGhCsYe/+szLTy1g== + version "6.1.1" + resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-6.1.1.tgz#5be94b277b8955904476a2400260002ce6c56e38" + integrity sha512-b4dlw/9V8A71rLIDsSwVmak9z2DuBUB7CA1/wSdelNEzqsjoSPeADTWNO09lpH49Diy3/JIZ2bSPB1dI3LJCHg== dependencies: cssesc "^3.0.0" util-deprecate "^1.0.2" postcss-sort-media-queries@^4.2.1: - version "4.3.0" - resolved "https://registry.yarnpkg.com/postcss-sort-media-queries/-/postcss-sort-media-queries-4.3.0.tgz#f48a77d6ce379e86676fc3f140cf1b10a06f6051" - integrity sha512-jAl8gJM2DvuIJiI9sL1CuiHtKM4s5aEIomkU8G3LFvbP+p8i7Sz8VV63uieTgoewGqKbi+hxBTiOKJlB35upCg== + version "4.4.1" + resolved "https://registry.yarnpkg.com/postcss-sort-media-queries/-/postcss-sort-media-queries-4.4.1.tgz#04a5a78db3921eb78f28a1a781a2e68e65258128" + integrity sha512-QDESFzDDGKgpiIh4GYXsSy6sek2yAwQx1JASl5AxBtU1Lq2JfKBljIPNdil989NcSKRQX1ToiaKphImtBuhXWw== dependencies: sort-css-media-queries "2.1.0" @@ -6323,19 +6269,14 @@ postcss-zindex@^5.1.0: resolved "https://registry.yarnpkg.com/postcss-zindex/-/postcss-zindex-5.1.0.tgz#4a5c7e5ff1050bd4c01d95b1847dfdcc58a496ff" integrity sha512-fgFMf0OtVSBR1va1JNHYgMxYk73yhn/qb4uQDq1DLGYolz8gHCyr/sesEuGUaYs58E3ZJRcpoGuPVoB7Meiq9A== -postcss@^8.3.11, postcss@^8.4.14, postcss@^8.4.17, postcss@^8.4.18: - version "8.4.19" - resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.19.tgz#61178e2add236b17351897c8bcc0b4c8ecab56fc" - integrity sha512-h+pbPsyhlYj6N2ozBmHhHrs9DzGmbaarbLvWipMRO7RLS+v4onj26MPFXA5OBYFxyqYhUJK456SwDcY9H2/zsA== +postcss@^8.3.11, postcss@^8.4.14, postcss@^8.4.17, postcss@^8.4.33: + version "8.4.40" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.40.tgz#eb81f2a4dd7668ed869a6db25999e02e9ad909d8" + integrity sha512-YF2kKIUzAofPMpfH6hOi2cGnv/HrUlfucspc7pDyvv7kGdqXrfj8SCl/t8owkEgKEuu8ZcRjSOxFxVLqwChZ2Q== dependencies: - nanoid "^3.3.4" - picocolors "^1.0.0" - source-map-js "^1.0.2" - -prelude-ls@~1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54" - integrity sha512-ESF23V4SKG6lVSGZgYNpbsiaAkdab6ZgOxe52p7+Kid3W3u3bxR4Vfd/o21dmN7jSt0IwgZ4v5MUd26FEtXE9w== + nanoid "^3.3.7" + picocolors "^1.0.1" + source-map-js "^1.2.0" prepend-http@^2.0.0: version "2.0.0" @@ -6402,9 +6343,9 @@ property-information@^5.0.0, property-information@^5.3.0: xtend "^4.0.0" property-information@^6.0.0: - version "6.2.0" - resolved "https://registry.yarnpkg.com/property-information/-/property-information-6.2.0.tgz#b74f522c31c097b5149e3c3cb8d7f3defd986a1d" - integrity sha512-kma4U7AFCTwpqq5twzC1YVIDXSqg6qQK6JN0smOw8fgRy1OkMi0CYSzFmsy6dnqSenamAtj0CyXMUJ1Mf6oROg== + version "6.5.0" + resolved "https://registry.yarnpkg.com/property-information/-/property-information-6.5.0.tgz#6212fbb52ba757e92ef4fb9d657563b933b7ffec" + integrity sha512-PgTgs/BlvHxOu8QuEN7wi5A0OmXaBcHpmCSTehcs6Uuu9IkDIEo13Hy7n898RHfrQ49vKCoGeWZSaAK01nwVig== proxy-addr@~2.0.7: version "2.0.7" @@ -6433,9 +6374,9 @@ punycode@^1.3.2: integrity sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ== punycode@^2.1.0, punycode@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" - integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== + version "2.3.1" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.1.tgz#027422e2faec0b25e1549c3e1bd8309b9133b6e5" + integrity sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg== pupa@^2.1.1: version "2.1.1" @@ -6490,10 +6431,10 @@ range-parser@^1.2.1, range-parser@~1.2.1: resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031" integrity sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg== -raw-body@2.5.1: - version "2.5.1" - resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.5.1.tgz#fe1b1628b181b700215e5fd42389f98b71392857" - integrity sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig== +raw-body@2.5.2: + version "2.5.2" + resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.5.2.tgz#99febd83b90e08975087e8f1f9419a149366b68a" + integrity sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA== dependencies: bytes "3.1.2" http-errors "2.0.0" @@ -6564,12 +6505,21 @@ react-error-overlay@^6.0.11: resolved "https://registry.yarnpkg.com/react-error-overlay/-/react-error-overlay-6.0.11.tgz#92835de5841c5cf08ba00ddd2d677b6d17ff9adb" integrity sha512-/6UZ2qgEyH2aqzYZgQPxEnz33NJ2gNsnHA2o5+o4wW9bLM/JYQitNP9xPhsXwC08hMMovfGe/8retsdDsczPRg== -react-fast-compare@^3.2.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/react-fast-compare/-/react-fast-compare-3.2.0.tgz#641a9da81b6a6320f270e89724fb45a0b39e43bb" - integrity sha512-rtGImPZ0YyLrscKI9xTpV8psd6I8VAtjKCzQDlzyDvqJA8XOW78TXYQwNRNd8g8JZnDu8q9Fu/1v4HPAVwVdHA== +react-fast-compare@^3.2.0, react-fast-compare@^3.2.2: + version "3.2.2" + resolved "https://registry.yarnpkg.com/react-fast-compare/-/react-fast-compare-3.2.2.tgz#929a97a532304ce9fee4bcae44234f1ce2c21d49" + integrity sha512-nsO+KSNgo1SbJqJEYRE9ERzo7YtYbou/OqjSQKxV7jcKox7+usiUVZOAC+XnDOABXggQTno0Y1CpVnuWEc1boQ== + +react-helmet-async@*: + version "2.0.5" + resolved "https://registry.yarnpkg.com/react-helmet-async/-/react-helmet-async-2.0.5.tgz#cfc70cd7bb32df7883a8ed55502a1513747223ec" + integrity sha512-rYUYHeus+i27MvFE+Jaa4WsyBKGkL6qVgbJvSBoX8mbsWoABJXdEO0bZyi0F6i+4f0NuIb8AvqPMj3iXFHkMwg== + dependencies: + invariant "^2.2.4" + react-fast-compare "^3.2.2" + shallowequal "^1.1.0" -react-helmet-async@*, react-helmet-async@^1.3.0: +react-helmet-async@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/react-helmet-async/-/react-helmet-async-1.3.0.tgz#7bd5bf8c5c69ea9f02f6083f14ce33ef545c222e" integrity sha512-9jZ57/dAn9t3q6hneQS0wukqC2ENOBgMNVEhb/ZG9ZSxUetzVIw4iAmEU38IaVg3QGYauQPhSeUTuIUtFglWpg== @@ -6643,11 +6593,11 @@ react-router@5.3.4, react-router@^5.3.3: tiny-warning "^1.0.0" react-textarea-autosize@^8.3.2: - version "8.4.0" - resolved "https://registry.yarnpkg.com/react-textarea-autosize/-/react-textarea-autosize-8.4.0.tgz#4d0244d6a50caa897806b8c44abc0540a69bfc8c" - integrity sha512-YrTFaEHLgJsi8sJVYHBzYn+mkP3prGkmP2DKb/tm0t7CLJY5t1Rxix8070LAKb0wby7bl/lf2EeHkuMihMZMwQ== + version "8.5.3" + resolved "https://registry.yarnpkg.com/react-textarea-autosize/-/react-textarea-autosize-8.5.3.tgz#d1e9fe760178413891484847d3378706052dd409" + integrity sha512-XT1024o2pqCuZSuBt9FwHlaDeNtVrtCXu0Rnz88t1jUGheCLa3PhjE1GH8Ctm2axEtvdCl5SUHYschyQ0L5QHQ== dependencies: - "@babel/runtime" "^7.10.2" + "@babel/runtime" "^7.20.13" use-composed-ref "^1.3.0" use-latest "^1.2.1" @@ -6660,9 +6610,9 @@ react@^17.0.1: object-assign "^4.1.1" readable-stream@^2.0.1: - version "2.3.7" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57" - integrity sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw== + version "2.3.8" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.8.tgz#91125e8042bba1b9887f49345f6277027ce8be9b" + integrity sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA== dependencies: core-util-is "~1.0.0" inherits "~2.0.3" @@ -6673,9 +6623,9 @@ readable-stream@^2.0.1: util-deprecate "~1.0.1" readable-stream@^3.0.6: - version "3.6.0" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198" - integrity sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA== + version "3.6.2" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.2.tgz#56a9b36ea965c00c5a93ef31eb111a0f11056967" + integrity sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA== dependencies: inherits "^2.0.3" string_decoder "^1.1.1" @@ -6708,9 +6658,9 @@ recursive-readdir@^2.2.2: minimatch "^3.0.5" regenerate-unicode-properties@^10.1.0: - version "10.1.0" - resolved "https://registry.yarnpkg.com/regenerate-unicode-properties/-/regenerate-unicode-properties-10.1.0.tgz#7c3192cab6dd24e21cb4461e5ddd7dd24fa8374c" - integrity sha512-d1VudCLoIGitcU/hEg2QqvyGZQmdC0Lf8BqdOMXGFSvJP4bNV1+XqbPQeHHLD51Jh4QJJ225dlIFvY4Ly6MXmQ== + version "10.1.1" + resolved "https://registry.yarnpkg.com/regenerate-unicode-properties/-/regenerate-unicode-properties-10.1.1.tgz#6b0e05489d9076b04c436f318d9b067bba459480" + integrity sha512-X007RyZLsCJVVrjgEFVpLUTZwyOZk3oiL75ZcuYjlIWd6rNJtOjkBwQc5AsRrpbKVkxN6sklw/k/9m2jJYOf8Q== dependencies: regenerate "^1.4.2" @@ -6719,26 +6669,26 @@ regenerate@^1.4.2: resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.4.2.tgz#b9346d8827e8f5a32f7ba29637d398b69014848a" integrity sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A== -regenerator-runtime@^0.13.10: - version "0.13.11" - resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz#f6dca3e7ceec20590d07ada785636a90cdca17f9" - integrity sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg== +regenerator-runtime@^0.14.0: + version "0.14.1" + resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz#356ade10263f685dda125100cd862c1db895327f" + integrity sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw== -regenerator-transform@^0.15.0: - version "0.15.1" - resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.15.1.tgz#f6c4e99fc1b4591f780db2586328e4d9a9d8dc56" - integrity sha512-knzmNAcuyxV+gQCufkYcvOqX/qIIfHLv0u5x79kRxuGojfYVky1f15TzZEu2Avte8QGepvUNTnLskf8E6X6Vyg== +regenerator-transform@^0.15.2: + version "0.15.2" + resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.15.2.tgz#5bbae58b522098ebdf09bca2f83838929001c7a4" + integrity sha512-hfMp2BoF0qOk3uc5V20ALGDS2ddjQaLrdl7xrGXvAIow7qeWRM2VA2HuCHkUKk9slq3VwEwLNK3DFBqDfPGYtg== dependencies: "@babel/runtime" "^7.8.4" -regexpu-core@^5.1.0: - version "5.2.2" - resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-5.2.2.tgz#3e4e5d12103b64748711c3aad69934d7718e75fc" - integrity sha512-T0+1Zp2wjF/juXMrMxHxidqGYn8U4R+zleSJhX9tQ1PUsS8a9UtYfbsF9LdiVgNX3kiX8RNaKM42nfSgvFJjmw== +regexpu-core@^5.3.1: + version "5.3.2" + resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-5.3.2.tgz#11a2b06884f3527aec3e93dbbf4a3b958a95546b" + integrity sha512-RAM5FlZz+Lhmo7db9L298p2vHP5ZywrVXmVXpmAD9GuL5MPH6t9ROw1iA/wfHkQ76Qe7AaPF0nGuim96/IrQMQ== dependencies: + "@babel/regjsgen" "^0.8.0" regenerate "^1.4.2" regenerate-unicode-properties "^10.1.0" - regjsgen "^0.7.1" regjsparser "^0.9.1" unicode-match-property-ecmascript "^2.0.0" unicode-match-property-value-ecmascript "^2.1.0" @@ -6757,11 +6707,6 @@ registry-url@^5.0.0: dependencies: rc "^1.2.8" -regjsgen@^0.7.1: - version "0.7.1" - resolved "https://registry.yarnpkg.com/regjsgen/-/regjsgen-0.7.1.tgz#ee5ef30e18d3f09b7c369b76e7c2373ed25546f6" - integrity sha512-RAt+8H2ZEzHeYWxZ3H2z6tF18zyyOnlcdaafLrm21Bguj7uZy6ULibiAFdXEtKQY4Sy7wDTwDiOazasMLc4KPA== - regjsparser@^0.9.1: version "0.9.1" resolved "https://registry.yarnpkg.com/regjsparser/-/regjsparser-0.9.1.tgz#272d05aa10c7c1f67095b1ff0addae8442fc5709" @@ -6781,17 +6726,16 @@ rehype-katex@5: unified "^9.0.0" unist-util-visit "^2.0.0" -rehype-mathjax@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/rehype-mathjax/-/rehype-mathjax-4.0.2.tgz#5d5bfc0380e81c67b8700cd4c61068f8bddc448f" - integrity sha512-9q4Q4icTIbM5RtvQ4XquvEApGV2oDMaSVa5G3DwXomWU4fAPWYcOOt+iQRNaIH3RBMbFF239QbE5K7hm7rxMPQ== +rehype-mathjax@^4.0.3: + version "4.0.3" + resolved "https://registry.yarnpkg.com/rehype-mathjax/-/rehype-mathjax-4.0.3.tgz#e8de43b54b2bafc4dca33d1f7f65e77191b59ec3" + integrity sha512-QIwWH9U+r54nMQklVkT1qluxhKyzdPWz9dFwgel3BrseQsWZafRTDTUj8VR8/14nFuRIV2ChuCMz4zpACPoYvg== dependencies: "@types/hast" "^2.0.0" "@types/mathjax" "^0.0.37" - "@types/web" "^0.0.46" hast-util-from-dom "^4.0.0" hast-util-to-text "^3.1.0" - jsdom "^18.0.0" + jsdom "^20.0.0" mathjax-full "^3.0.0" unified "^10.0.0" unist-util-visit "^4.0.0" @@ -6913,11 +6857,11 @@ resolve-pathname@^3.0.0: integrity sha512-C7rARubxI8bXFNB/hqcp/4iUeIXJhJZvFPFPiSPRnhU5UPxzMFIl+2E6yY6c4k9giDJAhtV+enfA+G89N6Csng== resolve@^1.1.6, resolve@^1.14.2, resolve@^1.3.2: - version "1.22.1" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.1.tgz#27cb2ebb53f91abb49470a928bba7558066ac177" - integrity sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw== + version "1.22.8" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.8.tgz#b6c87a9f2aa06dfab52e3d70ac8cde321fa5a48d" + integrity sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw== dependencies: - is-core-module "^2.9.0" + is-core-module "^2.13.0" path-parse "^1.0.7" supports-preserve-symlinks-flag "^1.0.0" @@ -6946,9 +6890,9 @@ rimraf@^3.0.2: glob "^7.1.3" rtl-detect@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/rtl-detect/-/rtl-detect-1.0.4.tgz#40ae0ea7302a150b96bc75af7d749607392ecac6" - integrity sha512-EBR4I2VDSSYr7PkBmFy04uhycIpDKp+21p/jARYXlCSjQksTBQcJ0HFUPOO79EPPH5JS6VAhiIQbycf0O3JAxQ== + version "1.1.2" + resolved "https://registry.yarnpkg.com/rtl-detect/-/rtl-detect-1.1.2.tgz#ca7f0330af5c6bb626c15675c642ba85ad6273c6" + integrity sha512-PGMBq03+TTG/p/cRB7HCLKJ1MgDIi07+QU1faSjiYRfmY5UsAttV9Hs08jDAHVwcOwmVLcSJkpwyfXszVjWfIQ== rtlcss@^3.5.0: version "3.5.0" @@ -6968,9 +6912,9 @@ run-parallel@^1.1.9: queue-microtask "^1.2.2" rxjs@^7.5.4: - version "7.5.7" - resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-7.5.7.tgz#2ec0d57fdc89ece220d2e702730ae8f1e49def39" - integrity sha512-z9MzKh/UcOqB3i20H6rtrlaE/CgjLOvheWK/9ILrbhROGTweAi1BaFsTT9FbwZi5Trr1qNRs+MXkhmR06awzQA== + version "7.8.1" + resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-7.8.1.tgz#6f6f3d99ea8044291efd92e7c7fcf562c4057543" + integrity sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg== dependencies: tslib "^2.1.0" @@ -6990,14 +6934,14 @@ safe-buffer@5.2.1, safe-buffer@>=5.1.0, safe-buffer@^5.1.0, safe-buffer@~5.2.0: integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== sax@^1.2.4: - version "1.2.4" - resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9" - integrity sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw== + version "1.4.1" + resolved "https://registry.yarnpkg.com/sax/-/sax-1.4.1.tgz#44cc8988377f126304d3b3fc1010c733b929ef0f" + integrity sha512-+aWOz7yVScEGoKNd4PA10LZ8sk0A/z5+nXQG5giUO5rprX9jgYsTdov9qCchZiPIZezbZH+jRut8nPodFAX4Jg== -saxes@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/saxes/-/saxes-5.0.1.tgz#eebab953fa3b7608dbe94e5dadb15c888fa6696d" - integrity sha512-5LBh1Tls8c9xgGjw3QrMwETmTMVk0oFgvrFSvWx62llR2hcEInrKNZ2GZCCuuy2lvWrdl5jhbpeqc5hRYKFOcw== +saxes@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/saxes/-/saxes-6.0.0.tgz#fe5b4a4768df4f14a201b1ba6a65c1f3d9988cc5" + integrity sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA== dependencies: xmlchars "^2.2.0" @@ -7027,24 +6971,24 @@ schema-utils@^2.6.5: ajv "^6.12.4" ajv-keywords "^3.5.2" -schema-utils@^3.0.0, schema-utils@^3.1.0, schema-utils@^3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-3.1.1.tgz#bc74c4b6b6995c1d88f76a8b77bea7219e0c8281" - integrity sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw== +schema-utils@^3.0.0, schema-utils@^3.1.1, schema-utils@^3.2.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-3.3.0.tgz#f50a88877c3c01652a15b622ae9e9795df7a60fe" + integrity sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg== dependencies: "@types/json-schema" "^7.0.8" ajv "^6.12.5" ajv-keywords "^3.5.2" schema-utils@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-4.0.0.tgz#60331e9e3ae78ec5d16353c467c34b3a0a1d3df7" - integrity sha512-1edyXKgh6XnJsJSQ8mKWXnN/BVaIbFMLpouRUrXgVq7WYne5kw3MW7UPhO44uRXQSIpTSXoJbmrR2X0w9kUTyg== + version "4.2.0" + resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-4.2.0.tgz#70d7c93e153a273a805801882ebd3bff20d89c8b" + integrity sha512-L0jRsrPpjdckP3oPug3/VxNKt2trR8TcabrM6FOAAlvC/9Phcmm+cuAgTlxBqdBR1WJx7Naj9WHw+aOmheSVbw== dependencies: "@types/json-schema" "^7.0.9" - ajv "^8.8.0" + ajv "^8.9.0" ajv-formats "^2.1.1" - ajv-keywords "^5.0.0" + ajv-keywords "^5.1.0" section-matter@^1.0.0: version "1.0.0" @@ -7060,10 +7004,11 @@ select-hose@^2.0.0: integrity sha512-mEugaLK+YfkijB4fx0e6kImuJdCIt2LxCRcbEYPqRGCs4F2ogyfZU5IAZRdjCP8JPq2AtdNoC/Dux63d9Kiryg== selfsigned@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/selfsigned/-/selfsigned-2.1.1.tgz#18a7613d714c0cd3385c48af0075abf3f266af61" - integrity sha512-GSL3aowiF7wa/WtSFwnUrludWFoNhftq8bUkH9pkzjpN2XSPOAYEgg6e0sS9s0rZwgJzJiQRPU18A6clnoW5wQ== + version "2.4.1" + resolved "https://registry.yarnpkg.com/selfsigned/-/selfsigned-2.4.1.tgz#560d90565442a3ed35b674034cec4e95dceb4ae0" + integrity sha512-th5B4L2U+eGLq1TVh7zNRGBapioSORUeymIydxgFpwww9d2qyKvtuPU2jJuHvYAwwqi2Y596QBL3eEqcPEYL8Q== dependencies: + "@types/node-forge" "^1.3.0" node-forge "^1" semver-diff@^3.1.1: @@ -7074,21 +7019,19 @@ semver-diff@^3.1.1: semver "^6.3.0" semver@^5.4.1: - version "5.7.1" - resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" - integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== + version "5.7.2" + resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.2.tgz#48d55db737c3287cd4835e17fa13feace1c41ef8" + integrity sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g== -semver@^6.0.0, semver@^6.1.1, semver@^6.1.2, semver@^6.2.0, semver@^6.3.0: - version "6.3.0" - resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" - integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== +semver@^6.0.0, semver@^6.2.0, semver@^6.3.0, semver@^6.3.1: + version "6.3.1" + resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4" + integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== -semver@^7.3.2, semver@^7.3.4, semver@^7.3.7, semver@^7.3.8: - version "7.3.8" - resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.8.tgz#07a78feafb3f7b32347d725e33de7e2a2df67798" - integrity sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A== - dependencies: - lru-cache "^6.0.0" +semver@^7.3.2, semver@^7.3.4, semver@^7.3.7, semver@^7.5.4: + version "7.6.3" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.6.3.tgz#980f7b5550bc175fb4dc09403085627f9eb33143" + integrity sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A== send@0.18.0: version "0.18.0" @@ -7109,10 +7052,10 @@ send@0.18.0: range-parser "~1.2.1" statuses "2.0.1" -serialize-javascript@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-6.0.0.tgz#efae5d88f45d7924141da8b5c3a7a7e663fefeb8" - integrity sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag== +serialize-javascript@^6.0.0, serialize-javascript@^6.0.1: + version "6.0.2" + resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-6.0.2.tgz#defa1e055c83bf6d59ea805d8da862254eb6a6c2" + integrity sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g== dependencies: randombytes "^2.1.0" @@ -7153,6 +7096,18 @@ serve-static@1.15.0: parseurl "~1.3.3" send "0.18.0" +set-function-length@^1.2.1: + version "1.2.2" + resolved "https://registry.yarnpkg.com/set-function-length/-/set-function-length-1.2.2.tgz#aac72314198eaed975cf77b2c3b6b880695e5449" + integrity sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg== + dependencies: + define-data-property "^1.1.4" + es-errors "^1.3.0" + function-bind "^1.1.2" + get-intrinsic "^1.2.4" + gopd "^1.0.1" + has-property-descriptors "^1.0.2" + setimmediate@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285" @@ -7192,10 +7147,10 @@ shebang-regex@^3.0.0: resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== -shell-quote@^1.7.3: - version "1.7.4" - resolved "https://registry.yarnpkg.com/shell-quote/-/shell-quote-1.7.4.tgz#33fe15dee71ab2a81fcbd3a52106c5cfb9fb75d8" - integrity sha512-8o/QEhSSRb1a5i7TFR0iM4G16Z0vYB2OQVs4G3aAFXjn3T6yEx8AZxy1PgDF7I00LZHYA3WxaSYIf5e5sAX8Rw== +shell-quote@^1.7.3, shell-quote@^1.8.1: + version "1.8.1" + resolved "https://registry.yarnpkg.com/shell-quote/-/shell-quote-1.8.1.tgz#6dbf4db75515ad5bac63b4f1894c3a154c766680" + integrity sha512-6j1W9l1iAs/4xYBI1SYOVZyFcCis9b4KCLQ8fgAGG07QvzaRLVVRQvAy85yNmmZSjYjg4MWh4gNvlPujU/5LpA== shelljs@^0.8.5: version "0.8.5" @@ -7207,27 +7162,28 @@ shelljs@^0.8.5: rechoir "^0.6.2" side-channel@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.4.tgz#efce5c8fdc104ee751b25c58d4290011fa5ea2cf" - integrity sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw== + version "1.0.6" + resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.6.tgz#abd25fb7cd24baf45466406b1096b7831c9215f2" + integrity sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA== dependencies: - call-bind "^1.0.0" - get-intrinsic "^1.0.2" - object-inspect "^1.9.0" + call-bind "^1.0.7" + es-errors "^1.3.0" + get-intrinsic "^1.2.4" + object-inspect "^1.13.1" signal-exit@^3.0.2, signal-exit@^3.0.3: version "3.0.7" resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9" integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== -sirv@^1.0.7: - version "1.0.19" - resolved "https://registry.yarnpkg.com/sirv/-/sirv-1.0.19.tgz#1d73979b38c7fe91fcba49c85280daa9c2363b49" - integrity sha512-JuLThK3TnZG1TAKDwNIqNq6QA2afLOCcm+iE8D1Kj3GA40pSPsxQjjJl0J8X3tsR7T+CP1GavpzLwYkgVLWrZQ== +sirv@^2.0.3: + version "2.0.4" + resolved "https://registry.yarnpkg.com/sirv/-/sirv-2.0.4.tgz#5dd9a725c578e34e449f332703eb2a74e46a29b0" + integrity sha512-94Bdh3cC2PKrbgSOUqTiGPWVZeSiXfKOVZNJniWoqrWrRkB1CJzBU3NEbiTsPcYy1lDsANA/THzS+9WBiy5nfQ== dependencies: - "@polka/url" "^1.0.0-next.20" - mrmime "^1.0.0" - totalist "^1.0.0" + "@polka/url" "^1.0.0-next.24" + mrmime "^2.0.0" + totalist "^3.0.0" sisteransi@^1.0.5: version "1.0.5" @@ -7235,9 +7191,9 @@ sisteransi@^1.0.5: integrity sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg== sitemap@^7.1.1: - version "7.1.1" - resolved "https://registry.yarnpkg.com/sitemap/-/sitemap-7.1.1.tgz#eeed9ad6d95499161a3eadc60f8c6dce4bea2bef" - integrity sha512-mK3aFtjz4VdJN0igpIJrinf3EO8U8mxOPsTBzSsy06UtjZQJ3YY3o3Xa7zSc5nMqcMrRwlChHZ18Kxg0caiPBg== + version "7.1.2" + resolved "https://registry.yarnpkg.com/sitemap/-/sitemap-7.1.2.tgz#6ce1deb43f6f177c68bc59cf93632f54e3ae6b72" + integrity sha512-ARCqzHJ0p4gWt+j7NlU5eDlIO9+Rkr/JhPFZKKQ1l5GCus7rJH4UdrlVAh0xC/gDS/Qir2UMxqYNHtsKr2rpCw== dependencies: "@types/node" "^17.0.5" "@types/sax" "^1.2.1" @@ -7268,10 +7224,10 @@ sort-css-media-queries@2.1.0: resolved "https://registry.yarnpkg.com/sort-css-media-queries/-/sort-css-media-queries-2.1.0.tgz#7c85e06f79826baabb232f5560e9745d7a78c4ce" integrity sha512-IeWvo8NkNiY2vVYdPa27MCQiR0MN0M80johAYFVxWWXQ44KU84WNxjslwBHmc/7ZL2ccwkM7/e6S5aiKZXm7jA== -source-map-js@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.0.2.tgz#adbc361d9c62df380125e7f161f71c826f1e490c" - integrity sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw== +source-map-js@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.2.0.tgz#16b809c162517b5b8c3e7dcd315a2a5c2612b2af" + integrity sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg== source-map-support@~0.5.20: version "0.5.21" @@ -7359,9 +7315,9 @@ statuses@2.0.1: integrity sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA== std-env@^3.0.1: - version "3.3.1" - resolved "https://registry.yarnpkg.com/std-env/-/std-env-3.3.1.tgz#93a81835815e618c8aa75e7c8a4dc04f7c314e29" - integrity sha512-3H20QlwQsSm2OvAxWIYhs+j01MzzqwMwGiiO1NQaJYZgJZFPuAbf95/DiKRBSTYIJ2FeGUc+B/6mPGcWP9dO3Q== + version "3.7.0" + resolved "https://registry.yarnpkg.com/std-env/-/std-env-3.7.0.tgz#c9f7386ced6ecf13360b6c6c55b8aaa4ef7481d2" + integrity sha512-JPbdCEQLj1w5GilpiHAx3qJvFndqybBysA3qUOnznweH4QbNYUsW/ea8QzSrnh0vNsezMMw5bcVool8lM0gwzg== string-width@^4.0.0, string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.2: version "4.2.3" @@ -7412,9 +7368,9 @@ strip-ansi@^6.0.0, strip-ansi@^6.0.1: ansi-regex "^5.0.1" strip-ansi@^7.0.1: - version "7.0.1" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-7.0.1.tgz#61740a08ce36b61e50e65653f07060d000975fb2" - integrity sha512-cXNxvT8dFNRVfhVME3JAe98mkXDYN2O1l7jmcwMnOslDeESg1rF/OZMtK0nRAhiari1unG5cD4jG3rapUAkLbw== + version "7.1.0" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-7.1.0.tgz#d5b6568ca689d8561370b0707685d22434faff45" + integrity sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ== dependencies: ansi-regex "^6.0.1" @@ -7507,29 +7463,29 @@ tapable@^1.0.0: resolved "https://registry.yarnpkg.com/tapable/-/tapable-1.1.3.tgz#a1fccc06b58db61fd7a45da2da44f5f3a3e67ba2" integrity sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA== -tapable@^2.0.0, tapable@^2.1.1, tapable@^2.2.0: +tapable@^2.0.0, tapable@^2.1.1, tapable@^2.2.0, tapable@^2.2.1: version "2.2.1" resolved "https://registry.yarnpkg.com/tapable/-/tapable-2.2.1.tgz#1967a73ef4060a82f12ab96af86d52fdb76eeca0" integrity sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ== -terser-webpack-plugin@^5.1.3, terser-webpack-plugin@^5.3.3: - version "5.3.6" - resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-5.3.6.tgz#5590aec31aa3c6f771ce1b1acca60639eab3195c" - integrity sha512-kfLFk+PoLUQIbLmB1+PZDMRSZS99Mp+/MHqDNmMA6tOItzRt+Npe3E+fsMs5mfcM0wCtrrdU387UnV+vnSffXQ== +terser-webpack-plugin@^5.3.10, terser-webpack-plugin@^5.3.3: + version "5.3.10" + resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-5.3.10.tgz#904f4c9193c6fd2a03f693a2150c62a92f40d199" + integrity sha512-BKFPWlPDndPs+NGGCr1U59t0XScL5317Y0UReNrHaw9/FwhPENlq6bfgs+4yPfyP51vqC1bQ4rp1EfXW5ZSH9w== dependencies: - "@jridgewell/trace-mapping" "^0.3.14" + "@jridgewell/trace-mapping" "^0.3.20" jest-worker "^27.4.5" schema-utils "^3.1.1" - serialize-javascript "^6.0.0" - terser "^5.14.1" + serialize-javascript "^6.0.1" + terser "^5.26.0" -terser@^5.10.0, terser@^5.14.1: - version "5.15.1" - resolved "https://registry.yarnpkg.com/terser/-/terser-5.15.1.tgz#8561af6e0fd6d839669c73b92bdd5777d870ed6c" - integrity sha512-K1faMUvpm/FBxjBXud0LWVAGxmvoPbZbfTCYbSgaaYQaIXI3/TdI7a7ZGA73Zrou6Q8Zmz3oeUTsp/dj+ag2Xw== +terser@^5.10.0, terser@^5.26.0: + version "5.31.3" + resolved "https://registry.yarnpkg.com/terser/-/terser-5.31.3.tgz#b24b7beb46062f4653f049eea4f0cd165d0f0c38" + integrity sha512-pAfYn3NIZLyZpa83ZKigvj6Rn9c/vd5KfYGX7cN1mnzqgDcxWvrU5ZtAfIKhEXz9nRecw4z3LXkjaq96/qZqAA== dependencies: - "@jridgewell/source-map" "^0.3.2" - acorn "^8.5.0" + "@jridgewell/source-map" "^0.3.3" + acorn "^8.8.2" commander "^2.20.0" source-map-support "~0.5.20" @@ -7544,9 +7500,9 @@ thunky@^1.0.2: integrity sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA== tiny-invariant@^1.0.2: - version "1.3.1" - resolved "https://registry.yarnpkg.com/tiny-invariant/-/tiny-invariant-1.3.1.tgz#8560808c916ef02ecfd55e66090df23a4b7aa642" - integrity sha512-AD5ih2NlSssTCwsMznbvwMZpJ1cbhkGd2uueNxzv2jDlEeZdU04JQfRnggJQ8DrcVBGjAsCKwFBbDlVNtEMlzw== + version "1.3.3" + resolved "https://registry.yarnpkg.com/tiny-invariant/-/tiny-invariant-1.3.3.tgz#46680b7a873a0d5d10005995eb90a70d74d60127" + integrity sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg== tiny-warning@^1.0.0: version "1.0.3" @@ -7575,15 +7531,15 @@ toidentifier@1.0.1: resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.1.tgz#3be34321a88a820ed1bd80dfaa33e479fbb8dd35" integrity sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA== -totalist@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/totalist/-/totalist-1.1.0.tgz#a4d65a3e546517701e3e5c37a47a70ac97fe56df" - integrity sha512-gduQwd1rOdDMGxFG1gEvhV88Oirdo2p+KjoYFU7k2g+i7n6AFFbDQ5kMPUsW0pNbfQsB/cwXvT1i4Bue0s9g5g== +totalist@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/totalist/-/totalist-3.0.1.tgz#ba3a3d600c915b1a97872348f79c127475f6acf8" + integrity sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ== -tough-cookie@^4.0.0: - version "4.1.2" - resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-4.1.2.tgz#e53e84b85f24e0b65dd526f46628db6c85f6b874" - integrity sha512-G9fqXWoYFZgTc2z8Q5zaHy/vJMjm+WV0AkAeHxVCQiEB1b+dGvWzFW6QV07cY5jQ5gRkeid2qIkzkxUnmoQZUQ== +tough-cookie@^4.1.2: + version "4.1.4" + resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-4.1.4.tgz#945f1461b45b5a8c76821c33ea49c3ac192c1b36" + integrity sha512-Loo5UUvLD9ScZ6jh8beX1T6sO1w2/MpCRpEP7V280GKMVUQ0Jzar2U3UJPsrdbziLEMMhu3Ujnq//rhiFuIeag== dependencies: psl "^1.1.33" punycode "^2.1.1" @@ -7618,21 +7574,14 @@ trough@^1.0.0: integrity sha512-rvuRbTarPXmMb79SmzEp8aqXNKcK+y0XaB298IXueQ8I2PsrATcPBCSPyK/dDNa2iWOhKlfNnOjdAOTBU/nkFA== trough@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/trough/-/trough-2.1.0.tgz#0f7b511a4fde65a46f18477ab38849b22c554876" - integrity sha512-AqTiAOLcj85xS7vQ8QkAV41hPDIJ71XJB4RCUrzo/1GM2CQwhkJGaf9Hgr7BOugMRpgGUrqRg/DrBDl4H40+8g== + version "2.2.0" + resolved "https://registry.yarnpkg.com/trough/-/trough-2.2.0.tgz#94a60bd6bd375c152c1df911a4b11d5b0256f50f" + integrity sha512-tmMpK00BjZiUyVyvrBK7knerNgmgvcV/KLVyuma/SC+TQN167GrMRciANTz09+k3zW8L8t60jWO1GpfkZdjTaw== tslib@^2.0.3, tslib@^2.1.0, tslib@^2.4.0: - version "2.4.1" - resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.4.1.tgz#0d0bfbaac2880b91e22df0768e55be9753a5b17e" - integrity sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA== - -type-check@~0.3.2: - version "0.3.2" - resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.3.2.tgz#5884cab512cf1d355e3fb784f30804b2b520db72" - integrity sha512-ZCmOJdvOWDBYJlzAoFkC+Q0+bUyEOS1ltgp1MGU03fqHG+dbi9tBFU2Rd9QKiDZFAYrhPh2JUf7rZRIuHRKtOg== - dependencies: - prelude-ls "~1.1.2" + version "2.6.3" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.6.3.tgz#0438f810ad7a9edcde7a241c3d80db693c8cbfe0" + integrity sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ== type-fest@^0.20.2: version "0.20.2" @@ -7659,10 +7608,15 @@ typedarray-to-buffer@^3.1.5: dependencies: is-typedarray "^1.0.0" -ua-parser-js@^0.7.30: - version "0.7.32" - resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.32.tgz#cd8c639cdca949e30fa68c44b7813ef13e36d211" - integrity sha512-f9BESNVhzlhEFf2CHMSj40NWOjYPl1YKYbrvIr/hFTDEmLq7SRbWvm7FcdcpCYT95zrOhC7gZSxjdnnTpBcwVw== +ua-parser-js@^1.0.35: + version "1.0.38" + resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-1.0.38.tgz#66bb0c4c0e322fe48edfe6d446df6042e62f25e2" + integrity sha512-Aq5ppTOfvrCMgAPneW1HfWj66Xi7XL+/mIy996R1/CLS/rcyJQm6QZdsKrUeivDFQ+Oc9Wyuwor8Ze8peEoUoQ== + +undici-types@~5.26.4: + version "5.26.5" + resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-5.26.5.tgz#bcd539893d00b56e964fd2657a4866b221a65617" + integrity sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA== unherit@^1.0.4: version "1.1.3" @@ -7752,9 +7706,9 @@ unist-util-find-after@^3.0.0: unist-util-is "^4.0.0" unist-util-find-after@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/unist-util-find-after/-/unist-util-find-after-4.0.0.tgz#1101cebf5fed88ae3c6f3fa676e86fd5772a4f32" - integrity sha512-gfpsxKQde7atVF30n5Gff2fQhAc4/HTOV4CvkXpTg9wRfQhZWdXitpyXHWB6YcYgnsxLx+4gGHeVjCTAAp9sjw== + version "4.0.1" + resolved "https://registry.yarnpkg.com/unist-util-find-after/-/unist-util-find-after-4.0.1.tgz#80c69c92b0504033638ce11973f4135f2c822e2d" + integrity sha512-QO/PuPMm2ERxC6vFXEPtmAutOopy5PknD+Oq64gGwxKtk4xwo9Z97t9Av1obPmGU0IyTa6EKYUfTrK2QJS3Ozw== dependencies: "@types/unist" "^2.0.0" unist-util-is "^5.0.0" @@ -7770,9 +7724,11 @@ unist-util-is@^4.0.0: integrity sha512-ZOQSsnce92GrxSqlnEEseX0gi7GH9zTJZ0p9dtu87WRb/37mMPO2Ilx1s/t9vBHrFhbgweUwb+t7cIn5dxPhZg== unist-util-is@^5.0.0: - version "5.1.1" - resolved "https://registry.yarnpkg.com/unist-util-is/-/unist-util-is-5.1.1.tgz#e8aece0b102fa9bc097b0fef8f870c496d4a6236" - integrity sha512-F5CZ68eYzuSvJjGhCLPL3cYx45IxkqXSetCcRgUXtbcm50X2L9oOWQlfUfDdAf+6Pd27YDblBfdtmsThXmwpbQ== + version "5.2.1" + resolved "https://registry.yarnpkg.com/unist-util-is/-/unist-util-is-5.2.1.tgz#b74960e145c18dcb6226bc57933597f5486deae9" + integrity sha512-u9njyyfEh43npf1M+yGKDGVPbY/JWEemg5nH05ncKPfi+kBbKBJoTdsogMu33uhytuLlv9y0O7GH7fEdwLdLQw== + dependencies: + "@types/unist" "^2.0.0" unist-util-position@^3.0.0: version "3.1.0" @@ -7801,9 +7757,9 @@ unist-util-stringify-position@^2.0.0: "@types/unist" "^2.0.2" unist-util-stringify-position@^3.0.0: - version "3.0.2" - resolved "https://registry.yarnpkg.com/unist-util-stringify-position/-/unist-util-stringify-position-3.0.2.tgz#5c6aa07c90b1deffd9153be170dce628a869a447" - integrity sha512-7A6eiDCs9UtjcwZOcCpM4aPII3bAAGv13E96IkawkOAW0OhH+yRxtY0lzo8KiHpzEMfH7Q+FizUmwp8Iqy5EWg== + version "3.0.3" + resolved "https://registry.yarnpkg.com/unist-util-stringify-position/-/unist-util-stringify-position-3.0.3.tgz#03ad3348210c2d930772d64b489580c13a7db39d" + integrity sha512-k5GzIBZ/QatR8N5X2y+drfpWG8IDBzdnVj6OInRNWm1oXrzydiaAT2OQiA8DPRRZyAKb9b6I2a6PxYklZD0gKg== dependencies: "@types/unist" "^2.0.0" @@ -7816,9 +7772,9 @@ unist-util-visit-parents@^3.0.0: unist-util-is "^4.0.0" unist-util-visit-parents@^5.1.1: - version "5.1.1" - resolved "https://registry.yarnpkg.com/unist-util-visit-parents/-/unist-util-visit-parents-5.1.1.tgz#868f353e6fce6bf8fa875b251b0f4fec3be709bb" - integrity sha512-gks4baapT/kNRaWxuGkl5BIhoanZo7sC/cUT/JToSRNL1dYoXRFl75d++NkjYk4TAu2uv2Px+l8guMajogeuiw== + version "5.1.3" + resolved "https://registry.yarnpkg.com/unist-util-visit-parents/-/unist-util-visit-parents-5.1.3.tgz#b4520811b0ca34285633785045df7a8d6776cfeb" + integrity sha512-x6+y8g7wWMyQhL1iZfhIPhDAs7Xwbn9nRosDXl7qoPTSCy0yNxnKc+hWokFifWQIDGi154rdUqKvbCa4+1kLhg== dependencies: "@types/unist" "^2.0.0" unist-util-is "^5.0.0" @@ -7833,9 +7789,9 @@ unist-util-visit@2.0.3, unist-util-visit@^2.0.0, unist-util-visit@^2.0.3: unist-util-visit-parents "^3.0.0" unist-util-visit@^4.0.0: - version "4.1.1" - resolved "https://registry.yarnpkg.com/unist-util-visit/-/unist-util-visit-4.1.1.tgz#1c4842d70bd3df6cc545276f5164f933390a9aad" - integrity sha512-n9KN3WV9k4h1DxYR1LoajgN93wpEi/7ZplVe02IoB4gH5ctI1AaF2670BLHQYbwj+pY83gFtyeySFiyMHJklrg== + version "4.1.2" + resolved "https://registry.yarnpkg.com/unist-util-visit/-/unist-util-visit-4.1.2.tgz#125a42d1eb876283715a3cb5cceaa531828c72e2" + integrity sha512-MSd8OUGISqHdVvfY9TPhyK2VdUrPgxkUtWSuMHF6XAAFuL4LokseigBnZtPnJMu+FbynTkFNnFlyjxpVKujMRg== dependencies: "@types/unist" "^2.0.0" unist-util-is "^5.0.0" @@ -7847,22 +7803,22 @@ universalify@^0.2.0: integrity sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg== universalify@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/universalify/-/universalify-2.0.0.tgz#75a4984efedc4b08975c5aeb73f530d02df25717" - integrity sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ== + version "2.0.1" + resolved "https://registry.yarnpkg.com/universalify/-/universalify-2.0.1.tgz#168efc2180964e6386d061e094df61afe239b18d" + integrity sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw== unpipe@1.0.0, unpipe@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" integrity sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ== -update-browserslist-db@^1.0.9: - version "1.0.10" - resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.0.10.tgz#0f54b876545726f17d00cd9a2561e6dade943ff3" - integrity sha512-OztqDenkfFkbSG+tRxBeAnCVPckDBcvibKd35yDONx6OU8N7sqgwc7rCbkJ/WcYtVRZ4ba68d6byhC21GFh7sQ== +update-browserslist-db@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.1.0.tgz#7ca61c0d8650766090728046e416a8cde682859e" + integrity sha512-EdRAaAyk2cUE1wOf2DkEhzxqOQvFOoRJFNS6NeyJ01Gp2beMRpBAINjM2iDXE3KCuKhwnvHIQCJm6ThL2Z+HzQ== dependencies: - escalade "^3.1.1" - picocolors "^1.0.0" + escalade "^3.1.2" + picocolors "^1.0.1" update-notifier@^5.1.0: version "5.1.0" @@ -7932,6 +7888,11 @@ use-latest@^1.2.1: dependencies: use-isomorphic-layout-effect "^1.1.1" +use-sync-external-store@^1.2.0: + version "1.2.2" + resolved "https://registry.yarnpkg.com/use-sync-external-store/-/use-sync-external-store-1.2.2.tgz#c3b6390f3a30eba13200d2302dcdf1e7b57b2ef9" + integrity sha512-PElTlVMwpblvbNqQ82d2n6RjStvdSoNe9FG28kNfz3WiXilJm4DdNkEzRhCZuIDwY8U08WVihhGR5iRqAwfDiw== + util-deprecate@^1.0.1, util-deprecate@^1.0.2, util-deprecate@~1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" @@ -7943,9 +7904,9 @@ utila@~0.4: integrity sha512-Z0DbgELS9/L/75wZbro8xAnT50pBVFQZ+hUEueGDU5FN51YSCYM+jdxsfCiHjwNP/4LCDD0i/graKpeBnOXKRA== utility-types@^3.10.0: - version "3.10.0" - resolved "https://registry.yarnpkg.com/utility-types/-/utility-types-3.10.0.tgz#ea4148f9a741015f05ed74fd615e1d20e6bed82b" - integrity sha512-O11mqxmi7wMKCo6HKFt5AhO4BwY3VV68YU07tgxfz8zJTIxr4BpsezN49Ffwy9j3ZpwwJp4fkRwjRzq3uWE6Rg== + version "3.11.0" + resolved "https://registry.yarnpkg.com/utility-types/-/utility-types-3.11.0.tgz#607c40edb4f258915e901ea7995607fdf319424c" + integrity sha512-6Z7Ma2aVEWisaL6TvBCy7P8rm2LQoPv6dJ7ecIaIixHcwfbJ0x7mWdbcwlIM5IGQxPZSFYeqRCqlOOeKoJYMkw== utils-merge@1.0.1: version "1.0.1" @@ -7981,9 +7942,9 @@ vfile-message@^2.0.0: unist-util-stringify-position "^2.0.0" vfile-message@^3.0.0: - version "3.1.3" - resolved "https://registry.yarnpkg.com/vfile-message/-/vfile-message-3.1.3.tgz#1360c27a99234bebf7bddbbbca67807115e6b0dd" - integrity sha512-0yaU+rj2gKAyEk12ffdSbBfjnnj+b1zqTBv3OQCTn8yEB02bsPizwdBPrLJjHnK+cU9EMMcUnNv938XcZIkmdA== + version "3.1.4" + resolved "https://registry.yarnpkg.com/vfile-message/-/vfile-message-3.1.4.tgz#15a50816ae7d7c2d1fa87090a7f9f96612b59dea" + integrity sha512-fa0Z6P8HUrQN4BZaX05SIVXic+7kE3b05PWAtPuYP9QLHsLKYR7/AlLW3NtOrpXRLeawpDLMsVkmk5DG0NXgWw== dependencies: "@types/unist" "^2.0.0" unist-util-stringify-position "^3.0.0" @@ -7999,26 +7960,19 @@ vfile@^4.0.0: vfile-message "^2.0.0" vfile@^5.0.0: - version "5.3.6" - resolved "https://registry.yarnpkg.com/vfile/-/vfile-5.3.6.tgz#61b2e70690cc835a5d0d0fd135beae74e5a39546" - integrity sha512-ADBsmerdGBs2WYckrLBEmuETSPyTD4TuLxTrw0DvjirxW1ra4ZwkbzG8ndsv3Q57smvHxo677MHaQrY9yxH8cA== + version "5.3.7" + resolved "https://registry.yarnpkg.com/vfile/-/vfile-5.3.7.tgz#de0677e6683e3380fafc46544cfe603118826ab7" + integrity sha512-r7qlzkgErKjobAmyNIkkSpizsFPYiUPuJb5pNW1RB4JcYVZhs4lIbVqk8XPk033CV/1z8ss5pkax8SuhGpcG8g== dependencies: "@types/unist" "^2.0.0" is-buffer "^2.0.0" unist-util-stringify-position "^3.0.0" vfile-message "^3.0.0" -w3c-hr-time@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/w3c-hr-time/-/w3c-hr-time-1.0.2.tgz#0a89cdf5cc15822df9c360543676963e0cc308cd" - integrity sha512-z8P5DvDNjKDoFIHK7q8r8lackT6l+jo/Ye3HOle7l9nICP9lf1Ci25fy9vHd0JOWewkIFzXIEig3TdKT7JQ5fQ== - dependencies: - browser-process-hrtime "^1.0.0" - -w3c-xmlserializer@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/w3c-xmlserializer/-/w3c-xmlserializer-3.0.0.tgz#06cdc3eefb7e4d0b20a560a5a3aeb0d2d9a65923" - integrity sha512-3WFqGEgSXIyGhOmAFtlicJNMjEps8b1MG31NCA0/vOF9+nKMUW1ckhi9cnNHmf88Rzw5V+dwIwsm2C7X8k9aQg== +w3c-xmlserializer@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/w3c-xmlserializer/-/w3c-xmlserializer-4.0.0.tgz#aebdc84920d806222936e3cdce408e32488a3073" + integrity sha512-d+BFHzbiCx6zGfz0HyQ6Rg69w9k19nviJspaj4yNscGjrHu94sVP+aRm75yEbCh+r2/yR+7q6hux9LVtbuTGBw== dependencies: xml-name-validator "^4.0.0" @@ -8033,10 +7987,10 @@ wait-on@^6.0.1: minimist "^1.2.5" rxjs "^7.5.4" -watchpack@^2.4.0: - version "2.4.0" - resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-2.4.0.tgz#fa33032374962c78113f93c7f2fb4c54c9862a5d" - integrity sha512-Lcvm7MGST/4fup+ifyKi2hjyIAwcdI4HRgtvTpIUxBRhB+RFtUh8XtDOxUfctVCnhVi+QQj49i91OyvzkJl6cg== +watchpack@^2.4.1: + version "2.4.1" + resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-2.4.1.tgz#29308f2cac150fa8e4c92f90e0ec954a9fed7fff" + integrity sha512-8wrBCMtVhqcXP2Sup1ctSkga6uc2Bx0IIvKyT7yTFier5AXHooSI+QyQQAtTb7+E0IUCCKyTFmXqdqgum2XWGg== dependencies: glob-to-regexp "^0.4.1" graceful-fs "^4.1.2" @@ -8069,24 +8023,27 @@ webidl-conversions@^7.0.0: integrity sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g== webpack-bundle-analyzer@^4.5.0: - version "4.7.0" - resolved "https://registry.yarnpkg.com/webpack-bundle-analyzer/-/webpack-bundle-analyzer-4.7.0.tgz#33c1c485a7fcae8627c547b5c3328b46de733c66" - integrity sha512-j9b8ynpJS4K+zfO5GGwsAcQX4ZHpWV+yRiHDiL+bE0XHJ8NiPYLTNVQdlFYWxtpg9lfAQNlwJg16J9AJtFSXRg== + version "4.10.2" + resolved "https://registry.yarnpkg.com/webpack-bundle-analyzer/-/webpack-bundle-analyzer-4.10.2.tgz#633af2862c213730be3dbdf40456db171b60d5bd" + integrity sha512-vJptkMm9pk5si4Bv922ZbKLV8UTT4zib4FPgXMhgzUny0bfDDkLXAVQs3ly3fS4/TN9ROFtb0NFrm04UXFE/Vw== dependencies: + "@discoveryjs/json-ext" "0.5.7" acorn "^8.0.4" acorn-walk "^8.0.0" - chalk "^4.1.0" commander "^7.2.0" + debounce "^1.2.1" + escape-string-regexp "^4.0.0" gzip-size "^6.0.0" - lodash "^4.17.20" + html-escaper "^2.0.2" opener "^1.5.2" - sirv "^1.0.7" + picocolors "^1.0.0" + sirv "^2.0.3" ws "^7.3.1" -webpack-dev-middleware@^5.3.1: - version "5.3.3" - resolved "https://registry.yarnpkg.com/webpack-dev-middleware/-/webpack-dev-middleware-5.3.3.tgz#efae67c2793908e7311f1d9b06f2a08dcc97e51f" - integrity sha512-hj5CYrY0bZLB+eTO+x/j67Pkrquiy7kWepMHmUMoPsmcUaeEnQJqFzHJOyxgWlq746/wUuA64p9ta34Kyb01pA== +webpack-dev-middleware@^5.3.4: + version "5.3.4" + resolved "https://registry.yarnpkg.com/webpack-dev-middleware/-/webpack-dev-middleware-5.3.4.tgz#eb7b39281cbce10e104eb2b8bf2b63fce49a3517" + integrity sha512-BVdTqhhs+0IfoeAf7EoH5WE+exCmqGerHfDM0IL096Px60Tq2Mn9MAbnaGUe6HiMa41KMCYF19gyzZmBcq/o4Q== dependencies: colorette "^2.0.10" memfs "^3.4.3" @@ -8095,9 +8052,9 @@ webpack-dev-middleware@^5.3.1: schema-utils "^4.0.0" webpack-dev-server@^4.9.3: - version "4.11.1" - resolved "https://registry.yarnpkg.com/webpack-dev-server/-/webpack-dev-server-4.11.1.tgz#ae07f0d71ca0438cf88446f09029b92ce81380b5" - integrity sha512-lILVz9tAUy1zGFwieuaQtYiadImb5M3d+H+L1zDYalYoDl0cksAB1UNyuE5MMWJrG6zR1tXkCP2fitl7yoUJiw== + version "4.15.2" + resolved "https://registry.yarnpkg.com/webpack-dev-server/-/webpack-dev-server-4.15.2.tgz#9e0c70a42a012560860adb186986da1248333173" + integrity sha512-0XavAZbNJ5sDrCbkpWL8mia0o5WPOd2YGtxrEiZkBK9FjLppIUK2TgxK6qGD2P3hUXTJNNPVibrerKcx5WkR1g== dependencies: "@types/bonjour" "^3.5.9" "@types/connect-history-api-fallback" "^1.3.5" @@ -8105,7 +8062,7 @@ webpack-dev-server@^4.9.3: "@types/serve-index" "^1.9.1" "@types/serve-static" "^1.13.10" "@types/sockjs" "^0.3.33" - "@types/ws" "^8.5.1" + "@types/ws" "^8.5.5" ansi-html-community "^0.0.8" bonjour-service "^1.0.11" chokidar "^3.5.3" @@ -8118,6 +8075,7 @@ webpack-dev-server@^4.9.3: html-entities "^2.3.2" http-proxy-middleware "^2.0.3" ipaddr.js "^2.0.1" + launch-editor "^2.6.0" open "^8.0.9" p-retry "^4.5.0" rimraf "^3.0.2" @@ -8126,15 +8084,16 @@ webpack-dev-server@^4.9.3: serve-index "^1.9.1" sockjs "^0.3.24" spdy "^4.0.2" - webpack-dev-middleware "^5.3.1" - ws "^8.4.2" + webpack-dev-middleware "^5.3.4" + ws "^8.13.0" webpack-merge@^5.8.0: - version "5.8.0" - resolved "https://registry.yarnpkg.com/webpack-merge/-/webpack-merge-5.8.0.tgz#2b39dbf22af87776ad744c390223731d30a68f61" - integrity sha512-/SaI7xY0831XwP6kzuwhKWVKDP9t1QY1h65lAFLbZqMPIuYcD9QAW4u9STIbU9kaJbPBB/geU/gLr1wDjOhQ+Q== + version "5.10.0" + resolved "https://registry.yarnpkg.com/webpack-merge/-/webpack-merge-5.10.0.tgz#a3ad5d773241e9c682803abf628d4cd62b8a4177" + integrity sha512-+4zXKdx7UnO+1jaN4l2lHVD+mFvnlZQP/6ljaJVb4SZiwIKeUnrT5l0gkT8z+n4hKpC+jpOv6O9R+gLtag7pSA== dependencies: clone-deep "^4.0.1" + flat "^5.0.2" wildcard "^2.0.0" webpack-sources@^3.2.2, webpack-sources@^3.2.3: @@ -8143,33 +8102,33 @@ webpack-sources@^3.2.2, webpack-sources@^3.2.3: integrity sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w== webpack@^5.73.0: - version "5.75.0" - resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.75.0.tgz#1e440468647b2505860e94c9ff3e44d5b582c152" - integrity sha512-piaIaoVJlqMsPtX/+3KTTO6jfvrSYgauFVdt8cr9LTHKmcq/AMd4mhzsiP7ZF/PGRNPGA8336jldh9l2Kt2ogQ== + version "5.93.0" + resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.93.0.tgz#2e89ec7035579bdfba9760d26c63ac5c3462a5e5" + integrity sha512-Y0m5oEY1LRuwly578VqluorkXbvXKh7U3rLoQCEO04M97ScRr44afGVkI0FQFsXzysk5OgFAxjZAb9rsGQVihA== dependencies: "@types/eslint-scope" "^3.7.3" - "@types/estree" "^0.0.51" - "@webassemblyjs/ast" "1.11.1" - "@webassemblyjs/wasm-edit" "1.11.1" - "@webassemblyjs/wasm-parser" "1.11.1" + "@types/estree" "^1.0.5" + "@webassemblyjs/ast" "^1.12.1" + "@webassemblyjs/wasm-edit" "^1.12.1" + "@webassemblyjs/wasm-parser" "^1.12.1" acorn "^8.7.1" - acorn-import-assertions "^1.7.6" - browserslist "^4.14.5" + acorn-import-attributes "^1.9.5" + browserslist "^4.21.10" chrome-trace-event "^1.0.2" - enhanced-resolve "^5.10.0" - es-module-lexer "^0.9.0" + enhanced-resolve "^5.17.0" + es-module-lexer "^1.2.1" eslint-scope "5.1.1" events "^3.2.0" glob-to-regexp "^0.4.1" - graceful-fs "^4.2.9" + graceful-fs "^4.2.11" json-parse-even-better-errors "^2.3.1" loader-runner "^4.2.0" mime-types "^2.1.27" neo-async "^2.6.2" - schema-utils "^3.1.0" + schema-utils "^3.2.0" tapable "^2.1.1" - terser-webpack-plugin "^5.1.3" - watchpack "^2.4.0" + terser-webpack-plugin "^5.3.10" + watchpack "^2.4.1" webpack-sources "^3.2.3" webpackbar@^5.0.2: @@ -8208,14 +8167,6 @@ whatwg-mimetype@^3.0.0: resolved "https://registry.yarnpkg.com/whatwg-mimetype/-/whatwg-mimetype-3.0.0.tgz#5fa1a7623867ff1af6ca3dc72ad6b8a4208beba7" integrity sha512-nt+N2dzIutVRxARx1nghPKGv1xHikU7HKdfafKkLNLindmPU/ch3U31NOCGGA/dmPcmb1VlofO0vnKAcsm0o/Q== -whatwg-url@^10.0.0: - version "10.0.0" - resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-10.0.0.tgz#37264f720b575b4a311bd4094ed8c760caaa05da" - integrity sha512-CLxxCmdUby142H5FZzn4D8ikO1cmypvXVQktsgosNy4a4BHrDHeciBBGZhb0bNoR5/MltoCatso+vFjjGx8t0w== - dependencies: - tr46 "^3.0.0" - webidl-conversions "^7.0.0" - whatwg-url@^11.0.0: version "11.0.0" resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-11.0.0.tgz#0a849eebb5faf2119b901bb76fd795c2848d4018" @@ -8266,14 +8217,9 @@ widest-line@^4.0.1: string-width "^5.0.1" wildcard@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/wildcard/-/wildcard-2.0.0.tgz#a77d20e5200c6faaac979e4b3aadc7b3dd7f8fec" - integrity sha512-JcKqAHLPxcdb9KM49dufGXn2x3ssnfjbcaQdLlfZsL9rH9wgDQjUtDxbo8NE0F6SFvydeu1VhZe7hZuHsB2/pw== - -word-wrap@~1.2.3: - version "1.2.3" - resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.3.tgz#610636f6b1f703891bd34771ccb17fb93b47079c" - integrity sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ== + version "2.0.1" + resolved "https://registry.yarnpkg.com/wildcard/-/wildcard-2.0.1.tgz#5ab10d02487198954836b6349f74fff961e10f67" + integrity sha512-CC1bOL87PIWSBhDcTrdeLo6eGT7mCFtrg0uIJtqJUFyK+eJnzl8A1niH56uu7KMa5XFrtiV+AQuHO3n7DsHnLQ== wrap-ansi@^7.0.0: version "7.0.0" @@ -8285,9 +8231,9 @@ wrap-ansi@^7.0.0: strip-ansi "^6.0.0" wrap-ansi@^8.0.1: - version "8.0.1" - resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-8.0.1.tgz#2101e861777fec527d0ea90c57c6b03aac56a5b3" - integrity sha512-QFF+ufAqhoYHvoHdajT/Po7KoXVBPXS2bgjIam5isfWJPfIOnQZ50JtUiVvCv/sjgacf3yRrt2ZKUZ/V4itN4g== + version "8.1.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz#56dc22368ee570face1b49819975d9b9a5ead214" + integrity sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ== dependencies: ansi-styles "^6.1.0" string-width "^5.0.1" @@ -8309,14 +8255,14 @@ write-file-atomic@^3.0.0: typedarray-to-buffer "^3.1.5" ws@^7.3.1: - version "7.5.9" - resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.9.tgz#54fa7db29f4c7cec68b1ddd3a89de099942bb591" - integrity sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q== + version "7.5.10" + resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.10.tgz#58b5c20dc281633f6c19113f39b349bd8bd558d9" + integrity sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ== -ws@^8.2.3, ws@^8.4.2: - version "8.11.0" - resolved "https://registry.yarnpkg.com/ws/-/ws-8.11.0.tgz#6a0d36b8edfd9f96d8b25683db2f8d7de6e8e143" - integrity sha512-HPG3wQd9sNQoT9xHyNCXoDUa+Xw/VevmY9FoHyQ+g+rrMn4j6FB4np7Z0OhdTgjx6MgQLK7jwSy1YecU1+4Asg== +ws@^8.11.0, ws@^8.13.0: + version "8.18.0" + resolved "https://registry.yarnpkg.com/ws/-/ws-8.18.0.tgz#0d7505a6eafe2b0e712d232b42279f53bc289bbc" + integrity sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw== xdg-basedir@^4.0.0: version "4.0.0" @@ -8350,10 +8296,10 @@ xtend@^4.0.0, xtend@^4.0.1: resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54" integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ== -yallist@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" - integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== +yallist@^3.0.2: + version "3.1.1" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd" + integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g== yaml@^1.10.0, yaml@^1.10.2, yaml@^1.7.2: version "1.10.2" From 49b56d19f5848d3a555315c8223fb8269a594b72 Mon Sep 17 00:00:00 2001 From: walnut-the-cat <122475853+walnut-the-cat@users.noreply.github.com> Date: Fri, 26 Jul 2024 08:02:29 -0700 Subject: [PATCH 150/150] NEP-509: Stateless validation stage 0 (#509) --- neps/nep-0509.md | 599 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 599 insertions(+) create mode 100644 neps/nep-0509.md diff --git a/neps/nep-0509.md b/neps/nep-0509.md new file mode 100644 index 000000000..4b10254cc --- /dev/null +++ b/neps/nep-0509.md @@ -0,0 +1,599 @@ +--- +NEP: 509 +Title: Stateless validation Stage 0 +Authors: Robin Cheng, Anton Puhach, Alex Logunov, Yoon Hong +Status: Draft +DiscussionsTo: https://docs.google.com/document/d/1C-w4FNeXl8ZMd_Z_YxOf30XA1JM6eMDp5Nf3N-zzNWU/edit?usp=sharing, https://docs.google.com/document/d/1TzMENFGYjwc2g5A3Yf4zilvBwuYJufsUQJwRjXGb9Xc/edit?usp=sharing +Type: Protocol +Version: 1.0.0 +Created: 2023-09-19 +LastUpdated: 2023-09-19 +--- + +## Summary + +The NEP proposes an solution to achieve phase 2 of sharding (where none of the validators needs to track all shards), with stateless validation, instead of the traditionally proposed approach of fraud proof and state rollback. + +The fundamental idea is that validators do not need to have state locally to validate chunks. + +* Under stateless validation, the responsibility of a chunk producer extends to packaging transactions and receipts and annotating them with state witnesses. This extended role will be called "chunk proposers". +* The state witness of a chunk is defined to be a subset of the trie state, alongside its proof of inclusion in the trie, that is needed to execute a chunk. A state witness allows anyone to execute the chunk without having the state of its shard locally. +* Then, at each block height, validators will be randomly assigned to a shard, to validate the state witness for that shard. Once a validator receives both a chunk and its state witness, it verifies the state transition of the chunk, signs a chunk endorsement and sends it to the block producer. This is similar to, but separate from, block approvals and consensus. +* The block producer waits for sufficient chunk endorsements before including a chunk into the block it produces, or omits the chunk if not enough endorsements arrive in time. + +## Motivation + +As phase 1 of sharding requires block producers to track all shards due to underlying security concerns, the team explored potential ways to achieve phase 2 of sharding, where none of the validators has to track all shards. + +The early design of phase 2 relied on the security assumption that as long as there is one honest validator or fisherman tracking a shard, the shard is secure; by doing so, it naturally relied on protocol's ability to handle challenges (when an honest validator or fisherman detects a malicious behavior and submits a proof of such), state rollbacks (when validators agree that the submitted challenge is valid), and slashing (to punish the malicious validator). While it sounds straightforward and simple on paper, the complex interactions between these abilities and the rest of the protocol led to concrete designs that were extremely complicated, involving several specific problems we still don't know how to solve. + +As a result, the team sought alternative approaches and concluded that stateless validation is the most realistic and promising one; the stateless validation approach does not assume the existence of a fishermen, does not rely on challenges, and never rolls back state. Instead, it relies on the assumption that a shard is secure if every single chunk in that shard is validated by a randomly sampled subset of all validators, to always produce valid chunks in the first place. + +## Specification + +### Assumptions + +* Not more than 1/3 of validators (by stake) is corrupted. +* In memory trie is enabled - [REF](https://docs.google.com/document/d/1_X2z6CZbIsL68PiFvyrasjRdvKA_uucyIaDURziiH2U/edit?usp=sharing) +* State sync is enabled (so that nodes can track different shards across epochs) +* Merkle Patricia Trie continues to be the state trie implementation +* Congestion Control is enabled - [NEP-539](https://github.com/near/NEPs/pull/539) + +### Design requirements + +* No validator needs to track all shards. +* Security of protocol must not degrade. + * Validator assignment for both chunk validation and block validation should not create any security vulnerabilities. +* Block processing time should not take significantly more than what it takes today. +* Any additional load on network and compute should not negatively affect existing functionalities of any node in the blockchain. + * The cost of additional network and compute should be acceptable. +* Validator rewards should not be reduced. + +### Design before NEP-509 + +The current high-level chunk production flow, excluding details and edge cases, is as follows: + +* Block producer at height `H`, `BP(H)`, produces block `B(H)` with chunks accessible to it and distributes it. +* Chunk producer for shard `S` at height `H+1`, `CP(S, H+1)`, produces chunk `C(S, H+1)` based on `B(H)` and distributes it. +* `BP(H+1)` collects all chunks at height `H+1` until certain timeout is reached. +* `BP(H+1)` produces block `B(H+1)` with chunks `C(*, H+1)` accessible to it and distributes it. + +And the flow goes on for heights H+1, H+2, etc. The "induction base" is at genesis height, where genesis block with default chunks is accessible to everyone, so chunk producers can start right away from genesis height + 1. + +One can observe that there is no "chunk validation" step here. In fact, validity of chunks is implicitly guaranteed by **requirement for all block producers to track all shards**. +To achieve phase 2 of sharding, we want to drop this requirement. For that, we propose the following changes to the flow: + +### Design after NEP-509 + +* Chunk producer, in addition to producing a chunk, produces new `ChunkStateWitness` message. The `ChunkStateWitness` contains data which is enough to prove validity of the chunk's header that is being produced. + * `ChunkStateWitness` proves to anyone, including those who track only block data and no shards, that this chunk header is correct. + * `ChunkStateWitness` is not part of the chunk itself; it is distributed separately and is considered transient data. +* The chunk producer distributes the `ChunkStateWitness` to a subset of **chunk validators** which are assigned for this shard. This is in addition to, and independent of, the existing chunk distribution logic (implemented by `ShardsManager`) today. + * Chunk Validator selection and assignment are described below. +* A chunk validator, upon receiving a `ChunkStateWitness`, validates the state witness and determines if the chunk header is indeed correctly produced. If so, it sends a `ChunkEndorsement` to the current block producer. +* As the existing logic is today, the block producer for this block waits until either all chunks are ready, or a timeout occurs, and then proposes a block containing whatever chunks are ready. Now, the notion of readiness here is expanded to also having more than 2/3 of chunk endorsements by stake. + * This means that if a chunk does not receive enough chunk endorsements by the timeout, it will not be included in the block. In other words, the block only contains chunks for which there is already a consensus of validity. **This is the key reason why we will no longer need fraud proofs / tracking all shards**. + * The 2/3 fraction has the denominator being the total stake assigned to validate this shard, *not* the total stake of all validators. +* The block producer, when producing the block, additionally includes the chunk endorsements (at least 2/3 needed for each chunk) in the block's body. The validity of the block is expanded to also having valid 2/3 chunk endorsements by stake for each chunk included in the block. + * If a block fails validation because of not having the required chunk endorsements, it is considered a block validation failure for the purpose of Doomslug consensus, just like any other block validation failure. In other words, nodes will not apply the block on top of their blockchain, and (block) validators will not endorse the block. + +So the high-level specification can be described as the list of changes in the validator roles and responsibilities: + +* Block producers: + * (Same as today) Produce blocks, (new) including waiting for chunk endorsements + * (Same as today) Maintain chunk parts (i.e. participates in data availability based on Reed-Solomon erasure encoding) + * (New) No longer require tracking any shard + * (Same as today) Should have high barrier of entry (required stake) for security reasons, to make block double signing harder. +* Chunk producers: + * (Same as today) Produce chunks + * (New) Produces and distributes state witnesses to chunk validators + * (Same as today) Must track the shard it produces the chunk for +* Block validators: + * (Same as today) Validate blocks, (new) including verifying chunk endorsements + * (Same as today) Vote for blocks with endorsement or skip messages + * (New) No longer require tracking any shard + * (Same as today) Must collectively have a majority of all the validator stake, for security reasons. + * (Same as today) Should have high barrier of entry to keep `BlockHeader` size low, because it is proportional to the total byte size of block validator signatures; +* (New) Chunk validators: + * Validate state witnesses and sends chunk endorsements to block producers + * Do not require tracking any shard + * Must collectively have a majority of all the validator stake, to ensure the security of chunk validation. + +See the Validator Structure Change section below for more details. + +### Out of scope + +* Resharding support. +* Data size optimizations such as compression, for both chunk data and state witnesses, except basic optimizations that are practically necessary. +* Separation of consensus and execution, where consensus runs independently from execution, and validators asynchronously perform state transitions after the transactions are proposed on the consensus layer, for the purpose of amortizing the computation and network transfer time. +* ZK integration. +* Underlying data structure change (e.g. verkle tree). + +## Reference Implementation + +Here we carefully describe new structures and logic introduced, without going into too much technical details. + +### Validator Structure Change + +#### Roles + +Currently, there are two different types of validators. Their responsibilities are defined as in the following pseudocode: + +```python +if index(validator) < 100: + roles(validator).append("block producer") +roles(validator).append("chunk producer") +``` + +The validators are ordered by non-increasing stake in the considered epoch. Here and below by "block production" we mean both production and validation. + +With stateless validation, this structure must change for several reasons: + +* Chunk production is the most resource consuming activity. +* *Only* chunk production needs state in memory while other responsibilities can be completed via acquiring state witness +* Chunk production does not have to be performed by all validators. + +Hence, to make transition seamless, we change the role of nodes out of top 100 to only validate chunks: + +```python +if index(validator) < 100: + roles(validator).append("chunk producer") + roles(validator).append("block producer") +roles(validator).append("chunk validator") +``` + +The more stake validator has, the more **heavy** work it will get assigned. We expect that validators with higher stakes have more powerful hardware. +With stateless validation, relative heaviness of the work changes. Comparing to the current order "block production" > "chunk production", the new order is "chunk production" > "block production" > "chunk validation". + +Shards are equally split among chunk producers: as in Mainnet on 12 Jun 2024 we have 6 shards, each shard would have ~16 chunk producers assigned. + +In the future, with increase in number of shards, we can generalise the assignment by saying that each shard should have `X` chunk producers assigned, if we have at least `X * S` validators. In such case, pseudocode for the role assignment would look as follows: + +```python +if index(validator) < X * S: + roles(validator).append("chunk producer") +if index(validator) < 100: + roles(validator).append("block producer") +roles(validator).append("chunk validator") +``` + +#### Rewards + +Reward for each validator is defined as `total_epoch_reward * validator_relative_stake * work_quality_ratio`, where: + +* `total_epoch_reward` is selected so that total inflation of the token is 5% per annum; +* `validator_relative_stake = validator_stake / total_epoch_stake`; +* `work_quality_ratio` is the measure of the work quality from 0 to 1. + +So, the actual reward never exceeds total reward, and when everyone does perfect work, they are equal. +For the context of the NEP, it is enough to assume that `work_quality_ratio = avg_{role}({role}_quality_ratio)`. +So, if node is both a block and chunk producer, we compute quality for each role separately and then take average of them. + +When epoch is finalized, all block headers in it uniquely determine who was expected to produce each block and chunk. +Thus, if we define quality ratio for block producer as `produced_blocks/expected_blocks`, everyone is able to compute it. +Similarly, `produced_chunks/expected_chunks` is a quality for chunk producer. +It is more accurate to say `included_chunks/expected_chunks`, because inclusion of chunk in block is a final decision of a block producer which defines success here. + +Ideally, we could compute quality for chunk validator as `produced_endorsements/expected_endorsements`. Unfortunately, we won't do it in Stage 0 because: + +* Mask of endorsements is not part of the block header, and it would be a significant change; +* Block producer doesn't have to wait for all endorsements to be collected, so it could be unfair to say that endorsement was not produced if block producer just went ahead. + +So for now we decided to compute quality for chunk validator as ratio of `included_chunks/expected_chunks`, where we iterate over chunks which node was expected to validate. +It has clear drawbacks though: + +* chunk validators are not incentivized to validate the chunks, given they will be rewarded the same in either case; +* if chunks are not produced at all, chunk validators will also be impacted. + +We plan to address them in the future releases. + +#### Kickouts + +In addition to that, if node performance is too poor, we want a mechanism to kick it out of the validator list, to ensure healthy protocol performance and validator rotation. +Currently, we have a threshold for each role, and if for some role the same `{role}_quality_ratio` is lower than threshold, the node is kicked out. + +If we write this in pseudocode, + +```python +if validator is block producer and block_producer_quality_ratio < 0.8: + kick out validator +if validator is chunk producer and chunk_producer_quality_ratio < 0.8: + kick out validator +``` + +For chunk validator, we apply absolutely the same formula. However, because: + +* the formula doesn't count endorsements explicitly +* for chunk producers it kind of just makes chunk production condition stronger without adding value + +we apply it to nodes which **only validate chunks**. So, we add this line: + +```python +if validator is only chunk validator and chunk_validator_quality_ratio < 0.8: + kick out validator +``` + +As we pointed out above, current formula `chunk_validator_quality_ratio` is problematic. +Here it brings even a bigger issue: if chunk producers don't produce chunks, chunk validators will be kicked out as well, which impacts network stability. +This is another reason to come up with the better formula. + +#### Shard assignment + +As chunk producer becomes the most important role, we need to ensure that every epoch has significant amount of healthy chunk producers. +This is a **significant difference** with current logic, where chunk-only producers generally have low stake and their performance doesn't impact overall performance. + +The most challenging part of becoming a chunk producer for a shard is to download most recent shard state within previous epoch. This is called "state sync". +Unfortunately, as of now, state sync is centralised on published snapshots, which is a major point of failure, until we don't have decentralised state sync. + +Because of that, we make additional change: if node was a chunk producer for some shard in the previous epoch, and it is a chunk producer for current epoch, it will be assigned to the same shard. +This way, we minimise number of required state syncs at each epoch. + +The exact algorithm needs a thorough description to satisfy different edge cases, so we will just leave a link to full explanation: https://github.com/near/nearcore/issues/11213#issuecomment-2111234940. + +### ChunkStateWitness + +The full structure is described [here](https://github.com/near/nearcore/blob/b8f08d9ded5b7cbae9d73883785902b76e4626fc/core/primitives/src/stateless_validation.rs#L247). +Let's construct it sequentially together with explaining why every field is needed. Start from simple data: + +```rust +pub struct ChunkStateWitness { + pub chunk_producer: AccountId, + pub epoch_id: EpochId, + /// The chunk header which this witness is proving. + pub chunk_header: ShardChunkHeader, +} +``` + +What is needed to prove `ShardChunkHeader`? + +The key function we have in codebase is [validate_chunk_with_chunk_extra_and_receipts_root](https://github.com/near/nearcore/blob/c2d80742187d9b8fc1bb672f16e3d5c144722742/chain/chain/src/validate.rs#L141). +The main arguments there are `prev_chunk_extra: &ChunkExtra` which stands for execution result of previous chunk, and `chunk_header`. +The most important field for `ShardChunkHeader` is `prev_state_root` - consider latest implementation `ShardChunkHeaderInnerV3`. It stands for state root resulted from updating shard for the previous block, which means applying previous chunk if there is no missing chunks. +So, chunk validator needs some way to run transactions and receipts from the previous chunk. Let's call it a "main state transition" and add two more fields to state witness: + +```rust + /// The base state and post-state-root of the main transition where we + /// apply transactions and receipts. Corresponds to the state transition + /// that takes us from the pre-state-root of the last new chunk of this + /// shard to the post-state-root of that same chunk. + pub main_state_transition: ChunkStateTransition, + /// The transactions to apply. These must be in the correct order in which + /// they are to be applied. + pub transactions: Vec, +``` + +where + +```rust +/// Represents the base state and the expected post-state-root of a chunk's state +/// transition. The actual state transition itself is not included here. +pub struct ChunkStateTransition { + /// The block that contains the chunk; this identifies which part of the + /// state transition we're talking about. + pub block_hash: CryptoHash, + /// The partial state before the state transition. This includes whatever + /// initial state that is necessary to compute the state transition for this + /// chunk. It is a list of Merkle tree nodes. + pub base_state: PartialState, + /// The expected final state root after applying the state transition. + pub post_state_root: CryptoHash, +} +``` + +Fine, but where do we take the receipts? + +Receipts are internal messages, resulting from transaction execution, sent between shards, and **by default** they are not signed by anyone. + +However, each receipt is an execution outcome of some transaction or other parent receipt, executed in some previous chunk. +For every chunk, we conveniently store `prev_outgoing_receipts_root` which is a Merkle hash of all receipts sent to other shards resulting by execution of this chunk. So, for every receipt, there is a proof of its generation in some parent chunk. If there are no missing chunk, then it's enough to consider chunks from previous block. + +So we add another field: + +```rust + /// Non-strict superset of the receipts that must be applied, along with + /// information that allows these receipts to be verifiable against the + /// blockchain history. + pub source_receipt_proofs: HashMap, +``` + +What about missing chunks though? + +Unfortunately, production and inclusion of any chunk **cannot be guaranteed**: + +* chunk producer may go offline; +* chunk validators may not generate 2/3 endorsements; +* block producer may not receive enough information to include chunk. + +Let's handle this case as well. +First, each chunk producer needs not just to prove main state transition, but also all state transitions for latest missing chunks: + +```rust + /// For each missing chunk after the last new chunk of the shard, we need + /// to carry out an implicit state transition. This is technically needed + /// to handle validator rewards distribution. This list contains one for each + /// such chunk, in forward chronological order. + /// + /// After these are applied as well, we should arrive at the pre-state-root + /// of the chunk that this witness is for. + pub implicit_transitions: Vec, +``` + +Then, while our shard was missing chunks, other shards could still produce chunks, which could generate receipts targeting our shards. So, we need to extend `source_receipt_proofs`. +Field structure doesn't change, but we need to carefully pick range of set of source chunks, so different subsets will cover all source receipts without intersection. + +Let's say B2 is the block that contains the last new chunk of shard S before chunk which state transition we execute, and B1 is the block that contains the last new chunk of shard S before B2. +Then, we will define set of blocks B as the contiguous subsequence of blocks B1 (EXCLUSIVE) to B2 (inclusive) in this chunk's chain (i.e. the linear chain that this chunk's parent block is on). Lastly, source chunks are all chunks included in blocks from B. + +The last caveat is **new** transactions introduced by chunk with `chunk_header`. As chunk header introduces `tx_root` for them, we need to check validity of this field as well. +If we don't do it, malicious chunk producer can include invalid transaction, and if it gets its chunk endorsed, nodes which track the shard must either accept invalid transaction or refuse to process chunk, but the latter means that shard will get stuck. + +To validate new `tx_root`, we also need Merkle partial state to validate sender' balances, access keys, nonces, etc., which leads to two last fields to be added: + +```rust + pub new_transactions: Vec, + pub new_transactions_validation_state: PartialState, +``` + +The logic to produce `ChunkStateWitness` is [here](https://github.com/near/nearcore/blob/b8f08d9ded5b7cbae9d73883785902b76e4626fc/chain/client/src/stateless_validation/state_witness_producer.rs#L79). +Itself, it requires some minor changes to the logic of applying chunks, related to generating `ChunkStateTransition::base_state`. +It is controlled by [this line](https://github.com/near/nearcore/blob/dc03a34101f77a17210873c4b5be28ef23443864/chain/chain/src/runtime/mod.rs#L977), which causes all nodes read during applying chunk to be put inside `TrieRecorder`. +After applying chunk, its contents are saved to `StateTransitionData`. + +The validation logic is [here](https://github.com/near/nearcore/blob/b8f08d9ded5b7cbae9d73883785902b76e4626fc/chain/client/src/stateless_validation/chunk_validator/mod.rs#L85). +First, it performs all validation steps for which access to `ChainStore` is required, `pre_validate_chunk_state_witness` is responsible for this. It is done separately because `ChainStore` is owned by a single thread. +Then, it spawns a thread which runs computation-heavy `validate_chunk_state_witness` which main purpose is to apply chunk based on received state transitions and verify that execution results in chunk header are correct. +If validation is successful, `ChunkEndorsement` is sent. + +### ChunkEndorsement + +It is basically a triple of `(ChunkHash, AccountId, Signature)`. +Receiving this message means that specific chunk validator account endorsed chunk with specific chunk hash. +Ideally chunk validator would send chunk endorsement to just the next block producer at the same height for which chunk was produced. +However, block at that height can be skipped and block producers at heights h+1, h+2, ... will have to pick up the chunk. +To address that, we send `ChunkEndorsement` to all block producers at heights from `h` to `h+d-1`. We pick `d=5` as more than 5 skipped blocks in a row are very unlikely to occur. + +On block producer side, chunk endorsements are collected and stored in `ChunkEndorsementTracker`. +Small **caveat** is that *sometimes* chunk endorsement may be received before chunk header which is required to understand that sender is indeed a validator of the chunk. +Such endorsements are stored as *pending*. +When chunk header is received, all pending endorsements are checked for validity and marked as *validated*. +All endorsements received after that are validated right away. + +Finally, when block producer attempts to produce a block, in addition to checking chunk existence, it also checks that it has 2/3 endorsement stake for that chunk hash. +To make chunk inclusion verifiable, we introduce [another version](https://github.com/near/nearcore/blob/cf2caa3513f58da8be758d1c93b0900ffd5d51d2/core/primitives/src/block_body.rs#L30) of block body `BlockBodyV2` which has new field `chunk_endorsements`. +It is basically a `Vec>>` where element with indices `(s, i)` contains signature of i-th chunk validator for shard s if it was included and None otherwise. +Lastly, we add condition to block validation, such that if chunk `s` was included in the block, then block body must contain 2/3 endorsements for that shard. + +This logic is triggered in `ChunkInclusionTracker` by methods [get_chunk_headers_ready_for_inclusion](https://github.com/near/nearcore/blob/6184e5dac45afb10a920cfa5532ce6b3c088deee/chain/client/src/chunk_inclusion_tracker.rs#L146) and couple similar ones. Number of ready chunks is returned by [num_chunk_headers_ready_for_inclusion](https://github.com/near/nearcore/blob/6184e5dac45afb10a920cfa5532ce6b3c088deee/chain/client/src/chunk_inclusion_tracker.rs#L178). + +### Chunk validators selection + +Chunk validators will be randomly assigned to validate shards, for each block (or as we may decide later, for multiple blocks in a row, if required for performance reasons). A chunk validator may be assigned multiple shards at once, if it has sufficient stake. + +Each chunk validator's stake is divided into "mandates". There are full and partial mandates. The number of mandates per shard is a fixed parameter and the amount of stake per mandate is dynamically computed based on this parameter and the actual stake distribution; any remaining amount smaller than a full mandate is a partial mandate. A chunk validator therefore has zero or more full mandates plus up to one partial mandate. The list of full mandates and the list of partial mandates are then separately shuffled and partitioned equally (as in, no more than one mandate in difference between any two shards) across the shards. Any mandate assigned to a shard means that the chunk validator who owns the mandate is assigned to validate that shard. Because a chunk validator may have multiple mandates, it may be assigned multiple shards to validate. + +For Stage 0, we select **target amount of mandates per shard** to 68, which was a [result of the latest research](https://near.zulipchat.com/#narrow/stream/407237-core.2Fstateless-validation/topic/validator.20seat.20assignment/near/435252304). +With this number of mandates per shard and 6 shards, we predict the protocol to be secure for 40 years at 90% confidence. +Based on target number of mandates and total chunk validators stake, [here](https://github.com/near/nearcore/blob/696190b150dd2347f9f042fa99b844b67c8001d8/core/primitives/src/validator_mandates/mod.rs#L76) we compute price of a single full mandate for each new epoch using binary search. +All the mandates are stored in new version of `EpochInfo` `EpochInfoV4` in [validator_mandates](https://github.com/near/nearcore/blob/164b7a367623eb651914eeaf1cbf3579c107c22d/core/primitives/src/epoch_manager.rs#L775) field. + +After that, for each height in the epoch, [EpochInfo::sample_chunk_validators](https://github.com/near/nearcore/blob/164b7a367623eb651914eeaf1cbf3579c107c22d/core/primitives/src/epoch_manager.rs#L1224) is called to return `ChunkValidatorStakeAssignment`. It is `Vec>` where s-th element corresponds to s-th shard in the epoch, contains ids of all chunk validator for that height and shard, alongside with its total mandate stake assigned to that shard. +`sample_chunk_validators` basically just shuffles `validator_mandates` among shards using height-specific seed. If there are no more than 1/3 malicious validators, then by Chernoff bound the probability that at least one shard is corrupted is small enough. **This is a reason why we can split validators among shards and still rely on basic consensus assumption**. + +This way, everyone tracking block headers can compute chunk validator assignment for each height and shard. + +### Size limits + +`ChunkStateWitness` is relatively large message. Given large number of receivers as well, its size must be strictly limited. +If `ChunkStateWitness` for some state transition gets so uncontrollably large that it never can be handled by majority of validators, then its shard gets stuck. + +We try to limit the size of the `ChunkStateWitness` to 16 MiB. All the limits are described [in this section](https://github.com/near/nearcore/blob/b34db1e2281fbfe1d99a36b4a90df3fc7f5d00cb/docs/misc/state_witness_size_limits.md). +Additionally, we have limit on currently stored partial state witnesses and chunk endorsements, because malicious chunk validators can spam these as well. + +## State witness size limits + +A number of new limits will be introduced in order to keep the size of `ChunkStateWitness` reasonable. +`ChunkStateWitness` contains all the incoming transactions and receipts that will be processed during chunk application and in theory a single receipt could be tens of megabatytes in size. Distributing a `ChunkStateWitness` this large to all chunk validators would be troublesome, so we limit the size and number of transactions, receipts, etc. The limits aim to keep the total uncompressed size of `ChunkStateWitness` under 16 MiB. + +There are two types of size limits: + +* Hard limit - The size must be below this limit, anything else is considered invalid. This is usually used in the context of having limits for a single item. +* Soft limit - Things are added until the limit is exceeded, after that things stop being added. The last added thing is allowed to slightly exceed the limit. This is used in the context of having limits for a list of items. + +The limits are: + +* `max_transaction_size - 1.5 MiB` + * All transactions must be below 1.5 MiB, otherwise they'll be considered invalid and rejected. +* Previously was 4 MiB, now reduced to 1.5 MiB +* `max_receipt_size - 4 MiB`: + * All receipts must be below 4 MiB, otherwise they'll be considered invalid and rejected. + * Previously there was no limit on receipt size. Set to 4 MiB, might be reduced to 1.5 MiB in the future to match the transaction limit. +* `combined_transactions_size_limit - 4 MiB` + * Hard limit on total size of transactions from this and previous chunk. `ChunkStateWitness` contains transactions from two chunks, this limit applies to the sum of their sizes. +* `new_transactions_validation_state_size_soft_limit - 500 KiB` + * Validating new transactions generates storage proof (recorded trie nodes), which has to be limited. Once transaction validation generates more storage proof than this limit, the chunk producer stops adding new transactions to the chunk. +* `per_receipt_storage_proof_size_limit - 4 MB` + * Executing a receipt generates storage proof. A single receipt is allowed to generate at most 4 MB of storage proof. This is a hard limit, receipts which generate more than that will fail. +* `main_storage_proof_size_soft_limit - 3 MB` + * This is a limit on the total size of storage proof generated by receipts in one chunk. Once receipts generate more storage proof than this limit, the chunk producer stops processing receipts and moves the rest to the delayed queue. + * It's a soft limit, which means that the total size of storage proof could reach 7 MB (2.99MB + one receipt which generates 4MB of storage proof) + * Due to implementation details it's hard to find the exact amount of storage proof generated by a receipt, so an upper bound estimation is used instead. This upper bound assumes that every removal generates additional 2000 bytes of storage proof, so receipts which perform a lot of trie removals might be limited more than theoretically applicable. +* `outgoing_receipts_usual_size_limit - 100 KiB` + * Limit on the size of outgoing receipts to another shard. Needed to keep the size of `source_receipt_proofs` small. + * On most block heights a shard isn't allowed to send receipts larger than 100 KiB to another shard. +* `outgoing_receipts_big_size_limit - 4.5 MiB` + * On every block height there's one special "allowed shard" which is allowed to send larger receipts, up to 4.5 MiB in total. + * A receiving shard will receive receipts from `num_shards - 1` shards using the usual limit and one shard using the big limit. + * The "allowed shard" is the same shard as in cross-shard congestion control. It's chosen in a round-robin fashion, at height 1 the special shard is 0, at height 2 it's 1 and so on. + +In total that gives 4 MiB + 500 KiB + 7MB + 5*100 KiB + 4.5 MiB ~= 16 MiB of maximum witness size. Possibly a little more on missing chunks. + +### New limits breaking contracts + +The new limits will break some existing contracts (for example, all transactions larger than 1.5 MiB). This is sad, but it's necessary. Stateless validation uses much more network bandwidth than the previous approach, as it has to send over all states on each chunk application. Because network bandwidth is limited, stateless validation +can't support some operations that were allowed in the previous design. + +In the past year (31,536,000 blocks) there were only 679 transactions bigger than 1.5MiB, sent between 164 unique (sender -> receiver) pairs. +Only 0.002% of blocks contain such transactions, so the hope is that the breakage will be minimal. Contracts generally shouldn't require more than 1.5MiB of WASM. + +The full list of transactions from the past year which would fail with the new limit is available here: https://gist.github.com/jancionear/4cf373aff5301a5905a5f685ff24ed6f +Contract developers can take a look at this list and see if their contract will be affected. + +### Validating the limits + +Chunk validators have to verify that chunk producer respected all of the limits while producing the chunk. This means that validators also have to keep track of recorded storage proof by recording all trie accesses and they have to enforce the limits. +If it turns out that some limits weren't respected, the validators will generate a different result of chunk application and they won't endorse the chunk. + +### Missing chunks + +When a shard is missing some chunks, the following chunk on that shard will receive receipts from multiple blocks. This could lead to large `source_receipt_proofs` so a mechanism is added to reduce the impact. If there are two or more missing chunks in a row, +the shard is considered fully congested and no new receipts will be sent to it (unless it's the `allowed_shard` to avoid deadlocks). + +## ChunkStateWitness distribution + +For chunk production, the chunk producer is required to distribute the chunk state witness to all the chunk validators. The chunk validators then validate the chunk and send the chunk endorsement to the block producer. Chunk state witness distribution is on a latency critical path. + +As we saw in the section above, the maximum size of the state witness can be ~16 MiB. If the chunk producer were to send the chunk state witness to all the chunk validators it would add a massive bandwidth requirement for the chunk producer. To ease and distribute the network requirements across all the chunk producers, we have a distribution mechanism similar to what we have for chunks in the shards manager. We divide the chunk state witness into a number of parts, and let the chunk validators distribute the parts among themselves, and later reconstruct the chunk state witness. + +### Distribution mechanism + +A chunk producer divides the state witness into a set of `N` parts where `N` is the number of chunk validators. The parts or partial witnesses are represented as [PartialEncodedStateWitness](https://github.com/near/nearcore/blob/66d3b134343d9f35f6e0b437ebbdbef3e4aa1de3/core/primitives/src/stateless_validation.rs#L40). Each chunk validator is the owner of one part. The chunk producer uses the [PartialEncodedStateWitnessMessage](https://github.com/near/nearcore/blob/66d3b134343d9f35f6e0b437ebbdbef3e4aa1de3/chain/network/src/state_witness.rs#L11) to send each part to their respective owners. The chunk validator part owners, on receiving the `PartialEncodedStateWitnessMessage`, forward this part to all other chunk validators via the [PartialEncodedStateWitnessForwardMessage](https://github.com/near/nearcore/blob/66d3b134343d9f35f6e0b437ebbdbef3e4aa1de3/chain/network/src/state_witness.rs#L15). Each validator then uses the partial witnesses received to reconstruct the full chunk state witness. + +We have a separate [PartialWitnessActor](https://github.com/near/nearcore/blob/66d3b134343d9f35f6e0b437ebbdbef3e4aa1de3/chain/client/src/stateless_validation/partial_witness/partial_witness_actor.rs#L32) actor/module that is responsible for dividing the state witness into parts, distributing the parts, handling both partial encoded state witness message and the forward message, validating and storing the parts, and reconstructing the state witness from the parts and sending is to the chunk validation module. + +### Building redundancy using Reed Solomon Erasure encoding + +During the distribution mechanism, it's possible that some of the chunk validators are malicious, offline, or have a high network latency. Since chunk witness distribution is on the critical path for block production, we safeguard the distribution mechanism by building in redundancy using the Reed Solomon Erasure encoding. + +With Reed Solomon Erasure encoding, we can divde the chunk state witness into `N` total parts with `D` number of data parts. We can reconstruct the whole state witness as long as we have `D` of the `N` parts. The ratio of data parts `r = D/N` is something we can play around with. + +While reducing `r`, i.e. reducing the number of data parts required to reconstruct the state witness does allow for a more robust distribution mechanism, it comes with the cost of bloating the overall size of parts we need to distribute. If `S` is the size of the state witness, after reed solomon encoding, the total size `S'` of all parts becomes `S' = S/r` or `S' = S * N / D`. + +For the first release of stateless validation, we've kept the ratio as `0.6` representing that ~2/3rd of all chunk validators need to be online for chunk state witness distribution mechanism to work smoothly. + +One thing to note here is that the redundancy and upkeep requirement of 2/3rd is the *number* of chunk validators and not the *stake* of chunk validators. + +### PartialEncodedStateWitness structure + +The partial encoded state witness has the following fields: + +* `(epoch_id, shard_id, height_created)` : These are the three fields that together uniquely determine the chunk associated with the partial witness. Since the chunk and chunk header distribution mechanism is independent of the partial witness, we rely on this triplet to uniquely identify which chunk is a part associated with. +* `part_ord` : The index or id of the part in the array of partial witnesses. +* `part` : The data associated with the part +* `encoded_length` : The total length of the state witness. This is required in the reed solomon decoding process to reconstruct the state witness. +* `signature` : Each part is signed by the chunk producer. This way the validity of the partial witness can be verified by the chunk validators receiving the parts. + +The `PartialEncodedStateWitnessTracker` module that is responsible for the storage and decoding of partial witnesses. This module has a LRU cache to store all the partial witnesses with `(epoch_id, shard_id, height_created)` triplet as the key. We reconstruct the state witness as soon as we have `D` of the `N` parts as forward the state witness to the validation module. + +### Network tradeoffs + +To get a sense of network requirements for validators with an without partial state witness distribution mechanism, we can do some quick back of the envelop calculations. Let `N` but the number of chunk validators, `S` be the size of the chunk state witness, `r` be the ratio of data parts to total parts for Reed Solomon Erasure encoding. + +Without the partial state witness distribution, each chunk producer would have to send the state witness to all chunk validators, which would require a bandwidth `B` of `B = N * S`. For the worst case of ~16 validators and ~16 MiB of state witness size, this can be a burst requirement of 2 Gbps. + +Partial state witness distribution takes this load off the chunk producer and distributes it evenly among all the chunk validators. However, we get an additional factor of `1/r` of extra data being transferred for redundancy. Each partial witness has a size of `P = S' / N` or `P = S / r / N`. The chunk producer and validators needs a bandwidth `B` of `B = P * N` or `B = S / r` to forward its owned part to all `N` chunk validators. For worst case of ~16 MiB of state witness size and encoding ratio of `0.6`, this works out to be ~214 Mbps, which is much more reasonable. + +### Future work + +In the Reed Solomon Erasure encoding section we discussed that the chunk state distribution mechanism relies on 2/3rd of the *number* of chunk validators being available/non-malicious and not 2/3rd of the *total stake* of the chunk validators. This can cause a potential issue where it's possible for more than 1/3rd of the chunk validators with small enough stake to be unavailable and cause the chunk production to stall. In the future we would like to address this problem. + +## Validator Role Change + +Currently, there are two different types of validators and their responsibilities are as follows: +| | Top ~50% validators | Remaining validatiors (Chunk only producers) | +|-----|:-----:|:----:| +| block production | Y | N | +| chunk production | Y | Y | +| block validation | Y | N | + +### Protocol upgrade + +The good property of the approach taken is that protocol upgrade happens almost seamlessly. + +If (main transition, implicit transitions) fully belong to the protocol version before upgrade to stateless validation, chunk validator endorsements are not distributed, chunk validators are not sampled, but the protocol is safe because of all-shards tracking, as we described in "High-level flow". + +If at least some transition belongs to the protocol version after upgrade, chunk header height also belongs to epoch after upgrade, so it has chunk validators assigned and requirement of 2/3 endorsements is enabled. + +The minor accuracy needed is that generating and saving of state transition proofs have to be saved one epoch in advance, so we won't have to re-apply chunks to generate proofs once stateless validation is enabled. But new epoch protocol version is defined by finalization of **previous previous epoch**, so this is fine. + +It also assumes that each epoch has at least two chunks, but if this is not the case, the chain is having a major disruption which never happened before. + +## Security Implications + +Block validators no longer required to track any shard which means they don't have to validate state transitions proposed by the chunks in the block. Instead they trust chunk endorsements included in the block to certify the validity of the state transitions. +This makes chunk validator selection algorithm correctness critical for the security of the whole protocol, which is probabilistic by nature unlike the current more strict 2/3 of non-malicious validators requirement. + +It is also worth mentioning that large state witness size makes witness distribution slow which could result in a missing chunk because the block producer won't get chunk endorsements in time. This design tries to address that by meticulously limiting max witness size (see [this doc](https://github.com/near/nearcore/blob/master/docs/misc/state_witness_size_limits.md)). + + +## Alternatives + +The only real alternative that was considered is the original nightshade proposal. The full overview of the differences can be found in the revised nightshade whitepaper at https://near.org/papers/nightshade. + +## Future possibilities + +* Integration with ZK allowing to get rid of large state witness distribution. If we treat state witness as a proof and ZK-ify it, anyone can validate that state witness indeed proves the new chunk header with much lower effort. Complexity of actual proof generation and computation indeed increases, but it can be distributed among chunk producers, and we can have separate concept of finality while allowing generic users to query optimistic chunks. +* Integration with resharding to further increase the number of shards and the total throughput. +* The sharding of non-validating nodes and services. There are a number of services that may benefit from tracking only a subset of shards. Some examples include the RPC, archival and read-RPC nodes. + +## Consequences + +### Positive + +* The validator nodes will need to track at most one shard. +* The state will be held in memory making the chunk application much faster. +* The disk space hardware requirement will decrease. The top 100 nodes will need to store at most 2 shards at a time and the remaining nodes will not need to store any shards. +* Thanks to the above, in the future, it will be possible to reduce the gas costs and by doing so increase the throughput of the system. + +### Neutral + +* The current approach to resharding will need to be revised to support generating state witness. +* The security assumptions will change. The responsibility will be moved from block producers to chunk validators and the security will become probabilistic. + +### Negative + +* The network bandwidth and memory hardware requirements will increase. + * The top 100 validators will need to store up to 2 shards in memory and participate in state witness distribution. + * The remaining validators will need to participate in state witness distribution. +* Additional limits will be put on the size of transactions, receipts and, more generally, cross shard communication. +* The dependency on cloud state sync will increase the centralization of the blockchain. This will be resolved separately by the decentralized state sync. + +### Backwards Compatibility + +[All NEPs that introduce backwards incompatibilities must include a section describing these incompatibilities and their severity. Author must explain a proposes to deal with these incompatibilities. Submissions without a sufficient backwards compatibility treatise may be rejected outright.] + +## Unresolved Issues (Optional) + +[Explain any issues that warrant further discussion. Considerations + +* What parts of the design do you expect to resolve through the NEP process before this gets merged? +* What parts of the design do you expect to resolve through the implementation of this feature before stabilization? +* What related issues do you consider out of scope for this NEP that could be addressed in the future independently of the solution that comes out of this NEP?] + +## Changelog + +[The changelog section provides historical context for how the NEP developed over time. Initial NEP submission should start with version 1.0.0, and all subsequent NEP extensions must follow [Semantic Versioning](https://semver.org/). Every version should have the benefits and concerns raised during the review. The author does not need to fill out this section for the initial draft. Instead, the assigned reviewers (Subject Matter Experts) should create the first version during the first technical review. After the final public call, the author should then finalize the last version of the decision context.] + +### 1.0.0 - Initial Version + +> Placeholder for the context about when and who approved this NEP version. + +#### Benefits + +> List of benefits filled by the Subject Matter Experts while reviewing this version: + +* Benefit 1 +* Benefit 2 + +#### Concerns + +> Template for Subject Matter Experts review for this version: +> Status: New | Ongoing | Resolved + +| # | Concern | Resolution | Status | +| --: | :------ | :--------- | -----: | +| 1 | | | | +| 2 | | | | + +## Copyright + +Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/).